%global _empty_manifest_terminate_build 0
Name: python-rss-parser
Version: 1.0.0
Release: 1
Summary: Typed pythonic RSS parser
License: GPL-3.0
URL: https://dhvcc.github.io/rss-parser
Source0: https://mirrors.aliyun.com/pypi/web/packages/d1/bf/662e818701a03cc46c4557576c72ac46c9681bb4e4e04c8874b583f92e86/rss_parser-1.0.0.tar.gz
BuildArch: noarch
Requires: python3-pydantic
Requires: python3-pytest
Requires: python3-xmltodict
%description
# Rss parser
[![Downloads](https://pepy.tech/badge/rss-parser)](https://pepy.tech/project/rss-parser)
[![Downloads](https://pepy.tech/badge/rss-parser/month)](https://pepy.tech/project/rss-parser/month)
[![Downloads](https://pepy.tech/badge/rss-parser/week)](https://pepy.tech/project/rss-parser/week)
[![PyPI version](https://img.shields.io/pypi/v/rss-parser)](https://pypi.org/project/rss-parser)
[![Python versions](https://img.shields.io/pypi/pyversions/rss-parser)](https://pypi.org/project/rss-parser)
[![Wheel status](https://img.shields.io/pypi/wheel/rss-parser)](https://pypi.org/project/rss-parser)
[![License](https://img.shields.io/pypi/l/rss-parser?color=success)](https://github.com/dhvcc/rss-parser/blob/master/LICENSE)
[![GitHub Pages](https://badgen.net/github/status/dhvcc/rss-parser/gh-pages?label=docs)](https://dhvcc.github.io/rss-parser#documentation)
![CI](https://github.com/dhvcc/rss-parser/actions/workflows/ci.yml/badge.svg?branch=master)
![PyPi publish](https://github.com/dhvcc/rss-parser/actions/workflows/publish_to_pypi.yml/badge.svg?branch=master)
## About
`rss-parser` is typed python RSS parsing module built using [pydantic](https://github.com/pydantic/pydantic) and [xmltodict](https://github.com/martinblech/xmltodict)
## Installation
```bash
pip install rss-parser
```
or
```bash
git clone https://github.com/dhvcc/rss-parser.git
cd rss-parser
poetry build
pip install dist/*.whl
```
## Usage
### Quickstart
```python
from rss_parser import Parser
from requests import get
rss_url = "https://rss.art19.com/apology-line"
response = get(rss_url)
rss = Parser.parse(response.text)
# Print out rss meta data
print("Language", rss.channel.language)
print("RSS", rss.version)
# Iteratively print feed items
for item in rss.channel.items:
print(item.title)
print(item.description[:50])
# Language en
# RSS 2.0
# Wondery Presents - Flipping The Bird: Elon vs Twitter
#
When Elon Musk posted a video of himself arrivi
# Introducing: The Apology Line
#
If you could call a number and say you’re sorry
```
Here we can see that description is still somehow has
- this is beacause it's placed as [CDATA](https://www.w3resource.com/xml/CDATA-sections.php) like so
```xml
If you could call ...
]]>
```
### Overriding schema
If you want to customize the schema or provide a custom one - use `schema` keyword argument of the parser
```python
from rss_parser.models import XMLBaseModel
from rss_parser.models.rss import RSS
from rss_parser.models.types import Tag
class CustomSchema(RSS, XMLBaseModel):
channel: None = None # Removing previous channel field
custom: Tag[str]
with open("tests/samples/custom.xml") as f:
data = f.read()
rss = Parser.parse(data, schema=CustomSchema)
print("RSS", rss.version)
print("Custom", rss.custom)
# RSS 2.0
# Custom Custom tag data
```
### xmltodict
This library uses [xmltodict](https://github.com/martinblech/xmltodict) to parse XML data. You can see the detailed documentation [here](https://github.com/martinblech/xmltodict#xmltodict)
The basic thing you should know is that your data is processed into dictionaries
For example, this data
```xml
content
```
will result in the following
```python
{
"tag": "content"
}
```
*But*, when handling attributes, the content of the tag will be also a dictionary
```xml
data
```
Turns into
```python
{
"tag": {
"@attr": "1",
"@data-value": "data",
"#text": "content"
}
}
```
### Tag field
This is a generic field that handles tags as raw data or a dictonary returned with attributes
*Although this is a complex class, it forwards most of the methods to it's content attribute, so you don't notice a difference if you're only after the .content value*
Example
```python
from rss_parser.models import XMLBaseModel
class Model(XMLBaseModel):
number: Tag[int]
string: Tag[str]
m = Model(
number=1,
string={'@attr': '1', '#text': 'content'},
)
m.number.content == 1 # Content value is an integer, as per the generic type
m.number.content + 10 == m.number + 10 # But you're still able to use the Tag itself in common operators
m.number.bit_length() == 1 # As it's the case for methods/attributes not found in the Tag itself
type(m.number), type(m.number.content) == (, ) # types are NOT the same, however, the interfaces are very similar most of the time
m.number.attributes == {} # The attributes are empty by default
m.string.attributes == {'attr': '1'} # But are populated when provided. Note that the @ symbol is trimmed from the beggining, however, camelCase is not converted
# Generic argument types are handled by pydantic - let's try to provide a string for a Tag[int] number
m = Model(number='not_a_number', string={'@customAttr': 'v', '#text': 'str tag value'}) # This will lead in the following traceback
# Traceback (most recent call last):
# ...
# pydantic.error_wrappers.ValidationError: 1 validation error for Model
# number -> content
# value is not a valid integer (type=type_error.integer)
```
**If you wish to avoid all of the method/attribute forwarding "magic" - you should use `rss_parser.models.types.TagRaw`**
## Contributing
Pull requests are welcome. For major changes, please open an issue first
to discuss what you would like to change.
Install dependencies with `poetry install` (`pip install poetry`)
`pre-commit` usage is highly recommended. To install hooks run
```bash
poetry run pre-commit install -t=pre-commit -t=pre-push
```
## License
[GPLv3](https://github.com/dhvcc/rss-parser/blob/master/LICENSE)
%package -n python3-rss-parser
Summary: Typed pythonic RSS parser
Provides: python-rss-parser
BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: python3-pip
%description -n python3-rss-parser
# Rss parser
[![Downloads](https://pepy.tech/badge/rss-parser)](https://pepy.tech/project/rss-parser)
[![Downloads](https://pepy.tech/badge/rss-parser/month)](https://pepy.tech/project/rss-parser/month)
[![Downloads](https://pepy.tech/badge/rss-parser/week)](https://pepy.tech/project/rss-parser/week)
[![PyPI version](https://img.shields.io/pypi/v/rss-parser)](https://pypi.org/project/rss-parser)
[![Python versions](https://img.shields.io/pypi/pyversions/rss-parser)](https://pypi.org/project/rss-parser)
[![Wheel status](https://img.shields.io/pypi/wheel/rss-parser)](https://pypi.org/project/rss-parser)
[![License](https://img.shields.io/pypi/l/rss-parser?color=success)](https://github.com/dhvcc/rss-parser/blob/master/LICENSE)
[![GitHub Pages](https://badgen.net/github/status/dhvcc/rss-parser/gh-pages?label=docs)](https://dhvcc.github.io/rss-parser#documentation)
![CI](https://github.com/dhvcc/rss-parser/actions/workflows/ci.yml/badge.svg?branch=master)
![PyPi publish](https://github.com/dhvcc/rss-parser/actions/workflows/publish_to_pypi.yml/badge.svg?branch=master)
## About
`rss-parser` is typed python RSS parsing module built using [pydantic](https://github.com/pydantic/pydantic) and [xmltodict](https://github.com/martinblech/xmltodict)
## Installation
```bash
pip install rss-parser
```
or
```bash
git clone https://github.com/dhvcc/rss-parser.git
cd rss-parser
poetry build
pip install dist/*.whl
```
## Usage
### Quickstart
```python
from rss_parser import Parser
from requests import get
rss_url = "https://rss.art19.com/apology-line"
response = get(rss_url)
rss = Parser.parse(response.text)
# Print out rss meta data
print("Language", rss.channel.language)
print("RSS", rss.version)
# Iteratively print feed items
for item in rss.channel.items:
print(item.title)
print(item.description[:50])
# Language en
# RSS 2.0
# Wondery Presents - Flipping The Bird: Elon vs Twitter
# When Elon Musk posted a video of himself arrivi
# Introducing: The Apology Line
#
If you could call a number and say you’re sorry
```
Here we can see that description is still somehow has
- this is beacause it's placed as [CDATA](https://www.w3resource.com/xml/CDATA-sections.php) like so
```xml
If you could call ...
]]>
```
### Overriding schema
If you want to customize the schema or provide a custom one - use `schema` keyword argument of the parser
```python
from rss_parser.models import XMLBaseModel
from rss_parser.models.rss import RSS
from rss_parser.models.types import Tag
class CustomSchema(RSS, XMLBaseModel):
channel: None = None # Removing previous channel field
custom: Tag[str]
with open("tests/samples/custom.xml") as f:
data = f.read()
rss = Parser.parse(data, schema=CustomSchema)
print("RSS", rss.version)
print("Custom", rss.custom)
# RSS 2.0
# Custom Custom tag data
```
### xmltodict
This library uses [xmltodict](https://github.com/martinblech/xmltodict) to parse XML data. You can see the detailed documentation [here](https://github.com/martinblech/xmltodict#xmltodict)
The basic thing you should know is that your data is processed into dictionaries
For example, this data
```xml
content
```
will result in the following
```python
{
"tag": "content"
}
```
*But*, when handling attributes, the content of the tag will be also a dictionary
```xml
data
```
Turns into
```python
{
"tag": {
"@attr": "1",
"@data-value": "data",
"#text": "content"
}
}
```
### Tag field
This is a generic field that handles tags as raw data or a dictonary returned with attributes
*Although this is a complex class, it forwards most of the methods to it's content attribute, so you don't notice a difference if you're only after the .content value*
Example
```python
from rss_parser.models import XMLBaseModel
class Model(XMLBaseModel):
number: Tag[int]
string: Tag[str]
m = Model(
number=1,
string={'@attr': '1', '#text': 'content'},
)
m.number.content == 1 # Content value is an integer, as per the generic type
m.number.content + 10 == m.number + 10 # But you're still able to use the Tag itself in common operators
m.number.bit_length() == 1 # As it's the case for methods/attributes not found in the Tag itself
type(m.number), type(m.number.content) == (, ) # types are NOT the same, however, the interfaces are very similar most of the time
m.number.attributes == {} # The attributes are empty by default
m.string.attributes == {'attr': '1'} # But are populated when provided. Note that the @ symbol is trimmed from the beggining, however, camelCase is not converted
# Generic argument types are handled by pydantic - let's try to provide a string for a Tag[int] number
m = Model(number='not_a_number', string={'@customAttr': 'v', '#text': 'str tag value'}) # This will lead in the following traceback
# Traceback (most recent call last):
# ...
# pydantic.error_wrappers.ValidationError: 1 validation error for Model
# number -> content
# value is not a valid integer (type=type_error.integer)
```
**If you wish to avoid all of the method/attribute forwarding "magic" - you should use `rss_parser.models.types.TagRaw`**
## Contributing
Pull requests are welcome. For major changes, please open an issue first
to discuss what you would like to change.
Install dependencies with `poetry install` (`pip install poetry`)
`pre-commit` usage is highly recommended. To install hooks run
```bash
poetry run pre-commit install -t=pre-commit -t=pre-push
```
## License
[GPLv3](https://github.com/dhvcc/rss-parser/blob/master/LICENSE)
%package help
Summary: Development documents and examples for rss-parser
Provides: python3-rss-parser-doc
%description help
# Rss parser
[![Downloads](https://pepy.tech/badge/rss-parser)](https://pepy.tech/project/rss-parser)
[![Downloads](https://pepy.tech/badge/rss-parser/month)](https://pepy.tech/project/rss-parser/month)
[![Downloads](https://pepy.tech/badge/rss-parser/week)](https://pepy.tech/project/rss-parser/week)
[![PyPI version](https://img.shields.io/pypi/v/rss-parser)](https://pypi.org/project/rss-parser)
[![Python versions](https://img.shields.io/pypi/pyversions/rss-parser)](https://pypi.org/project/rss-parser)
[![Wheel status](https://img.shields.io/pypi/wheel/rss-parser)](https://pypi.org/project/rss-parser)
[![License](https://img.shields.io/pypi/l/rss-parser?color=success)](https://github.com/dhvcc/rss-parser/blob/master/LICENSE)
[![GitHub Pages](https://badgen.net/github/status/dhvcc/rss-parser/gh-pages?label=docs)](https://dhvcc.github.io/rss-parser#documentation)
![CI](https://github.com/dhvcc/rss-parser/actions/workflows/ci.yml/badge.svg?branch=master)
![PyPi publish](https://github.com/dhvcc/rss-parser/actions/workflows/publish_to_pypi.yml/badge.svg?branch=master)
## About
`rss-parser` is typed python RSS parsing module built using [pydantic](https://github.com/pydantic/pydantic) and [xmltodict](https://github.com/martinblech/xmltodict)
## Installation
```bash
pip install rss-parser
```
or
```bash
git clone https://github.com/dhvcc/rss-parser.git
cd rss-parser
poetry build
pip install dist/*.whl
```
## Usage
### Quickstart
```python
from rss_parser import Parser
from requests import get
rss_url = "https://rss.art19.com/apology-line"
response = get(rss_url)
rss = Parser.parse(response.text)
# Print out rss meta data
print("Language", rss.channel.language)
print("RSS", rss.version)
# Iteratively print feed items
for item in rss.channel.items:
print(item.title)
print(item.description[:50])
# Language en
# RSS 2.0
# Wondery Presents - Flipping The Bird: Elon vs Twitter
# When Elon Musk posted a video of himself arrivi
# Introducing: The Apology Line
#
If you could call a number and say you’re sorry
```
Here we can see that description is still somehow has
- this is beacause it's placed as [CDATA](https://www.w3resource.com/xml/CDATA-sections.php) like so
```xml
If you could call ...
]]>
```
### Overriding schema
If you want to customize the schema or provide a custom one - use `schema` keyword argument of the parser
```python
from rss_parser.models import XMLBaseModel
from rss_parser.models.rss import RSS
from rss_parser.models.types import Tag
class CustomSchema(RSS, XMLBaseModel):
channel: None = None # Removing previous channel field
custom: Tag[str]
with open("tests/samples/custom.xml") as f:
data = f.read()
rss = Parser.parse(data, schema=CustomSchema)
print("RSS", rss.version)
print("Custom", rss.custom)
# RSS 2.0
# Custom Custom tag data
```
### xmltodict
This library uses [xmltodict](https://github.com/martinblech/xmltodict) to parse XML data. You can see the detailed documentation [here](https://github.com/martinblech/xmltodict#xmltodict)
The basic thing you should know is that your data is processed into dictionaries
For example, this data
```xml
content
```
will result in the following
```python
{
"tag": "content"
}
```
*But*, when handling attributes, the content of the tag will be also a dictionary
```xml
data
```
Turns into
```python
{
"tag": {
"@attr": "1",
"@data-value": "data",
"#text": "content"
}
}
```
### Tag field
This is a generic field that handles tags as raw data or a dictonary returned with attributes
*Although this is a complex class, it forwards most of the methods to it's content attribute, so you don't notice a difference if you're only after the .content value*
Example
```python
from rss_parser.models import XMLBaseModel
class Model(XMLBaseModel):
number: Tag[int]
string: Tag[str]
m = Model(
number=1,
string={'@attr': '1', '#text': 'content'},
)
m.number.content == 1 # Content value is an integer, as per the generic type
m.number.content + 10 == m.number + 10 # But you're still able to use the Tag itself in common operators
m.number.bit_length() == 1 # As it's the case for methods/attributes not found in the Tag itself
type(m.number), type(m.number.content) == (, ) # types are NOT the same, however, the interfaces are very similar most of the time
m.number.attributes == {} # The attributes are empty by default
m.string.attributes == {'attr': '1'} # But are populated when provided. Note that the @ symbol is trimmed from the beggining, however, camelCase is not converted
# Generic argument types are handled by pydantic - let's try to provide a string for a Tag[int] number
m = Model(number='not_a_number', string={'@customAttr': 'v', '#text': 'str tag value'}) # This will lead in the following traceback
# Traceback (most recent call last):
# ...
# pydantic.error_wrappers.ValidationError: 1 validation error for Model
# number -> content
# value is not a valid integer (type=type_error.integer)
```
**If you wish to avoid all of the method/attribute forwarding "magic" - you should use `rss_parser.models.types.TagRaw`**
## Contributing
Pull requests are welcome. For major changes, please open an issue first
to discuss what you would like to change.
Install dependencies with `poetry install` (`pip install poetry`)
`pre-commit` usage is highly recommended. To install hooks run
```bash
poetry run pre-commit install -t=pre-commit -t=pre-push
```
## License
[GPLv3](https://github.com/dhvcc/rss-parser/blob/master/LICENSE)
%prep
%autosetup -n rss_parser-1.0.0
%build
%py3_build
%install
%py3_install
install -d -m755 %{buildroot}/%{_pkgdocdir}
if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
pushd %{buildroot}
if [ -d usr/lib ]; then
find usr/lib -type f -printf "\"/%h/%f\"\n" >> filelist.lst
fi
if [ -d usr/lib64 ]; then
find usr/lib64 -type f -printf "\"/%h/%f\"\n" >> filelist.lst
fi
if [ -d usr/bin ]; then
find usr/bin -type f -printf "\"/%h/%f\"\n" >> filelist.lst
fi
if [ -d usr/sbin ]; then
find usr/sbin -type f -printf "\"/%h/%f\"\n" >> filelist.lst
fi
touch doclist.lst
if [ -d usr/share/man ]; then
find usr/share/man -type f -printf "\"/%h/%f.gz\"\n" >> doclist.lst
fi
popd
mv %{buildroot}/filelist.lst .
mv %{buildroot}/doclist.lst .
%files -n python3-rss-parser -f filelist.lst
%dir %{python3_sitelib}/*
%files help -f doclist.lst
%{_docdir}/*
%changelog
* Thu Jun 08 2023 Python_Bot - 1.0.0-1
- Package Spec generated