feat: add 1.0.0 version
This commit is contained in:
parent
a85b42dd58
commit
0a1d77100f
12 changed files with 973 additions and 0 deletions
26
.coveragerc
Normal file
26
.coveragerc
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
[run]
|
||||||
|
branch = true
|
||||||
|
source = genrss
|
||||||
|
omit =
|
||||||
|
.venv
|
||||||
|
__meta__.py
|
||||||
|
|
||||||
|
[report]
|
||||||
|
exclude_lines =
|
||||||
|
pragma: no cover
|
||||||
|
def __repr__
|
||||||
|
if self\.debug:
|
||||||
|
if settings.DEBUG
|
||||||
|
raise NotImplementedError
|
||||||
|
if 0:
|
||||||
|
if False:
|
||||||
|
if __name__ == .__main__.:
|
||||||
|
@abstractmethod
|
||||||
|
|
||||||
|
fail_under = 80
|
||||||
|
precision = 2
|
||||||
|
show_missing = true
|
||||||
|
skip_covered = true
|
||||||
|
|
||||||
|
[html]
|
||||||
|
directory = tests/htmlcov
|
155
.gitignore
vendored
Normal file
155
.gitignore
vendored
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/vim,python
|
||||||
|
# Edit at https://www.gitignore.io/?templates=vim,python
|
||||||
|
|
||||||
|
### Python ###
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
pip-wheel-metadata/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
### Vim ###
|
||||||
|
# Swap
|
||||||
|
[._]*.s[a-v][a-z]
|
||||||
|
[._]*.sw[a-p]
|
||||||
|
[._]s[a-rt-v][a-z]
|
||||||
|
[._]ss[a-gi-z]
|
||||||
|
[._]sw[a-p]
|
||||||
|
|
||||||
|
# Session
|
||||||
|
Session.vim
|
||||||
|
Sessionx.vim
|
||||||
|
|
||||||
|
# Temporary
|
||||||
|
.netrwhist
|
||||||
|
*~
|
||||||
|
# Auto-generated tag files
|
||||||
|
tags
|
||||||
|
# Persistent undo
|
||||||
|
[._]*.un~
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/vim,python
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.c9/
|
11
.travis.yml
Normal file
11
.travis.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
language: python
|
||||||
|
python:
|
||||||
|
- '3.6'
|
||||||
|
- '3.7'
|
||||||
|
install:
|
||||||
|
- pip install -r requirements-test.txt
|
||||||
|
- pip install -e .
|
||||||
|
script:
|
||||||
|
- coverage run -m pytest
|
||||||
|
after_success:
|
||||||
|
- coveralls
|
16
Pipfile
Normal file
16
Pipfile
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[[source]]
|
||||||
|
name = "pypi"
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
pytest = "*"
|
||||||
|
coverage = "*"
|
||||||
|
coveralls = "*"
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
lxml = "*"
|
||||||
|
pytz = "*"
|
||||||
|
|
||||||
|
[requires]
|
||||||
|
python_version = "3.7"
|
377
Pipfile.lock
generated
Normal file
377
Pipfile.lock
generated
Normal file
|
@ -0,0 +1,377 @@
|
||||||
|
{
|
||||||
|
"_meta": {
|
||||||
|
"hash": {
|
||||||
|
"sha256": "f0911fe39e4694db48dedc159ec16cbf28529b922b8b1ec5fdbdfd67d70cdcf3"
|
||||||
|
},
|
||||||
|
"pipfile-spec": 6,
|
||||||
|
"requires": {
|
||||||
|
"python_version": "3.7"
|
||||||
|
},
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"name": "pypi",
|
||||||
|
"url": "https://pypi.org/simple",
|
||||||
|
"verify_ssl": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"lxml": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:06c7616601430aa140a69f97e3116308fffe0848f543b639a5ec2e8920ae72fd",
|
||||||
|
"sha256:177202792f9842374a8077735c69c41a4282183f7851443d2beb8ee310720819",
|
||||||
|
"sha256:19317ad721ceb9e39847d11131903931e2794e447d4751ebb0d9236f1b349ff2",
|
||||||
|
"sha256:36d206e62f3e5dbaafd4ec692b67157e271f5da7fd925fda8515da675eace50d",
|
||||||
|
"sha256:387115b066c797c85f9861a9613abf50046a15aac16759bc92d04f94acfad082",
|
||||||
|
"sha256:3ce1c49d4b4a7bc75fb12acb3a6247bb7a91fe420542e6d671ba9187d12a12c2",
|
||||||
|
"sha256:4d2a5a7d6b0dbb8c37dab66a8ce09a8761409c044017721c21718659fa3365a1",
|
||||||
|
"sha256:58d0a1b33364d1253a88d18df6c0b2676a1746d27c969dc9e32d143a3701dda5",
|
||||||
|
"sha256:62a651c618b846b88fdcae0533ec23f185bb322d6c1845733f3123e8980c1d1b",
|
||||||
|
"sha256:69ff21064e7debc9b1b1e2eee8c2d686d042d4257186d70b338206a80c5bc5ea",
|
||||||
|
"sha256:7060453eba9ba59d821625c6af6a266bd68277dce6577f754d1eb9116c094266",
|
||||||
|
"sha256:7d26b36a9c4bce53b9cfe42e67849ae3c5c23558bc08363e53ffd6d94f4ff4d2",
|
||||||
|
"sha256:83b427ad2bfa0b9705e02a83d8d607d2c2f01889eb138168e462a3a052c42368",
|
||||||
|
"sha256:923d03c84534078386cf50193057aae98fa94cace8ea7580b74754493fda73ad",
|
||||||
|
"sha256:b773715609649a1a180025213f67ffdeb5a4878c784293ada300ee95a1f3257b",
|
||||||
|
"sha256:baff149c174e9108d4a2fee192c496711be85534eab63adb122f93e70aa35431",
|
||||||
|
"sha256:bca9d118b1014b4c2d19319b10a3ebed508ff649396ce1855e1c96528d9b2fa9",
|
||||||
|
"sha256:ce580c28845581535dc6000fc7c35fdadf8bea7ccb57d6321b044508e9ba0685",
|
||||||
|
"sha256:d34923a569e70224d88e6682490e24c842907ba2c948c5fd26185413cbe0cd96",
|
||||||
|
"sha256:dd9f0e531a049d8b35ec5e6c68a37f1ba6ec3a591415e6804cbdf652793d15d7",
|
||||||
|
"sha256:ecb805cbfe9102f3fd3d2ef16dfe5ae9e2d7a7dfbba92f4ff1e16ac9784dbfb0",
|
||||||
|
"sha256:ede9aad2197a0202caff35d417b671f5f91a3631477441076082a17c94edd846",
|
||||||
|
"sha256:ef2d1fc370400e0aa755aab0b20cf4f1d0e934e7fd5244f3dd4869078e4942b9",
|
||||||
|
"sha256:f2fec194a49bfaef42a548ee657362af5c7a640da757f6f452a35da7dd9f923c"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==4.3.4"
|
||||||
|
},
|
||||||
|
"pytz": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
|
||||||
|
"sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==2019.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"develop": {
|
||||||
|
"asn1crypto": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87",
|
||||||
|
"sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49"
|
||||||
|
],
|
||||||
|
"version": "==0.24.0"
|
||||||
|
},
|
||||||
|
"atomicwrites": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4",
|
||||||
|
"sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"
|
||||||
|
],
|
||||||
|
"version": "==1.3.0"
|
||||||
|
},
|
||||||
|
"attrs": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79",
|
||||||
|
"sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"
|
||||||
|
],
|
||||||
|
"version": "==19.1.0"
|
||||||
|
},
|
||||||
|
"certifi": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939",
|
||||||
|
"sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695"
|
||||||
|
],
|
||||||
|
"version": "==2019.6.16"
|
||||||
|
},
|
||||||
|
"cffi": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774",
|
||||||
|
"sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d",
|
||||||
|
"sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90",
|
||||||
|
"sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b",
|
||||||
|
"sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63",
|
||||||
|
"sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45",
|
||||||
|
"sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25",
|
||||||
|
"sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3",
|
||||||
|
"sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b",
|
||||||
|
"sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647",
|
||||||
|
"sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016",
|
||||||
|
"sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4",
|
||||||
|
"sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb",
|
||||||
|
"sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753",
|
||||||
|
"sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7",
|
||||||
|
"sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9",
|
||||||
|
"sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f",
|
||||||
|
"sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8",
|
||||||
|
"sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f",
|
||||||
|
"sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc",
|
||||||
|
"sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42",
|
||||||
|
"sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3",
|
||||||
|
"sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909",
|
||||||
|
"sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45",
|
||||||
|
"sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d",
|
||||||
|
"sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512",
|
||||||
|
"sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff",
|
||||||
|
"sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201"
|
||||||
|
],
|
||||||
|
"version": "==1.12.3"
|
||||||
|
},
|
||||||
|
"chardet": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||||
|
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||||
|
],
|
||||||
|
"version": "==3.0.4"
|
||||||
|
},
|
||||||
|
"configparser": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32",
|
||||||
|
"sha256:da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75"
|
||||||
|
],
|
||||||
|
"markers": "python_version < '3'",
|
||||||
|
"version": "==3.7.4"
|
||||||
|
},
|
||||||
|
"contextlib2": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48",
|
||||||
|
"sha256:f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"
|
||||||
|
],
|
||||||
|
"markers": "python_version < '3'",
|
||||||
|
"version": "==0.5.5"
|
||||||
|
},
|
||||||
|
"coverage": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9",
|
||||||
|
"sha256:39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74",
|
||||||
|
"sha256:3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390",
|
||||||
|
"sha256:465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8",
|
||||||
|
"sha256:48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe",
|
||||||
|
"sha256:5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf",
|
||||||
|
"sha256:5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e",
|
||||||
|
"sha256:68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741",
|
||||||
|
"sha256:6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09",
|
||||||
|
"sha256:7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd",
|
||||||
|
"sha256:7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034",
|
||||||
|
"sha256:839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420",
|
||||||
|
"sha256:8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c",
|
||||||
|
"sha256:932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab",
|
||||||
|
"sha256:988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba",
|
||||||
|
"sha256:998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e",
|
||||||
|
"sha256:9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609",
|
||||||
|
"sha256:9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2",
|
||||||
|
"sha256:a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49",
|
||||||
|
"sha256:a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b",
|
||||||
|
"sha256:aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d",
|
||||||
|
"sha256:bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce",
|
||||||
|
"sha256:bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9",
|
||||||
|
"sha256:c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4",
|
||||||
|
"sha256:c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773",
|
||||||
|
"sha256:c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723",
|
||||||
|
"sha256:df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c",
|
||||||
|
"sha256:f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f",
|
||||||
|
"sha256:f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1",
|
||||||
|
"sha256:f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260",
|
||||||
|
"sha256:fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==4.5.3"
|
||||||
|
},
|
||||||
|
"coveralls": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:d3d49234bffd41e91b241a69f0ebb9f64d7f0515711a76134d53d4647e7eb509",
|
||||||
|
"sha256:dafabcff87425fa2ab3122dee21229afbb4d6692cfdacc6bb895f7dfa8b2c849"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==1.8.1"
|
||||||
|
},
|
||||||
|
"cryptography": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:24b61e5fcb506424d3ec4e18bca995833839bf13c59fc43e530e488f28d46b8c",
|
||||||
|
"sha256:25dd1581a183e9e7a806fe0543f485103232f940fcfc301db65e630512cce643",
|
||||||
|
"sha256:3452bba7c21c69f2df772762be0066c7ed5dc65df494a1d53a58b683a83e1216",
|
||||||
|
"sha256:41a0be220dd1ed9e998f5891948306eb8c812b512dc398e5a01846d855050799",
|
||||||
|
"sha256:5751d8a11b956fbfa314f6553d186b94aa70fdb03d8a4d4f1c82dcacf0cbe28a",
|
||||||
|
"sha256:5f61c7d749048fa6e3322258b4263463bfccefecb0dd731b6561cb617a1d9bb9",
|
||||||
|
"sha256:72e24c521fa2106f19623a3851e9f89ddfdeb9ac63871c7643790f872a305dfc",
|
||||||
|
"sha256:7b97ae6ef5cba2e3bb14256625423413d5ce8d1abb91d4f29b6d1a081da765f8",
|
||||||
|
"sha256:961e886d8a3590fd2c723cf07be14e2a91cf53c25f02435c04d39e90780e3b53",
|
||||||
|
"sha256:96d8473848e984184b6728e2c9d391482008646276c3ff084a1bd89e15ff53a1",
|
||||||
|
"sha256:ae536da50c7ad1e002c3eee101871d93abdc90d9c5f651818450a0d3af718609",
|
||||||
|
"sha256:b0db0cecf396033abb4a93c95d1602f268b3a68bb0a9cc06a7cff587bb9a7292",
|
||||||
|
"sha256:cfee9164954c186b191b91d4193989ca994703b2fff406f71cf454a2d3c7327e",
|
||||||
|
"sha256:e6347742ac8f35ded4a46ff835c60e68c22a536a8ae5c4422966d06946b6d4c6",
|
||||||
|
"sha256:f27d93f0139a3c056172ebb5d4f9056e770fdf0206c2f422ff2ebbad142e09ed",
|
||||||
|
"sha256:f57b76e46a58b63d1c6375017f4564a28f19a5ca912691fd2e4261b3414b618d"
|
||||||
|
],
|
||||||
|
"version": "==2.7"
|
||||||
|
},
|
||||||
|
"docopt": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"
|
||||||
|
],
|
||||||
|
"version": "==0.6.2"
|
||||||
|
},
|
||||||
|
"enum34": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850",
|
||||||
|
"sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a",
|
||||||
|
"sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79",
|
||||||
|
"sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"
|
||||||
|
],
|
||||||
|
"markers": "python_version < '3'",
|
||||||
|
"version": "==1.1.6"
|
||||||
|
},
|
||||||
|
"funcsigs": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
|
||||||
|
"sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
|
||||||
|
],
|
||||||
|
"markers": "python_version < '3.0'",
|
||||||
|
"version": "==1.0.2"
|
||||||
|
},
|
||||||
|
"idna": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
|
||||||
|
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
|
||||||
|
],
|
||||||
|
"version": "==2.8"
|
||||||
|
},
|
||||||
|
"importlib-metadata": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:6dfd58dfe281e8d240937776065dd3624ad5469c835248219bd16cf2e12dbeb7",
|
||||||
|
"sha256:cb6ee23b46173539939964df59d3d72c3e0c1b5d54b84f1d8a7e912fe43612db"
|
||||||
|
],
|
||||||
|
"version": "==0.18"
|
||||||
|
},
|
||||||
|
"ipaddress": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:64b28eec5e78e7510698f6d4da08800a5c575caa4a286c93d651c5d3ff7b6794",
|
||||||
|
"sha256:b146c751ea45cad6188dd6cf2d9b757f6f4f8d6ffb96a023e6f2e26eea02a72c"
|
||||||
|
],
|
||||||
|
"version": "==1.0.22"
|
||||||
|
},
|
||||||
|
"more-itertools": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4",
|
||||||
|
"sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc",
|
||||||
|
"sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9"
|
||||||
|
],
|
||||||
|
"markers": "python_version <= '2.7'",
|
||||||
|
"version": "==5.0.0"
|
||||||
|
},
|
||||||
|
"packaging": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af",
|
||||||
|
"sha256:9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3"
|
||||||
|
],
|
||||||
|
"version": "==19.0"
|
||||||
|
},
|
||||||
|
"pathlib2": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2156525d6576d21c4dcaddfa427fae887ef89a7a9de5cbfe0728b3aafa78427e",
|
||||||
|
"sha256:446014523bb9be5c28128c4d2a10ad6bb60769e78bd85658fe44a450674e0ef8"
|
||||||
|
],
|
||||||
|
"markers": "python_version < '3.6'",
|
||||||
|
"version": "==2.3.4"
|
||||||
|
},
|
||||||
|
"pluggy": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0825a152ac059776623854c1543d65a4ad408eb3d33ee114dff91e57ec6ae6fc",
|
||||||
|
"sha256:b9817417e95936bf75d85d3f8767f7df6cdde751fc40aed3bb3074cbcb77757c"
|
||||||
|
],
|
||||||
|
"version": "==0.12.0"
|
||||||
|
},
|
||||||
|
"py": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
|
||||||
|
"sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
|
||||||
|
],
|
||||||
|
"version": "==1.8.0"
|
||||||
|
},
|
||||||
|
"pycparser": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
|
||||||
|
],
|
||||||
|
"version": "==2.19"
|
||||||
|
},
|
||||||
|
"pyopenssl": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:aeca66338f6de19d1aa46ed634c3b9ae519a64b458f8468aec688e7e3c20f200",
|
||||||
|
"sha256:c727930ad54b10fc157015014b666f2d8b41f70c0d03e83ab67624fd3dd5d1e6"
|
||||||
|
],
|
||||||
|
"version": "==19.0.0"
|
||||||
|
},
|
||||||
|
"pyparsing": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:530d8bf8cc93a34019d08142593cf4d78a05c890da8cf87ffa3120af53772238",
|
||||||
|
"sha256:f78e99616b6f1a4745c0580e170251ef1bbafc0d0513e270c4bd281bf29d2800"
|
||||||
|
],
|
||||||
|
"version": "==2.4.1"
|
||||||
|
},
|
||||||
|
"pytest": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:6aa9bc2f6f6504d7949e9df2a756739ca06e58ffda19b5e53c725f7b03fb4aae",
|
||||||
|
"sha256:b77ae6f2d1a760760902a7676887b665c086f71e3461c64ed2a312afcedc00d6"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==4.6.4"
|
||||||
|
},
|
||||||
|
"requests": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
|
||||||
|
"sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
|
||||||
|
],
|
||||||
|
"version": "==2.22.0"
|
||||||
|
},
|
||||||
|
"scandir": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e",
|
||||||
|
"sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022",
|
||||||
|
"sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f",
|
||||||
|
"sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f",
|
||||||
|
"sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae",
|
||||||
|
"sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173",
|
||||||
|
"sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4",
|
||||||
|
"sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32",
|
||||||
|
"sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188",
|
||||||
|
"sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d",
|
||||||
|
"sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac"
|
||||||
|
],
|
||||||
|
"markers": "python_version < '3.5'",
|
||||||
|
"version": "==1.10.0"
|
||||||
|
},
|
||||||
|
"six": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
|
||||||
|
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
|
||||||
|
],
|
||||||
|
"version": "==1.12.0"
|
||||||
|
},
|
||||||
|
"urllib3": {
|
||||||
|
"extras": [
|
||||||
|
"secure"
|
||||||
|
],
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4",
|
||||||
|
"sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"
|
||||||
|
],
|
||||||
|
"markers": "python_version < '3'",
|
||||||
|
"version": "==1.24.3"
|
||||||
|
},
|
||||||
|
"wcwidth": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
|
||||||
|
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
|
||||||
|
],
|
||||||
|
"version": "==0.1.7"
|
||||||
|
},
|
||||||
|
"zipp": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:4970c3758f4e89a7857a973b1e2a5d75bcdc47794442f2e2dd4fe8e0466e809a",
|
||||||
|
"sha256:8a5712cfd3bb4248015eb3b0b3c54a5f6ee3f2425963ef2a0125b8bc40aafaec"
|
||||||
|
],
|
||||||
|
"version": "==0.5.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,6 @@
|
||||||
# genrss
|
# genrss
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/icetemple/genrss.svg?branch=master)](https://travis-ci.org/icetemple/genrss)
|
||||||
|
[![Coverage Status](https://coveralls.io/repos/github/icetemple/genrss/badge.svg?branch=master)](https://coveralls.io/github/icetemple/genrss?branch=master)
|
||||||
|
|
||||||
RSS generator for python
|
RSS generator for python
|
||||||
|
|
139
genrss/__init__.py
Normal file
139
genrss/__init__.py
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
import mimetypes
|
||||||
|
from lxml.etree import Element, CDATA, tostring
|
||||||
|
from typing import Optional, List, NoReturn
|
||||||
|
from datetime import datetime
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
Enclosure = namedtuple('Enclosure', ('url', 'size', 'type'))
|
||||||
|
Enclosure.__new__.__defaults__ = (None, None, None)
|
||||||
|
|
||||||
|
RSS_DEFAULT_GENERATOR = f'Generated by genrss for python'
|
||||||
|
|
||||||
|
|
||||||
|
def create_element(name: str, text=None, children=None, **kwargs) -> Element:
|
||||||
|
el = Element(name, **kwargs)
|
||||||
|
if text:
|
||||||
|
if isinstance(text, datetime):
|
||||||
|
text = text.replace(tzinfo=pytz.timezone('GMT')). \
|
||||||
|
strftime("%a, %d %b %Y %H:%M:%S %Z")
|
||||||
|
el.text = text
|
||||||
|
elif isinstance(children, (list, tuple)):
|
||||||
|
for child in children:
|
||||||
|
el.append(child)
|
||||||
|
return el
|
||||||
|
|
||||||
|
|
||||||
|
class GenRSS:
|
||||||
|
def __init__(self, title: str, site_url: str, feed_url: str, **kwargs):
|
||||||
|
self.title: str = title
|
||||||
|
self.site_url: str = site_url
|
||||||
|
self.feed_url: str = feed_url
|
||||||
|
self.description: str = kwargs.pop('description', self.title)
|
||||||
|
self.image_url: Optional[str] = kwargs.pop('image_url', None)
|
||||||
|
self.author: Optional[str] = kwargs.pop('author', None)
|
||||||
|
self.pub_date: Optional[datetime] = kwargs.pop('pub_date', None)
|
||||||
|
self.copyright: Optional[str] = kwargs.pop('copyright', None)
|
||||||
|
self.language: Optional[str] = kwargs.pop('language', None)
|
||||||
|
self.editor: Optional[str] = kwargs.pop('editor', None)
|
||||||
|
self.webmaster: Optional[str] = kwargs.pop('webmaster', None)
|
||||||
|
self.docs_url: Optional[str] = kwargs.pop('docs_url', None)
|
||||||
|
self.categories: List[str] = kwargs.pop('categories', [])
|
||||||
|
|
||||||
|
self.items: List[Element] = []
|
||||||
|
self.generator = kwargs.pop('generator', RSS_DEFAULT_GENERATOR)
|
||||||
|
self.root_version = '2.0'
|
||||||
|
self.root_nsmap = {
|
||||||
|
'atom': 'http://www.w3.org/2005/Atom'
|
||||||
|
}
|
||||||
|
|
||||||
|
def item(self, title: str, **kwargs) -> NoReturn:
|
||||||
|
description: str = kwargs.pop('description', '')
|
||||||
|
url: Optional[str] = kwargs.pop('url', None)
|
||||||
|
guid: Optional[str] = kwargs.pop('guid', None)
|
||||||
|
author: Optional[str] = kwargs.pop('author', None)
|
||||||
|
categories: List[str] = kwargs.pop('categories', [])
|
||||||
|
enclosure: Optional[Enclosure] = kwargs.pop('enclosure', None)
|
||||||
|
pub_date: Optional[datetime] = kwargs.pop('pub_date', None)
|
||||||
|
|
||||||
|
item = create_element('item', children=[
|
||||||
|
create_element('title', CDATA(title)),
|
||||||
|
create_element('description', CDATA(description)),
|
||||||
|
])
|
||||||
|
|
||||||
|
if url:
|
||||||
|
item.append(create_element('link', url))
|
||||||
|
|
||||||
|
item.append(create_element(
|
||||||
|
'guid',
|
||||||
|
attrib={'isPermaLink': str(bool(not guid and url)).lower()},
|
||||||
|
text=(guid or url or CDATA(title))
|
||||||
|
))
|
||||||
|
|
||||||
|
if author or self.author:
|
||||||
|
if 'dc' not in self.root_nsmap:
|
||||||
|
self.root_nsmap['dc'] = 'http://purl.org/dc/elements/1.1/'
|
||||||
|
|
||||||
|
item.append(create_element(
|
||||||
|
'{http://purl.org/dc/elements/1.1/}creator',
|
||||||
|
CDATA(author or self.author)
|
||||||
|
))
|
||||||
|
|
||||||
|
for category in categories:
|
||||||
|
item.append(create_element('category', CDATA(category)))
|
||||||
|
|
||||||
|
if enclosure:
|
||||||
|
item.append(create_element(
|
||||||
|
'enclosure',
|
||||||
|
url=enclosure.url,
|
||||||
|
length=str(enclosure.size or 0),
|
||||||
|
type=enclosure.type or mimetypes.guess_type(enclosure.url)[0]
|
||||||
|
))
|
||||||
|
|
||||||
|
if pub_date:
|
||||||
|
item.append(create_element('pubDate', pub_date))
|
||||||
|
|
||||||
|
self.items.append(item)
|
||||||
|
|
||||||
|
def xml(self, pretty: bool = False) -> str:
|
||||||
|
root = Element('rss', nsmap=self.root_nsmap, version=self.root_version)
|
||||||
|
channel = create_element('channel', children=[
|
||||||
|
create_element('title', CDATA(self.title)),
|
||||||
|
create_element('description', CDATA(self.description)),
|
||||||
|
create_element('link', self.site_url),
|
||||||
|
create_element('{http://www.w3.org/2005/Atom}link',
|
||||||
|
href=self.feed_url, rel='self',
|
||||||
|
type='application/rss+xml'),
|
||||||
|
create_element('generator', self.generator),
|
||||||
|
create_element('lastBuildDate', datetime.utcnow())
|
||||||
|
])
|
||||||
|
|
||||||
|
if self.image_url:
|
||||||
|
channel.append(create_element('image', children=[
|
||||||
|
create_element('url', self.image_url),
|
||||||
|
create_element('title', CDATA(self.title)),
|
||||||
|
create_element('link', self.site_url)
|
||||||
|
]))
|
||||||
|
for category in self.categories:
|
||||||
|
channel.append(create_element('category', CDATA(category)))
|
||||||
|
if self.pub_date:
|
||||||
|
channel.append(create_element('pubDate', self.pub_date))
|
||||||
|
if self.copyright:
|
||||||
|
channel.append(create_element('copyright', CDATA(self.copyright)))
|
||||||
|
if self.language:
|
||||||
|
channel.append(create_element('language', CDATA(self.language)))
|
||||||
|
if self.editor:
|
||||||
|
channel.append(create_element('managingEditor', CDATA(self.editor)))
|
||||||
|
if self.webmaster:
|
||||||
|
channel.append(create_element('webMaster', CDATA(self.webmaster)))
|
||||||
|
if self.docs_url:
|
||||||
|
channel.append(create_element('docs', self.docs_url))
|
||||||
|
|
||||||
|
for item in self.items:
|
||||||
|
channel.append(item)
|
||||||
|
|
||||||
|
root.append(channel)
|
||||||
|
|
||||||
|
return '<?xml version="1.0" encoding="UTF-8"?>\n' \
|
||||||
|
+ tostring(root, pretty_print=pretty).decode('utf-8')
|
3
requirements-test.txt
Normal file
3
requirements-test.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
coverage==4.5.3
|
||||||
|
coveralls==1.8.1
|
||||||
|
pytest==4.6.4
|
25
setup.py
Normal file
25
setup.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
|
||||||
|
with open('README.md', 'r') as f:
|
||||||
|
readme = f.read()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
setup(
|
||||||
|
name='genrss',
|
||||||
|
version='1.0.0',
|
||||||
|
author='Dmitriy Pleshevskiy',
|
||||||
|
author_email='dmitriy@ideascup.me',
|
||||||
|
description='RSS feed generator for python',
|
||||||
|
long_description=readme,
|
||||||
|
long_description_content_type='text/markdown',
|
||||||
|
package_data={'': ['LICENSE', 'README.md']},
|
||||||
|
include_package_data=True,
|
||||||
|
license='MIT',
|
||||||
|
packages=['genrss'],
|
||||||
|
install_requires=[
|
||||||
|
'lxml==4.3.4',
|
||||||
|
'pytz==2019.1'
|
||||||
|
]
|
||||||
|
)
|
10
tests/support.py
Normal file
10
tests/support.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from genrss import GenRSS
|
||||||
|
|
||||||
|
|
||||||
|
def create_rss(**kwargs):
|
||||||
|
return GenRSS(title='SmartFridge', site_url='https://smartfridge.me/',
|
||||||
|
feed_url='https://smartfridge.me/rss.xml', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def create_item(feed, **kwargs):
|
||||||
|
feed.item(title='Recipe', **kwargs)
|
111
tests/test_rss.py
Normal file
111
tests/test_rss.py
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
from datetime import datetime
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
import pytz
|
||||||
|
import pytest
|
||||||
|
from genrss import RSS_DEFAULT_GENERATOR
|
||||||
|
from tests.support import create_rss
|
||||||
|
|
||||||
|
|
||||||
|
def test_init_rss():
|
||||||
|
feed = create_rss()
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<title><![CDATA[SmartFridge]]></title>' in xml
|
||||||
|
assert '<description><![CDATA[SmartFridge]]></description>' in xml
|
||||||
|
assert '<link>https://smartfridge.me/</link>' in xml
|
||||||
|
assert '<atom:link href="https://smartfridge.me/rss.xml" rel="self" ' \
|
||||||
|
'type="application/rss+xml"/>' in xml
|
||||||
|
assert '<generator>{}</generator>'.format(RSS_DEFAULT_GENERATOR) in xml
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('description, expose', [
|
||||||
|
pytest.param('a' * 10, 'a' * 10, id='short(10)'),
|
||||||
|
pytest.param('a' * 285, 'a' * 285, id='long(285)'),
|
||||||
|
pytest.param(
|
||||||
|
dedent('''\
|
||||||
|
This is text with
|
||||||
|
new lines.'''),
|
||||||
|
dedent('''\
|
||||||
|
This is text with
|
||||||
|
new lines.'''),
|
||||||
|
id='+nl'
|
||||||
|
)
|
||||||
|
])
|
||||||
|
def test_feed_description(description, expose):
|
||||||
|
feed = create_rss(description=description)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<description><![CDATA[{}]]></description>'.format(expose) in xml
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('copyright, expose', [
|
||||||
|
pytest.param('copyright © genrss', 'copyright © genrss', id='copy'),
|
||||||
|
])
|
||||||
|
def test_feed_copyright(copyright, expose):
|
||||||
|
feed = create_rss(copyright=copyright)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<copyright><![CDATA[{}]]></copyright>'.format(expose) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_feed_pub_date():
|
||||||
|
pub_date = datetime.utcnow()
|
||||||
|
feed = create_rss(pub_date=pub_date)
|
||||||
|
xml = feed.xml()
|
||||||
|
expose = pub_date.replace(tzinfo=pytz.timezone('GMT')). \
|
||||||
|
strftime("%a, %d %b %Y %H:%M:%S %Z")
|
||||||
|
assert xml
|
||||||
|
assert '<pubDate>{}</pubDate>'.format(expose) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_feed_language():
|
||||||
|
lang = 'en'
|
||||||
|
feed = create_rss(language=lang)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<language><![CDATA[{}]]></language>'.format(lang) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_feed_editor():
|
||||||
|
editor = 'Dmitriy Pleshevskiy'
|
||||||
|
feed = create_rss(editor=editor)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert ('<managingEditor><![CDATA[{}]]>'
|
||||||
|
'</managingEditor>').format(editor) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_feed_image_url():
|
||||||
|
image_url = 'https://s3.smartfridge.me/image.jpg'
|
||||||
|
feed = create_rss(image_url=image_url)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert (f'<image><url>{image_url}</url>'
|
||||||
|
'<title><![CDATA[SmartFridge]]></title>'
|
||||||
|
'<link>https://smartfridge.me/</link></image>') in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_feed_webmaster():
|
||||||
|
webmaster = 'Dmitriy Pleshevskiy'
|
||||||
|
feed = create_rss(webmaster=webmaster)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<webMaster><![CDATA[{}]]></webMaster>'.format(webmaster) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_feed_docs_url():
|
||||||
|
docs_url = 'https://smartfridge.me/docs'
|
||||||
|
feed = create_rss(docs_url=docs_url)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<docs>{}</docs>'.format(docs_url) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_feed_categories():
|
||||||
|
categories = ['Category 1', 'Category 2']
|
||||||
|
feed = create_rss(categories=categories)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<category><![CDATA[Category 1]]></category>' \
|
||||||
|
'<category><![CDATA[Category 2]]></category>' in xml
|
96
tests/test_rss_item.py
Normal file
96
tests/test_rss_item.py
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
from uuid import uuid4
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import pytz
|
||||||
|
import pytest
|
||||||
|
from genrss import Enclosure
|
||||||
|
from tests.support import create_rss, create_item
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def feed():
|
||||||
|
return create_rss()
|
||||||
|
|
||||||
|
|
||||||
|
def test_item(feed):
|
||||||
|
create_item(feed)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<item><title><![CDATA[Recipe]]></title>' \
|
||||||
|
'<description><![CDATA[]]></description>' \
|
||||||
|
'<guid isPermaLink="false"><![CDATA[Recipe]]></guid>' \
|
||||||
|
'</item>' in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_item_description(feed):
|
||||||
|
description = 'description'
|
||||||
|
create_item(feed, description=description)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<item><title><![CDATA[Recipe]]></title>' \
|
||||||
|
'<description><![CDATA[{}]]></description>' \
|
||||||
|
'<guid isPermaLink="false"><![CDATA[Recipe]]></guid>' \
|
||||||
|
'</item>'.format(description) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_item_guid(feed):
|
||||||
|
guid = uuid4().hex
|
||||||
|
create_item(feed, guid=guid)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<item><title><![CDATA[Recipe]]></title>' \
|
||||||
|
'<description><![CDATA[]]></description>' \
|
||||||
|
'<guid isPermaLink="false">{}</guid>' \
|
||||||
|
'</item>'.format(guid) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_item_url(feed):
|
||||||
|
url = 'https://smartfridge.me/'
|
||||||
|
create_item(feed, url=url)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<item><title><![CDATA[Recipe]]></title>' \
|
||||||
|
'<description><![CDATA[]]></description>' \
|
||||||
|
'<link>{url}</link>' \
|
||||||
|
'<guid isPermaLink="true">{url}</guid>' \
|
||||||
|
'</item>'.format(url=url) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_item_author(feed):
|
||||||
|
author = 'Dmitriy Pleshevskiy'
|
||||||
|
create_item(feed, author=author)
|
||||||
|
create_item(feed, author=author)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<dc:creator><![CDATA[{}]]></dc:creator>' \
|
||||||
|
'</item>'.format(author) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_item_categories(feed):
|
||||||
|
categories = ['Category 1', 'Category 2']
|
||||||
|
create_item(feed, categories=categories)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<category><![CDATA[Category 1]]></category>' \
|
||||||
|
'<category><![CDATA[Category 2]]></category>' \
|
||||||
|
'</item>' in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_item_pub_date(feed):
|
||||||
|
pub_date = datetime.utcnow()
|
||||||
|
expose = pub_date.replace(tzinfo=pytz.timezone('GMT')). \
|
||||||
|
strftime("%a, %d %b %Y %H:%M:%S %Z")
|
||||||
|
create_item(feed, pub_date=pub_date)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<pubDate>{}</pubDate>' \
|
||||||
|
'</item>'.format(expose) in xml
|
||||||
|
|
||||||
|
|
||||||
|
def test_item_enclosure(feed):
|
||||||
|
enclosure=Enclosure('https://smartfridge.me/image.jpg')
|
||||||
|
create_item(feed, enclosure=enclosure)
|
||||||
|
xml = feed.xml()
|
||||||
|
assert xml
|
||||||
|
assert '<enclosure length="{}" type="{}" url="{}"/>' \
|
||||||
|
'</item>'.format(0, 'image/jpeg', enclosure.url) in xml
|
Loading…
Reference in a new issue