Compare commits
No commits in common. "master" and "gh-pages" have entirely different histories.
20
.gitignore
vendored
|
@ -1,17 +1,5 @@
|
||||||
.idea/
|
|
||||||
venv
|
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
/MANIFEST
|
||||||
*.swp
|
/docs
|
||||||
|
/dist
|
||||||
feedgen/tests/tmp_Atomfeed.xml
|
/doc
|
||||||
|
|
||||||
feedgen/tests/tmp_Rssfeed.xml
|
|
||||||
|
|
||||||
tmp_Atomfeed.xml
|
|
||||||
|
|
||||||
tmp_Rssfeed.xml
|
|
||||||
|
|
||||||
# testing artifacts
|
|
||||||
.coverage
|
|
||||||
*.egg-info/
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Authorized licenses in lower case
|
|
||||||
|
|
||||||
# There is no project rule against adding new licenses as long as they are
|
|
||||||
# compatible with the project's license.
|
|
||||||
|
|
||||||
[Licenses]
|
|
||||||
authorized_licenses:
|
|
||||||
BSD
|
|
||||||
MIT
|
|
25
.travis.yml
|
@ -1,25 +0,0 @@
|
||||||
language: python
|
|
||||||
|
|
||||||
dist: bionic
|
|
||||||
|
|
||||||
# https://devguide.python.org/#branchstatus
|
|
||||||
python:
|
|
||||||
- 3.6
|
|
||||||
- 3.7
|
|
||||||
- 3.8
|
|
||||||
|
|
||||||
install:
|
|
||||||
- pip install bandit flake8 python-coveralls coverage liccheck
|
|
||||||
- pip install -r requirements.txt
|
|
||||||
- python setup.py bdist_wheel
|
|
||||||
- pip install dist/feedgen*
|
|
||||||
|
|
||||||
script:
|
|
||||||
- make test
|
|
||||||
- liccheck -s .licenses.ini
|
|
||||||
- python -m feedgen
|
|
||||||
- python -m feedgen atom
|
|
||||||
- python -m feedgen rss
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- coveralls
|
|
1
CNAME
Normal file
|
@ -0,0 +1 @@
|
||||||
|
feedgen.kiesow.be
|
|
@ -1,2 +0,0 @@
|
||||||
include license.bsd license.lgpl readme.rst
|
|
||||||
recursive-include docs *.html *.css *.png *.gif *.js
|
|
54
Makefile
|
@ -1,54 +0,0 @@
|
||||||
sdist: doc
|
|
||||||
python setup.py sdist
|
|
||||||
|
|
||||||
bdist_wheel: doc
|
|
||||||
python setup.py bdist_wheel
|
|
||||||
|
|
||||||
clean: doc-clean
|
|
||||||
@echo Removing binary files...
|
|
||||||
@rm -f `find feedgen -name '*.pyc'`
|
|
||||||
@rm -f `find feedgen -name '*.pyo'`
|
|
||||||
@rm -rf feedgen.egg-info/ build/
|
|
||||||
@echo Removing source distribution files...
|
|
||||||
@rm -rf dist/
|
|
||||||
@rm -f MANIFEST
|
|
||||||
@rm -f tmp_Atomfeed.xml tmp_Rssfeed.xml
|
|
||||||
|
|
||||||
doc: doc-clean doc-html doc-man
|
|
||||||
|
|
||||||
doc-clean:
|
|
||||||
@echo Removing docs...
|
|
||||||
@make -C doc clean
|
|
||||||
@rm -rf docs
|
|
||||||
|
|
||||||
doc-html:
|
|
||||||
@echo 'Generating HTML'
|
|
||||||
@make -C doc html
|
|
||||||
@mkdir -p docs/html
|
|
||||||
@echo 'Copying html to into docs dir'
|
|
||||||
@cp doc/_build/html/*.html docs/html/
|
|
||||||
@cp doc/_build/html/*.js docs/html/
|
|
||||||
@cp -r doc/_build/html/_static/ docs/html/
|
|
||||||
@cp -r doc/_build/html/ext/ docs/html/
|
|
||||||
|
|
||||||
doc-man:
|
|
||||||
@echo 'Generating manpage'
|
|
||||||
@make -C doc man
|
|
||||||
@mkdir -p docs/man
|
|
||||||
@echo 'Copying manpage to into docs dir'
|
|
||||||
@cp doc/_build/man/*.1 docs/man/
|
|
||||||
|
|
||||||
doc-latexpdf:
|
|
||||||
@echo 'Generating pdf'
|
|
||||||
@make -C doc latexpdf
|
|
||||||
@mkdir -p docs/pdf
|
|
||||||
@echo 'Copying pdf to into docs dir'
|
|
||||||
@cp doc/_build/latex/*.pdf docs/pdf/
|
|
||||||
|
|
||||||
publish:
|
|
||||||
twine upload dist/*
|
|
||||||
|
|
||||||
test:
|
|
||||||
coverage run --source=feedgen -m unittest discover -s tests
|
|
||||||
flake8 $$(find setup.py tests feedgen -name '*.py')
|
|
||||||
bandit -r feedgen
|
|
17
SECURITY.rst
|
@ -1,17 +0,0 @@
|
||||||
Security Policy
|
|
||||||
===============
|
|
||||||
|
|
||||||
Supported Versions
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Only the latest version of this library is supported.
|
|
||||||
We are doing our best to make updates as easy as possible
|
|
||||||
so that keeping up-to-date is usually pretty easy.
|
|
||||||
|
|
||||||
|
|
||||||
Reporting a Vulnerability
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
If you find a security vulnerability,
|
|
||||||
please report it by sending a mail to security@lkiesow.de.
|
|
||||||
We will discuss the problem internally and, if necessary, release a patched version as soon as possible.
|
|
BIN
_static/ajax-loader.gif
Normal file
After Width: | Height: | Size: 673 B |
BIN
_static/alert_info_32.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
_static/alert_warning_32.png
Normal file
After Width: | Height: | Size: 944 B |
676
_static/basic.css
Normal file
|
@ -0,0 +1,676 @@
|
||||||
|
/*
|
||||||
|
* basic.css
|
||||||
|
* ~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx stylesheet -- basic theme.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -- main layout ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.clearer {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- relbar ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.related {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related h3 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0 10px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related li.right {
|
||||||
|
float: right;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- sidebar --------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper {
|
||||||
|
padding: 10px 5px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar {
|
||||||
|
float: left;
|
||||||
|
width: 230px;
|
||||||
|
margin-left: -100%;
|
||||||
|
font-size: 90%;
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow-wrap : break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul ul,
|
||||||
|
div.sphinxsidebar ul.want-points {
|
||||||
|
margin-left: 20px;
|
||||||
|
list-style: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul ul {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar form {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar input {
|
||||||
|
border: 1px solid #98dbcc;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox form.search {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox input[type="text"] {
|
||||||
|
float: left;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0.25em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
border-left: none;
|
||||||
|
padding: 0.25em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- search page ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
ul.search {
|
||||||
|
margin: 10px 0 0 20px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li {
|
||||||
|
padding: 5px 0 5px 20px;
|
||||||
|
background-image: url(file.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 0 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li div.context {
|
||||||
|
color: #888;
|
||||||
|
margin: 2px 0 0 30px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.keywordmatches li.goodmatch a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- index page ------------------------------------------------------------ */
|
||||||
|
|
||||||
|
table.contentstable {
|
||||||
|
width: 90%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.contentstable p.biglink {
|
||||||
|
line-height: 150%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.biglink {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.linkdescr {
|
||||||
|
font-style: italic;
|
||||||
|
padding-top: 5px;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- general index --------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.indextable {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable td {
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable ul {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable > tbody > tr > td > ul {
|
||||||
|
padding-left: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable tr.pcap {
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable tr.cap {
|
||||||
|
margin-top: 10px;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.toggler {
|
||||||
|
margin-right: 3px;
|
||||||
|
margin-top: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.modindex-jumpbox {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.genindex-jumpbox {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- domain module index --------------------------------------------------- */
|
||||||
|
|
||||||
|
table.modindextable td {
|
||||||
|
padding: 2px;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- general body styles --------------------------------------------------- */
|
||||||
|
|
||||||
|
div.body {
|
||||||
|
min-width: 59em;
|
||||||
|
max-width: 70em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||||
|
-moz-hyphens: auto;
|
||||||
|
-ms-hyphens: auto;
|
||||||
|
-webkit-hyphens: auto;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.headerlink {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1:hover > a.headerlink,
|
||||||
|
h2:hover > a.headerlink,
|
||||||
|
h3:hover > a.headerlink,
|
||||||
|
h4:hover > a.headerlink,
|
||||||
|
h5:hover > a.headerlink,
|
||||||
|
h6:hover > a.headerlink,
|
||||||
|
dt:hover > a.headerlink,
|
||||||
|
caption:hover > a.headerlink,
|
||||||
|
p.caption:hover > a.headerlink,
|
||||||
|
div.code-block-caption:hover > a.headerlink {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p.caption {
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.first {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rubric {
|
||||||
|
margin-top: 30px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-left, .figure.align-left, object.align-left {
|
||||||
|
clear: left;
|
||||||
|
float: left;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-right, .figure.align-right, object.align-right {
|
||||||
|
clear: right;
|
||||||
|
float: right;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-center, .figure.align-center, object.align-center {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- sidebars -------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.sidebar {
|
||||||
|
margin: 0 0 0.5em 1em;
|
||||||
|
border: 1px solid #ddb;
|
||||||
|
padding: 7px 7px 0 7px;
|
||||||
|
background-color: #ffe;
|
||||||
|
width: 40%;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.sidebar-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- topics ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.topic {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 7px 7px 0 7px;
|
||||||
|
margin: 10px 0 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.topic-title {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- admonitions ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.admonition {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition dl {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.admonition-title {
|
||||||
|
margin: 0px 10px 5px 0px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p.centered {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- tables ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.docutils {
|
||||||
|
border: 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.align-center {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table caption span.caption-number {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
table caption span.caption-text {
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils td, table.docutils th {
|
||||||
|
padding: 1px 8px 1px 5px;
|
||||||
|
border-top: 0;
|
||||||
|
border-left: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-bottom: 1px solid #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.footnote td, table.footnote th {
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.citation {
|
||||||
|
border-left: solid 1px gray;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.citation td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- figures --------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.figure {
|
||||||
|
margin: 0.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.figure p.caption {
|
||||||
|
padding: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.figure p.caption span.caption-number {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.figure p.caption span.caption-text {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- field list styles ----------------------------------------------------- */
|
||||||
|
|
||||||
|
table.field-list td, table.field-list th {
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list ul {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-name {
|
||||||
|
-moz-hyphens: manual;
|
||||||
|
-ms-hyphens: manual;
|
||||||
|
-webkit-hyphens: manual;
|
||||||
|
hyphens: manual;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- hlist styles ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.hlist td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -- other body styles ----------------------------------------------------- */
|
||||||
|
|
||||||
|
ol.arabic {
|
||||||
|
list-style: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.loweralpha {
|
||||||
|
list-style: lower-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.upperalpha {
|
||||||
|
list-style: upper-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.lowerroman {
|
||||||
|
list-style: lower-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.upperroman {
|
||||||
|
list-style: upper-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd p {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd ul, dd table {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt:target, span.highlighted {
|
||||||
|
background-color: #fbe54e;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.highlighted {
|
||||||
|
fill: #fbe54e;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.glossary dt {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.optional {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-paren {
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
.versionmodified {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-message {
|
||||||
|
background-color: #fda;
|
||||||
|
padding: 5px;
|
||||||
|
border: 3px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footnote:target {
|
||||||
|
background-color: #ffa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-block {
|
||||||
|
display: block;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-block .line-block {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-left: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guilabel, .menuselection {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accelerator {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.classifier {
|
||||||
|
font-style: oblique;
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr, acronym {
|
||||||
|
border-bottom: dotted 1px;
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- code displays --------------------------------------------------------- */
|
||||||
|
|
||||||
|
pre {
|
||||||
|
overflow: auto;
|
||||||
|
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||||
|
}
|
||||||
|
|
||||||
|
span.pre {
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.linenos pre {
|
||||||
|
padding: 5px 0px;
|
||||||
|
border: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td {
|
||||||
|
padding: 0 0.5em 0 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption {
|
||||||
|
padding: 2px 5px;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption code {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption + div > div.highlight > pre {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption span.caption-number {
|
||||||
|
padding: 0.1em 0.3em;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption span.caption-text {
|
||||||
|
}
|
||||||
|
|
||||||
|
div.literal-block-wrapper {
|
||||||
|
padding: 1em 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.literal-block-wrapper div.highlight {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.descname {
|
||||||
|
background-color: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.descclassname {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.xref, a code {
|
||||||
|
background-color: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-link {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-back {
|
||||||
|
float: right;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.viewcode-block:target {
|
||||||
|
margin: -1px -10px;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- math display ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
img.math {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body div.math p {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.eqno {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.eqno a.headerlink {
|
||||||
|
position: relative;
|
||||||
|
left: 0px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.math:hover a.headerlink {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- printout stylesheet --------------------------------------------------- */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
div.document,
|
||||||
|
div.documentwrapper,
|
||||||
|
div.bodywrapper {
|
||||||
|
margin: 0 !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar,
|
||||||
|
div.related,
|
||||||
|
div.footer,
|
||||||
|
#top-link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
BIN
_static/bg-page.png
Normal file
After Width: | Height: | Size: 82 B |
BIN
_static/bullet_orange.png
Normal file
After Width: | Height: | Size: 165 B |
BIN
_static/comment-bright.png
Normal file
After Width: | Height: | Size: 756 B |
BIN
_static/comment-close.png
Normal file
After Width: | Height: | Size: 829 B |
BIN
_static/comment.png
Normal file
After Width: | Height: | Size: 641 B |
315
_static/doctools.js
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
/*
|
||||||
|
* doctools.js
|
||||||
|
* ~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx JavaScript utilities for all documentation.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* select a different prefix for underscore
|
||||||
|
*/
|
||||||
|
$u = _.noConflict();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* make the code below compatible with browsers without
|
||||||
|
* an installed firebug like debugger
|
||||||
|
if (!window.console || !console.firebug) {
|
||||||
|
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
||||||
|
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
|
||||||
|
"profile", "profileEnd"];
|
||||||
|
window.console = {};
|
||||||
|
for (var i = 0; i < names.length; ++i)
|
||||||
|
window.console[names[i]] = function() {};
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* small helper function to urldecode strings
|
||||||
|
*/
|
||||||
|
jQuery.urldecode = function(x) {
|
||||||
|
return decodeURIComponent(x).replace(/\+/g, ' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* small helper function to urlencode strings
|
||||||
|
*/
|
||||||
|
jQuery.urlencode = encodeURIComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns the parsed url parameters of the
|
||||||
|
* current request. Multiple values per key are supported,
|
||||||
|
* it will always return arrays of strings for the value parts.
|
||||||
|
*/
|
||||||
|
jQuery.getQueryParameters = function(s) {
|
||||||
|
if (typeof s === 'undefined')
|
||||||
|
s = document.location.search;
|
||||||
|
var parts = s.substr(s.indexOf('?') + 1).split('&');
|
||||||
|
var result = {};
|
||||||
|
for (var i = 0; i < parts.length; i++) {
|
||||||
|
var tmp = parts[i].split('=', 2);
|
||||||
|
var key = jQuery.urldecode(tmp[0]);
|
||||||
|
var value = jQuery.urldecode(tmp[1]);
|
||||||
|
if (key in result)
|
||||||
|
result[key].push(value);
|
||||||
|
else
|
||||||
|
result[key] = [value];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* highlight a given string on a jquery object by wrapping it in
|
||||||
|
* span elements with the given class name.
|
||||||
|
*/
|
||||||
|
jQuery.fn.highlightText = function(text, className) {
|
||||||
|
function highlight(node, addItems) {
|
||||||
|
if (node.nodeType === 3) {
|
||||||
|
var val = node.nodeValue;
|
||||||
|
var pos = val.toLowerCase().indexOf(text);
|
||||||
|
if (pos >= 0 &&
|
||||||
|
!jQuery(node.parentNode).hasClass(className) &&
|
||||||
|
!jQuery(node.parentNode).hasClass("nohighlight")) {
|
||||||
|
var span;
|
||||||
|
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
|
||||||
|
if (isInSVG) {
|
||||||
|
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
|
||||||
|
} else {
|
||||||
|
span = document.createElement("span");
|
||||||
|
span.className = className;
|
||||||
|
}
|
||||||
|
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
||||||
|
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
|
||||||
|
document.createTextNode(val.substr(pos + text.length)),
|
||||||
|
node.nextSibling));
|
||||||
|
node.nodeValue = val.substr(0, pos);
|
||||||
|
if (isInSVG) {
|
||||||
|
var bbox = span.getBBox();
|
||||||
|
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||||
|
rect.x.baseVal.value = bbox.x;
|
||||||
|
rect.y.baseVal.value = bbox.y;
|
||||||
|
rect.width.baseVal.value = bbox.width;
|
||||||
|
rect.height.baseVal.value = bbox.height;
|
||||||
|
rect.setAttribute('class', className);
|
||||||
|
var parentOfText = node.parentNode.parentNode;
|
||||||
|
addItems.push({
|
||||||
|
"parent": node.parentNode,
|
||||||
|
"target": rect});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!jQuery(node).is("button, select, textarea")) {
|
||||||
|
jQuery.each(node.childNodes, function() {
|
||||||
|
highlight(this, addItems);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var addItems = [];
|
||||||
|
var result = this.each(function() {
|
||||||
|
highlight(this, addItems);
|
||||||
|
});
|
||||||
|
for (var i = 0; i < addItems.length; ++i) {
|
||||||
|
jQuery(addItems[i].parent).before(addItems[i].target);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* backward compatibility for jQuery.browser
|
||||||
|
* This will be supported until firefox bug is fixed.
|
||||||
|
*/
|
||||||
|
if (!jQuery.browser) {
|
||||||
|
jQuery.uaMatch = function(ua) {
|
||||||
|
ua = ua.toLowerCase();
|
||||||
|
|
||||||
|
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
|
||||||
|
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
|
||||||
|
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
|
||||||
|
/(msie) ([\w.]+)/.exec(ua) ||
|
||||||
|
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
|
||||||
|
[];
|
||||||
|
|
||||||
|
return {
|
||||||
|
browser: match[ 1 ] || "",
|
||||||
|
version: match[ 2 ] || "0"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
jQuery.browser = {};
|
||||||
|
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small JavaScript module for the documentation.
|
||||||
|
*/
|
||||||
|
var Documentation = {
|
||||||
|
|
||||||
|
init : function() {
|
||||||
|
this.fixFirefoxAnchorBug();
|
||||||
|
this.highlightSearchWords();
|
||||||
|
this.initIndexTable();
|
||||||
|
if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
|
||||||
|
this.initOnKeyListeners();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i18n support
|
||||||
|
*/
|
||||||
|
TRANSLATIONS : {},
|
||||||
|
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
|
||||||
|
LOCALE : 'unknown',
|
||||||
|
|
||||||
|
// gettext and ngettext don't access this so that the functions
|
||||||
|
// can safely bound to a different name (_ = Documentation.gettext)
|
||||||
|
gettext : function(string) {
|
||||||
|
var translated = Documentation.TRANSLATIONS[string];
|
||||||
|
if (typeof translated === 'undefined')
|
||||||
|
return string;
|
||||||
|
return (typeof translated === 'string') ? translated : translated[0];
|
||||||
|
},
|
||||||
|
|
||||||
|
ngettext : function(singular, plural, n) {
|
||||||
|
var translated = Documentation.TRANSLATIONS[singular];
|
||||||
|
if (typeof translated === 'undefined')
|
||||||
|
return (n == 1) ? singular : plural;
|
||||||
|
return translated[Documentation.PLURALEXPR(n)];
|
||||||
|
},
|
||||||
|
|
||||||
|
addTranslations : function(catalog) {
|
||||||
|
for (var key in catalog.messages)
|
||||||
|
this.TRANSLATIONS[key] = catalog.messages[key];
|
||||||
|
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
|
||||||
|
this.LOCALE = catalog.locale;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add context elements like header anchor links
|
||||||
|
*/
|
||||||
|
addContextElements : function() {
|
||||||
|
$('div[id] > :header:first').each(function() {
|
||||||
|
$('<a class="headerlink">\u00B6</a>').
|
||||||
|
attr('href', '#' + this.id).
|
||||||
|
attr('title', _('Permalink to this headline')).
|
||||||
|
appendTo(this);
|
||||||
|
});
|
||||||
|
$('dt[id]').each(function() {
|
||||||
|
$('<a class="headerlink">\u00B6</a>').
|
||||||
|
attr('href', '#' + this.id).
|
||||||
|
attr('title', _('Permalink to this definition')).
|
||||||
|
appendTo(this);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* workaround a firefox stupidity
|
||||||
|
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
|
||||||
|
*/
|
||||||
|
fixFirefoxAnchorBug : function() {
|
||||||
|
if (document.location.hash && $.browser.mozilla)
|
||||||
|
window.setTimeout(function() {
|
||||||
|
document.location.href += '';
|
||||||
|
}, 10);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* highlight the search words provided in the url in the text
|
||||||
|
*/
|
||||||
|
highlightSearchWords : function() {
|
||||||
|
var params = $.getQueryParameters();
|
||||||
|
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
||||||
|
if (terms.length) {
|
||||||
|
var body = $('div.body');
|
||||||
|
if (!body.length) {
|
||||||
|
body = $('body');
|
||||||
|
}
|
||||||
|
window.setTimeout(function() {
|
||||||
|
$.each(terms, function() {
|
||||||
|
body.highlightText(this.toLowerCase(), 'highlighted');
|
||||||
|
});
|
||||||
|
}, 10);
|
||||||
|
$('<p class="highlight-link"><a href="javascript:Documentation.' +
|
||||||
|
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
|
||||||
|
.appendTo($('#searchbox'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init the domain index toggle buttons
|
||||||
|
*/
|
||||||
|
initIndexTable : function() {
|
||||||
|
var togglers = $('img.toggler').click(function() {
|
||||||
|
var src = $(this).attr('src');
|
||||||
|
var idnum = $(this).attr('id').substr(7);
|
||||||
|
$('tr.cg-' + idnum).toggle();
|
||||||
|
if (src.substr(-9) === 'minus.png')
|
||||||
|
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
|
||||||
|
else
|
||||||
|
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
|
||||||
|
}).css('display', '');
|
||||||
|
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
|
||||||
|
togglers.click();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to hide the search marks again
|
||||||
|
*/
|
||||||
|
hideSearchWords : function() {
|
||||||
|
$('#searchbox .highlight-link').fadeOut(300);
|
||||||
|
$('span.highlighted').removeClass('highlighted');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* make the url absolute
|
||||||
|
*/
|
||||||
|
makeURL : function(relativeURL) {
|
||||||
|
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the current relative url
|
||||||
|
*/
|
||||||
|
getCurrentURL : function() {
|
||||||
|
var path = document.location.pathname;
|
||||||
|
var parts = path.split(/\//);
|
||||||
|
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
|
||||||
|
if (this === '..')
|
||||||
|
parts.pop();
|
||||||
|
});
|
||||||
|
var url = parts.join('/');
|
||||||
|
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
initOnKeyListeners: function() {
|
||||||
|
$(document).keyup(function(event) {
|
||||||
|
var activeElementType = document.activeElement.tagName;
|
||||||
|
// don't navigate when in search box or textarea
|
||||||
|
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
|
||||||
|
switch (event.keyCode) {
|
||||||
|
case 37: // left
|
||||||
|
var prevHref = $('link[rel="prev"]').prop('href');
|
||||||
|
if (prevHref) {
|
||||||
|
window.location.href = prevHref;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 39: // right
|
||||||
|
var nextHref = $('link[rel="next"]').prop('href');
|
||||||
|
if (nextHref) {
|
||||||
|
window.location.href = nextHref;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// quick alias for translations
|
||||||
|
_ = Documentation.gettext;
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
Documentation.init();
|
||||||
|
});
|
10
_static/documentation_options.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
var DOCUMENTATION_OPTIONS = {
|
||||||
|
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||||
|
VERSION: '0.8.0',
|
||||||
|
LANGUAGE: 'None',
|
||||||
|
COLLAPSE_INDEX: false,
|
||||||
|
FILE_SUFFIX: '.html',
|
||||||
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: '.txt',
|
||||||
|
NAVIGATION_WITH_KEYS: false,
|
||||||
|
};
|
BIN
_static/down-pressed.png
Normal file
After Width: | Height: | Size: 222 B |
BIN
_static/down.png
Normal file
After Width: | Height: | Size: 202 B |
BIN
_static/file.png
Normal file
After Width: | Height: | Size: 286 B |
376
_static/haiku.css
Normal file
|
@ -0,0 +1,376 @@
|
||||||
|
/*
|
||||||
|
* haiku.css_t
|
||||||
|
* ~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx stylesheet -- haiku theme.
|
||||||
|
*
|
||||||
|
* Adapted from http://haiku-os.org/docs/Haiku-doc.css.
|
||||||
|
* Original copyright message:
|
||||||
|
*
|
||||||
|
* Copyright 2008-2009, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Francois Revol <revol@free.fr>
|
||||||
|
* Stephan Assmus <superstippi@gmx.de>
|
||||||
|
* Braden Ewing <brewin@gmail.com>
|
||||||
|
* Humdinger <humdingerb@gmail.com>
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import url("basic.css");
|
||||||
|
|
||||||
|
html {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
background: #FFF url(bg-page.png) top left repeat-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
line-height: 1.5;
|
||||||
|
margin: auto;
|
||||||
|
padding: 0px;
|
||||||
|
font-family: "DejaVu Sans", Arial, Helvetica, sans-serif;
|
||||||
|
min-width: 59em;
|
||||||
|
max-width: 70em;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footer {
|
||||||
|
padding: 8px;
|
||||||
|
font-size: 11px;
|
||||||
|
text-align: center;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* link colors and text decoration */
|
||||||
|
|
||||||
|
a:link {
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #dc3c01;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #892601;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover, a:active {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #ff4500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some headers act as anchors, don't give them a hover effect */
|
||||||
|
|
||||||
|
h1 a:hover, a:active {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #0c3762;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 a:hover, a:active {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #0c3762;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 a:hover, a:active {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #0c3762;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 a:hover, a:active {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #0c3762;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.headerlink {
|
||||||
|
color: #a7ce38;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.headerlink:hover {
|
||||||
|
color: #a7ce38;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* basic text elements */
|
||||||
|
|
||||||
|
div.content {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-left: 40px;
|
||||||
|
margin-right: 40px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* heading and navigation */
|
||||||
|
|
||||||
|
div.header {
|
||||||
|
position: relative;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
height: 85px;
|
||||||
|
/* background: #eeeeee; */
|
||||||
|
padding: 0 40px;
|
||||||
|
}
|
||||||
|
div.header h1 {
|
||||||
|
font-size: 1.6em;
|
||||||
|
font-weight: normal;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
color: #0c3762;
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
div.header h1 a {
|
||||||
|
font-weight: normal;
|
||||||
|
color: #0c3762;
|
||||||
|
}
|
||||||
|
div.header h2 {
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: normal;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #aaa;
|
||||||
|
border: 0;
|
||||||
|
margin-top: -3px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.header img.rightlogo {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.title {
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #0c3762;
|
||||||
|
border-bottom: dotted thin #e0e0e0;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
div.topnav {
|
||||||
|
/* background: #e0e0e0; */
|
||||||
|
}
|
||||||
|
div.topnav p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-left: 40px;
|
||||||
|
margin-right: 40px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
div.bottomnav {
|
||||||
|
background: #eeeeee;
|
||||||
|
}
|
||||||
|
div.bottomnav p {
|
||||||
|
margin-right: 40px;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.uplink {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* contents box */
|
||||||
|
|
||||||
|
table.index {
|
||||||
|
margin: 0px 0px 30px 30px;
|
||||||
|
padding: 1px;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: dotted;
|
||||||
|
border-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
table.index tr.heading {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
table.index tr.index {
|
||||||
|
background-color: #eeeeee;
|
||||||
|
}
|
||||||
|
table.index td {
|
||||||
|
padding: 5px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.index a:link, table.index a:visited {
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #dc3c01;
|
||||||
|
}
|
||||||
|
table.index a:hover, table.index a:active {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #ff4500;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Haiku User Guide styles and layout */
|
||||||
|
|
||||||
|
/* Rounded corner boxes */
|
||||||
|
/* Common declarations */
|
||||||
|
div.admonition {
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
-khtml-border-radius: 10px;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border-style: dotted;
|
||||||
|
border-width: thin;
|
||||||
|
border-color: #dcdcdc;
|
||||||
|
padding: 10px 15px 10px 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
div.note {
|
||||||
|
padding: 10px 15px 10px 80px;
|
||||||
|
background: #e4ffde url(alert_info_32.png) 15px 15px no-repeat;
|
||||||
|
min-height: 42px;
|
||||||
|
}
|
||||||
|
div.warning {
|
||||||
|
padding: 10px 15px 10px 80px;
|
||||||
|
background: #fffbc6 url(alert_warning_32.png) 15px 15px no-repeat;
|
||||||
|
min-height: 42px;
|
||||||
|
}
|
||||||
|
div.seealso {
|
||||||
|
background: #e4ffde;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* More layout and styles */
|
||||||
|
h1 {
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #0c3762;
|
||||||
|
border-bottom: dotted thin #e0e0e0;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #0c3762;
|
||||||
|
border-bottom: dotted thin #e0e0e0;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #0c3762;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 1.0em;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #0c3762;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.last {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-left: 5px;
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.content ul > li {
|
||||||
|
-moz-background-clip:border;
|
||||||
|
-moz-background-inline-policy:continuous;
|
||||||
|
-moz-background-origin:padding;
|
||||||
|
background: transparent url(bullet_orange.png) no-repeat scroll left 0.45em;
|
||||||
|
list-style-image: none;
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0 0 0 1.666em;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background-color: #e2e2e2;
|
||||||
|
font-size: 1.0em;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
border-color: #0c3762;
|
||||||
|
border-style: dotted;
|
||||||
|
border-width: thin;
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
padding: 0.8em;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-left: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* printer only pretty stuff */
|
||||||
|
@media print {
|
||||||
|
.noprint {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
/* for acronyms we want their definitions inlined at print time */
|
||||||
|
acronym[title]:after {
|
||||||
|
font-size: small;
|
||||||
|
content: " (" attr(title) ")";
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
/* and not have mozilla dotted underline */
|
||||||
|
acronym {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
div.topnav, div.bottomnav, div.header, table.index {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
div.content {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
background: #FFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-back {
|
||||||
|
font-family: "DejaVu Sans", Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.viewcode-block:target {
|
||||||
|
background-color: #f4debf;
|
||||||
|
border-top: 1px solid #ac9;
|
||||||
|
border-bottom: 1px solid #ac9;
|
||||||
|
margin: -1px -10px;
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* math display */
|
||||||
|
div.math p {
|
||||||
|
text-align: center;
|
||||||
|
}
|
10253
_static/jquery-3.2.1.js
vendored
Normal file
4
_static/jquery.js
vendored
Normal file
297
_static/language_data.js
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
/*
|
||||||
|
* language_data.js
|
||||||
|
* ~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* This script contains the language-specific data used by searchtools.js,
|
||||||
|
* namely the list of stopwords, stemmer, scorer and splitter.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
|
||||||
|
|
||||||
|
|
||||||
|
/* Non-minified version JS is _stemmer.js if file is provided */
|
||||||
|
/**
|
||||||
|
* Porter Stemmer
|
||||||
|
*/
|
||||||
|
var Stemmer = function() {
|
||||||
|
|
||||||
|
var step2list = {
|
||||||
|
ational: 'ate',
|
||||||
|
tional: 'tion',
|
||||||
|
enci: 'ence',
|
||||||
|
anci: 'ance',
|
||||||
|
izer: 'ize',
|
||||||
|
bli: 'ble',
|
||||||
|
alli: 'al',
|
||||||
|
entli: 'ent',
|
||||||
|
eli: 'e',
|
||||||
|
ousli: 'ous',
|
||||||
|
ization: 'ize',
|
||||||
|
ation: 'ate',
|
||||||
|
ator: 'ate',
|
||||||
|
alism: 'al',
|
||||||
|
iveness: 'ive',
|
||||||
|
fulness: 'ful',
|
||||||
|
ousness: 'ous',
|
||||||
|
aliti: 'al',
|
||||||
|
iviti: 'ive',
|
||||||
|
biliti: 'ble',
|
||||||
|
logi: 'log'
|
||||||
|
};
|
||||||
|
|
||||||
|
var step3list = {
|
||||||
|
icate: 'ic',
|
||||||
|
ative: '',
|
||||||
|
alize: 'al',
|
||||||
|
iciti: 'ic',
|
||||||
|
ical: 'ic',
|
||||||
|
ful: '',
|
||||||
|
ness: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
var c = "[^aeiou]"; // consonant
|
||||||
|
var v = "[aeiouy]"; // vowel
|
||||||
|
var C = c + "[^aeiouy]*"; // consonant sequence
|
||||||
|
var V = v + "[aeiou]*"; // vowel sequence
|
||||||
|
|
||||||
|
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
|
||||||
|
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
|
||||||
|
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
|
||||||
|
var s_v = "^(" + C + ")?" + v; // vowel in stem
|
||||||
|
|
||||||
|
this.stemWord = function (w) {
|
||||||
|
var stem;
|
||||||
|
var suffix;
|
||||||
|
var firstch;
|
||||||
|
var origword = w;
|
||||||
|
|
||||||
|
if (w.length < 3)
|
||||||
|
return w;
|
||||||
|
|
||||||
|
var re;
|
||||||
|
var re2;
|
||||||
|
var re3;
|
||||||
|
var re4;
|
||||||
|
|
||||||
|
firstch = w.substr(0,1);
|
||||||
|
if (firstch == "y")
|
||||||
|
w = firstch.toUpperCase() + w.substr(1);
|
||||||
|
|
||||||
|
// Step 1a
|
||||||
|
re = /^(.+?)(ss|i)es$/;
|
||||||
|
re2 = /^(.+?)([^s])s$/;
|
||||||
|
|
||||||
|
if (re.test(w))
|
||||||
|
w = w.replace(re,"$1$2");
|
||||||
|
else if (re2.test(w))
|
||||||
|
w = w.replace(re2,"$1$2");
|
||||||
|
|
||||||
|
// Step 1b
|
||||||
|
re = /^(.+?)eed$/;
|
||||||
|
re2 = /^(.+?)(ed|ing)$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
re = new RegExp(mgr0);
|
||||||
|
if (re.test(fp[1])) {
|
||||||
|
re = /.$/;
|
||||||
|
w = w.replace(re,"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (re2.test(w)) {
|
||||||
|
var fp = re2.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
re2 = new RegExp(s_v);
|
||||||
|
if (re2.test(stem)) {
|
||||||
|
w = stem;
|
||||||
|
re2 = /(at|bl|iz)$/;
|
||||||
|
re3 = new RegExp("([^aeiouylsz])\\1$");
|
||||||
|
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||||
|
if (re2.test(w))
|
||||||
|
w = w + "e";
|
||||||
|
else if (re3.test(w)) {
|
||||||
|
re = /.$/;
|
||||||
|
w = w.replace(re,"");
|
||||||
|
}
|
||||||
|
else if (re4.test(w))
|
||||||
|
w = w + "e";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1c
|
||||||
|
re = /^(.+?)y$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
re = new RegExp(s_v);
|
||||||
|
if (re.test(stem))
|
||||||
|
w = stem + "i";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2
|
||||||
|
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
suffix = fp[2];
|
||||||
|
re = new RegExp(mgr0);
|
||||||
|
if (re.test(stem))
|
||||||
|
w = stem + step2list[suffix];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3
|
||||||
|
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
suffix = fp[2];
|
||||||
|
re = new RegExp(mgr0);
|
||||||
|
if (re.test(stem))
|
||||||
|
w = stem + step3list[suffix];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4
|
||||||
|
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
|
||||||
|
re2 = /^(.+?)(s|t)(ion)$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
re = new RegExp(mgr1);
|
||||||
|
if (re.test(stem))
|
||||||
|
w = stem;
|
||||||
|
}
|
||||||
|
else if (re2.test(w)) {
|
||||||
|
var fp = re2.exec(w);
|
||||||
|
stem = fp[1] + fp[2];
|
||||||
|
re2 = new RegExp(mgr1);
|
||||||
|
if (re2.test(stem))
|
||||||
|
w = stem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5
|
||||||
|
re = /^(.+?)e$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
re = new RegExp(mgr1);
|
||||||
|
re2 = new RegExp(meq1);
|
||||||
|
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||||
|
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
|
||||||
|
w = stem;
|
||||||
|
}
|
||||||
|
re = /ll$/;
|
||||||
|
re2 = new RegExp(mgr1);
|
||||||
|
if (re.test(w) && re2.test(w)) {
|
||||||
|
re = /.$/;
|
||||||
|
w = w.replace(re,"");
|
||||||
|
}
|
||||||
|
|
||||||
|
// and turn initial Y back to y
|
||||||
|
if (firstch == "y")
|
||||||
|
w = firstch.toLowerCase() + w.substr(1);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var splitChars = (function() {
|
||||||
|
var result = {};
|
||||||
|
var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
|
||||||
|
1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
|
||||||
|
2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
|
||||||
|
2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
|
||||||
|
3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
|
||||||
|
3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
|
||||||
|
4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
|
||||||
|
8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
|
||||||
|
11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
|
||||||
|
43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
|
||||||
|
var i, j, start, end;
|
||||||
|
for (i = 0; i < singles.length; i++) {
|
||||||
|
result[singles[i]] = true;
|
||||||
|
}
|
||||||
|
var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
|
||||||
|
[722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
|
||||||
|
[1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
|
||||||
|
[1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
|
||||||
|
[1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
|
||||||
|
[2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
|
||||||
|
[2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
|
||||||
|
[2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
|
||||||
|
[2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
|
||||||
|
[2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
|
||||||
|
[2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
|
||||||
|
[2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
|
||||||
|
[3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
|
||||||
|
[3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
|
||||||
|
[3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
|
||||||
|
[3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
|
||||||
|
[3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
|
||||||
|
[3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
|
||||||
|
[4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
|
||||||
|
[4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
|
||||||
|
[4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
|
||||||
|
[4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
|
||||||
|
[5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
|
||||||
|
[6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
|
||||||
|
[6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
|
||||||
|
[6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
|
||||||
|
[6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
|
||||||
|
[7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
|
||||||
|
[7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
|
||||||
|
[8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
|
||||||
|
[8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
|
||||||
|
[8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
|
||||||
|
[10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
|
||||||
|
[11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
|
||||||
|
[12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
|
||||||
|
[12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
|
||||||
|
[12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
|
||||||
|
[19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
|
||||||
|
[42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
|
||||||
|
[42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
|
||||||
|
[43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
|
||||||
|
[43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
|
||||||
|
[43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
|
||||||
|
[43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
|
||||||
|
[44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
|
||||||
|
[57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
|
||||||
|
[64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
|
||||||
|
[65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
|
||||||
|
[65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
|
||||||
|
for (i = 0; i < ranges.length; i++) {
|
||||||
|
start = ranges[i][0];
|
||||||
|
end = ranges[i][1];
|
||||||
|
for (j = start; j <= end; j++) {
|
||||||
|
result[j] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
})();
|
||||||
|
|
||||||
|
function splitQuery(query) {
|
||||||
|
var result = [];
|
||||||
|
var start = -1;
|
||||||
|
for (var i = 0; i < query.length; i++) {
|
||||||
|
if (splitChars[query.charCodeAt(i)]) {
|
||||||
|
if (start !== -1) {
|
||||||
|
result.push(query.slice(start, i));
|
||||||
|
start = -1;
|
||||||
|
}
|
||||||
|
} else if (start === -1) {
|
||||||
|
start = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (start !== -1) {
|
||||||
|
result.push(query.slice(start));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
BIN
_static/minus.png
Normal file
After Width: | Height: | Size: 90 B |
BIN
_static/plus.png
Normal file
After Width: | Height: | Size: 90 B |
69
_static/pygments.css
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
.highlight .hll { background-color: #ffffcc }
|
||||||
|
.highlight { background: #eeffcc; }
|
||||||
|
.highlight .c { color: #408090; font-style: italic } /* Comment */
|
||||||
|
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||||
|
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
||||||
|
.highlight .o { color: #666666 } /* Operator */
|
||||||
|
.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
|
||||||
|
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
|
||||||
|
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
||||||
|
.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
|
||||||
|
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
|
||||||
|
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
|
||||||
|
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||||
|
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||||
|
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||||
|
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||||
|
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||||
|
.highlight .go { color: #333333 } /* Generic.Output */
|
||||||
|
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
||||||
|
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||||
|
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||||
|
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||||
|
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
||||||
|
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
||||||
|
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
||||||
|
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
|
||||||
|
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
||||||
|
.highlight .kt { color: #902000 } /* Keyword.Type */
|
||||||
|
.highlight .m { color: #208050 } /* Literal.Number */
|
||||||
|
.highlight .s { color: #4070a0 } /* Literal.String */
|
||||||
|
.highlight .na { color: #4070a0 } /* Name.Attribute */
|
||||||
|
.highlight .nb { color: #007020 } /* Name.Builtin */
|
||||||
|
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
||||||
|
.highlight .no { color: #60add5 } /* Name.Constant */
|
||||||
|
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
||||||
|
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
||||||
|
.highlight .ne { color: #007020 } /* Name.Exception */
|
||||||
|
.highlight .nf { color: #06287e } /* Name.Function */
|
||||||
|
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
|
||||||
|
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
||||||
|
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
|
||||||
|
.highlight .nv { color: #bb60d5 } /* Name.Variable */
|
||||||
|
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
|
||||||
|
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||||
|
.highlight .mb { color: #208050 } /* Literal.Number.Bin */
|
||||||
|
.highlight .mf { color: #208050 } /* Literal.Number.Float */
|
||||||
|
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
|
||||||
|
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
|
||||||
|
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
|
||||||
|
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||||
|
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
||||||
|
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
|
||||||
|
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||||
|
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
||||||
|
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||||
|
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
|
||||||
|
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
||||||
|
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
|
||||||
|
.highlight .sr { color: #235388 } /* Literal.String.Regex */
|
||||||
|
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
||||||
|
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
||||||
|
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .fm { color: #06287e } /* Name.Function.Magic */
|
||||||
|
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||||
|
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||||
|
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||||
|
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
|
||||||
|
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
|
481
_static/searchtools.js
Normal file
|
@ -0,0 +1,481 @@
|
||||||
|
/*
|
||||||
|
* searchtools.js
|
||||||
|
* ~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx JavaScript utilities for the full-text search.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!Scorer) {
|
||||||
|
/**
|
||||||
|
* Simple result scoring code.
|
||||||
|
*/
|
||||||
|
var Scorer = {
|
||||||
|
// Implement the following function to further tweak the score for each result
|
||||||
|
// The function takes a result array [filename, title, anchor, descr, score]
|
||||||
|
// and returns the new score.
|
||||||
|
/*
|
||||||
|
score: function(result) {
|
||||||
|
return result[4];
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
// query matches the full name of an object
|
||||||
|
objNameMatch: 11,
|
||||||
|
// or matches in the last dotted part of the object name
|
||||||
|
objPartialMatch: 6,
|
||||||
|
// Additive scores depending on the priority of the object
|
||||||
|
objPrio: {0: 15, // used to be importantResults
|
||||||
|
1: 5, // used to be objectResults
|
||||||
|
2: -5}, // used to be unimportantResults
|
||||||
|
// Used when the priority is not in the mapping.
|
||||||
|
objPrioDefault: 0,
|
||||||
|
|
||||||
|
// query found in title
|
||||||
|
title: 15,
|
||||||
|
// query found in terms
|
||||||
|
term: 5
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!splitQuery) {
|
||||||
|
function splitQuery(query) {
|
||||||
|
return query.split(/\s+/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search Module
|
||||||
|
*/
|
||||||
|
var Search = {
|
||||||
|
|
||||||
|
_index : null,
|
||||||
|
_queued_query : null,
|
||||||
|
_pulse_status : -1,
|
||||||
|
|
||||||
|
init : function() {
|
||||||
|
var params = $.getQueryParameters();
|
||||||
|
if (params.q) {
|
||||||
|
var query = params.q[0];
|
||||||
|
$('input[name="q"]')[0].value = query;
|
||||||
|
this.performSearch(query);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loadIndex : function(url) {
|
||||||
|
$.ajax({type: "GET", url: url, data: null,
|
||||||
|
dataType: "script", cache: true,
|
||||||
|
complete: function(jqxhr, textstatus) {
|
||||||
|
if (textstatus != "success") {
|
||||||
|
document.getElementById("searchindexloader").src = url;
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
},
|
||||||
|
|
||||||
|
setIndex : function(index) {
|
||||||
|
var q;
|
||||||
|
this._index = index;
|
||||||
|
if ((q = this._queued_query) !== null) {
|
||||||
|
this._queued_query = null;
|
||||||
|
Search.query(q);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
hasIndex : function() {
|
||||||
|
return this._index !== null;
|
||||||
|
},
|
||||||
|
|
||||||
|
deferQuery : function(query) {
|
||||||
|
this._queued_query = query;
|
||||||
|
},
|
||||||
|
|
||||||
|
stopPulse : function() {
|
||||||
|
this._pulse_status = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
startPulse : function() {
|
||||||
|
if (this._pulse_status >= 0)
|
||||||
|
return;
|
||||||
|
function pulse() {
|
||||||
|
var i;
|
||||||
|
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
||||||
|
var dotString = '';
|
||||||
|
for (i = 0; i < Search._pulse_status; i++)
|
||||||
|
dotString += '.';
|
||||||
|
Search.dots.text(dotString);
|
||||||
|
if (Search._pulse_status > -1)
|
||||||
|
window.setTimeout(pulse, 500);
|
||||||
|
}
|
||||||
|
pulse();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* perform a search for something (or wait until index is loaded)
|
||||||
|
*/
|
||||||
|
performSearch : function(query) {
|
||||||
|
// create the required interface elements
|
||||||
|
this.out = $('#search-results');
|
||||||
|
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
|
||||||
|
this.dots = $('<span></span>').appendTo(this.title);
|
||||||
|
this.status = $('<p style="display: none"></p>').appendTo(this.out);
|
||||||
|
this.output = $('<ul class="search"/>').appendTo(this.out);
|
||||||
|
|
||||||
|
$('#search-progress').text(_('Preparing search...'));
|
||||||
|
this.startPulse();
|
||||||
|
|
||||||
|
// index already loaded, the browser was quick!
|
||||||
|
if (this.hasIndex())
|
||||||
|
this.query(query);
|
||||||
|
else
|
||||||
|
this.deferQuery(query);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute search (requires search index to be loaded)
|
||||||
|
*/
|
||||||
|
query : function(query) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
// stem the searchterms and add them to the correct list
|
||||||
|
var stemmer = new Stemmer();
|
||||||
|
var searchterms = [];
|
||||||
|
var excluded = [];
|
||||||
|
var hlterms = [];
|
||||||
|
var tmp = splitQuery(query);
|
||||||
|
var objectterms = [];
|
||||||
|
for (i = 0; i < tmp.length; i++) {
|
||||||
|
if (tmp[i] !== "") {
|
||||||
|
objectterms.push(tmp[i].toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
|
||||||
|
tmp[i] === "") {
|
||||||
|
// skip this "word"
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// stem the word
|
||||||
|
var word = stemmer.stemWord(tmp[i].toLowerCase());
|
||||||
|
// prevent stemmer from cutting word smaller than two chars
|
||||||
|
if(word.length < 3 && tmp[i].length >= 3) {
|
||||||
|
word = tmp[i];
|
||||||
|
}
|
||||||
|
var toAppend;
|
||||||
|
// select the correct list
|
||||||
|
if (word[0] == '-') {
|
||||||
|
toAppend = excluded;
|
||||||
|
word = word.substr(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
toAppend = searchterms;
|
||||||
|
hlterms.push(tmp[i].toLowerCase());
|
||||||
|
}
|
||||||
|
// only add if not already in the list
|
||||||
|
if (!$u.contains(toAppend, word))
|
||||||
|
toAppend.push(word);
|
||||||
|
}
|
||||||
|
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
||||||
|
|
||||||
|
// console.debug('SEARCH: searching for:');
|
||||||
|
// console.info('required: ', searchterms);
|
||||||
|
// console.info('excluded: ', excluded);
|
||||||
|
|
||||||
|
// prepare search
|
||||||
|
var terms = this._index.terms;
|
||||||
|
var titleterms = this._index.titleterms;
|
||||||
|
|
||||||
|
// array of [filename, title, anchor, descr, score]
|
||||||
|
var results = [];
|
||||||
|
$('#search-progress').empty();
|
||||||
|
|
||||||
|
// lookup as object
|
||||||
|
for (i = 0; i < objectterms.length; i++) {
|
||||||
|
var others = [].concat(objectterms.slice(0, i),
|
||||||
|
objectterms.slice(i+1, objectterms.length));
|
||||||
|
results = results.concat(this.performObjectSearch(objectterms[i], others));
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookup as search terms in fulltext
|
||||||
|
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
|
||||||
|
|
||||||
|
// let the scorer override scores with a custom scoring function
|
||||||
|
if (Scorer.score) {
|
||||||
|
for (i = 0; i < results.length; i++)
|
||||||
|
results[i][4] = Scorer.score(results[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now sort the results by score (in opposite order of appearance, since the
|
||||||
|
// display function below uses pop() to retrieve items) and then
|
||||||
|
// alphabetically
|
||||||
|
results.sort(function(a, b) {
|
||||||
|
var left = a[4];
|
||||||
|
var right = b[4];
|
||||||
|
if (left > right) {
|
||||||
|
return 1;
|
||||||
|
} else if (left < right) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
// same score: sort alphabetically
|
||||||
|
left = a[1].toLowerCase();
|
||||||
|
right = b[1].toLowerCase();
|
||||||
|
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// for debugging
|
||||||
|
//Search.lastresults = results.slice(); // a copy
|
||||||
|
//console.info('search results:', Search.lastresults);
|
||||||
|
|
||||||
|
// print the results
|
||||||
|
var resultCount = results.length;
|
||||||
|
function displayNextItem() {
|
||||||
|
// results left, load the summary and display it
|
||||||
|
if (results.length) {
|
||||||
|
var item = results.pop();
|
||||||
|
var listItem = $('<li style="display:none"></li>');
|
||||||
|
if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
|
||||||
|
// dirhtml builder
|
||||||
|
var dirname = item[0] + '/';
|
||||||
|
if (dirname.match(/\/index\/$/)) {
|
||||||
|
dirname = dirname.substring(0, dirname.length-6);
|
||||||
|
} else if (dirname == 'index/') {
|
||||||
|
dirname = '';
|
||||||
|
}
|
||||||
|
listItem.append($('<a/>').attr('href',
|
||||||
|
DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
|
||||||
|
highlightstring + item[2]).html(item[1]));
|
||||||
|
} else {
|
||||||
|
// normal html builders
|
||||||
|
listItem.append($('<a/>').attr('href',
|
||||||
|
item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
|
||||||
|
highlightstring + item[2]).html(item[1]));
|
||||||
|
}
|
||||||
|
if (item[3]) {
|
||||||
|
listItem.append($('<span> (' + item[3] + ')</span>'));
|
||||||
|
Search.output.append(listItem);
|
||||||
|
listItem.slideDown(5, function() {
|
||||||
|
displayNextItem();
|
||||||
|
});
|
||||||
|
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
||||||
|
var suffix = DOCUMENTATION_OPTIONS.SOURCELINK_SUFFIX;
|
||||||
|
if (suffix === undefined) {
|
||||||
|
suffix = '.txt';
|
||||||
|
}
|
||||||
|
$.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[5] + (item[5].slice(-suffix.length) === suffix ? '' : suffix),
|
||||||
|
dataType: "text",
|
||||||
|
complete: function(jqxhr, textstatus) {
|
||||||
|
var data = jqxhr.responseText;
|
||||||
|
if (data !== '' && data !== undefined) {
|
||||||
|
listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
|
||||||
|
}
|
||||||
|
Search.output.append(listItem);
|
||||||
|
listItem.slideDown(5, function() {
|
||||||
|
displayNextItem();
|
||||||
|
});
|
||||||
|
}});
|
||||||
|
} else {
|
||||||
|
// no source available, just display title
|
||||||
|
Search.output.append(listItem);
|
||||||
|
listItem.slideDown(5, function() {
|
||||||
|
displayNextItem();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// search finished, update title and status message
|
||||||
|
else {
|
||||||
|
Search.stopPulse();
|
||||||
|
Search.title.text(_('Search Results'));
|
||||||
|
if (!resultCount)
|
||||||
|
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
|
||||||
|
else
|
||||||
|
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
|
||||||
|
Search.status.fadeIn(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayNextItem();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search for object names
|
||||||
|
*/
|
||||||
|
performObjectSearch : function(object, otherterms) {
|
||||||
|
var filenames = this._index.filenames;
|
||||||
|
var docnames = this._index.docnames;
|
||||||
|
var objects = this._index.objects;
|
||||||
|
var objnames = this._index.objnames;
|
||||||
|
var titles = this._index.titles;
|
||||||
|
|
||||||
|
var i;
|
||||||
|
var results = [];
|
||||||
|
|
||||||
|
for (var prefix in objects) {
|
||||||
|
for (var name in objects[prefix]) {
|
||||||
|
var fullname = (prefix ? prefix + '.' : '') + name;
|
||||||
|
if (fullname.toLowerCase().indexOf(object) > -1) {
|
||||||
|
var score = 0;
|
||||||
|
var parts = fullname.split('.');
|
||||||
|
// check for different match types: exact matches of full name or
|
||||||
|
// "last name" (i.e. last dotted part)
|
||||||
|
if (fullname == object || parts[parts.length - 1] == object) {
|
||||||
|
score += Scorer.objNameMatch;
|
||||||
|
// matches in last name
|
||||||
|
} else if (parts[parts.length - 1].indexOf(object) > -1) {
|
||||||
|
score += Scorer.objPartialMatch;
|
||||||
|
}
|
||||||
|
var match = objects[prefix][name];
|
||||||
|
var objname = objnames[match[1]][2];
|
||||||
|
var title = titles[match[0]];
|
||||||
|
// If more than one term searched for, we require other words to be
|
||||||
|
// found in the name/title/description
|
||||||
|
if (otherterms.length > 0) {
|
||||||
|
var haystack = (prefix + ' ' + name + ' ' +
|
||||||
|
objname + ' ' + title).toLowerCase();
|
||||||
|
var allfound = true;
|
||||||
|
for (i = 0; i < otherterms.length; i++) {
|
||||||
|
if (haystack.indexOf(otherterms[i]) == -1) {
|
||||||
|
allfound = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allfound) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var descr = objname + _(', in ') + title;
|
||||||
|
|
||||||
|
var anchor = match[3];
|
||||||
|
if (anchor === '')
|
||||||
|
anchor = fullname;
|
||||||
|
else if (anchor == '-')
|
||||||
|
anchor = objnames[match[1]][1] + '-' + fullname;
|
||||||
|
// add custom score for some objects according to scorer
|
||||||
|
if (Scorer.objPrio.hasOwnProperty(match[2])) {
|
||||||
|
score += Scorer.objPrio[match[2]];
|
||||||
|
} else {
|
||||||
|
score += Scorer.objPrioDefault;
|
||||||
|
}
|
||||||
|
results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search for full-text terms in the index
|
||||||
|
*/
|
||||||
|
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
|
||||||
|
var docnames = this._index.docnames;
|
||||||
|
var filenames = this._index.filenames;
|
||||||
|
var titles = this._index.titles;
|
||||||
|
|
||||||
|
var i, j, file;
|
||||||
|
var fileMap = {};
|
||||||
|
var scoreMap = {};
|
||||||
|
var results = [];
|
||||||
|
|
||||||
|
// perform the search on the required terms
|
||||||
|
for (i = 0; i < searchterms.length; i++) {
|
||||||
|
var word = searchterms[i];
|
||||||
|
var files = [];
|
||||||
|
var _o = [
|
||||||
|
{files: terms[word], score: Scorer.term},
|
||||||
|
{files: titleterms[word], score: Scorer.title}
|
||||||
|
];
|
||||||
|
|
||||||
|
// no match but word was a required one
|
||||||
|
if ($u.every(_o, function(o){return o.files === undefined;})) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// found search word in contents
|
||||||
|
$u.each(_o, function(o) {
|
||||||
|
var _files = o.files;
|
||||||
|
if (_files === undefined)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (_files.length === undefined)
|
||||||
|
_files = [_files];
|
||||||
|
files = files.concat(_files);
|
||||||
|
|
||||||
|
// set score for the word in each file to Scorer.term
|
||||||
|
for (j = 0; j < _files.length; j++) {
|
||||||
|
file = _files[j];
|
||||||
|
if (!(file in scoreMap))
|
||||||
|
scoreMap[file] = {}
|
||||||
|
scoreMap[file][word] = o.score;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// create the mapping
|
||||||
|
for (j = 0; j < files.length; j++) {
|
||||||
|
file = files[j];
|
||||||
|
if (file in fileMap)
|
||||||
|
fileMap[file].push(word);
|
||||||
|
else
|
||||||
|
fileMap[file] = [word];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now check if the files don't contain excluded terms
|
||||||
|
for (file in fileMap) {
|
||||||
|
var valid = true;
|
||||||
|
|
||||||
|
// check if all requirements are matched
|
||||||
|
if (fileMap[file].length != searchterms.length)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// ensure that none of the excluded terms is in the search result
|
||||||
|
for (i = 0; i < excluded.length; i++) {
|
||||||
|
if (terms[excluded[i]] == file ||
|
||||||
|
titleterms[excluded[i]] == file ||
|
||||||
|
$u.contains(terms[excluded[i]] || [], file) ||
|
||||||
|
$u.contains(titleterms[excluded[i]] || [], file)) {
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have still a valid result we can add it to the result list
|
||||||
|
if (valid) {
|
||||||
|
// select one (max) score for the file.
|
||||||
|
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
|
||||||
|
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
|
||||||
|
results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to return a node containing the
|
||||||
|
* search summary for a given text. keywords is a list
|
||||||
|
* of stemmed words, hlwords is the list of normal, unstemmed
|
||||||
|
* words. the first one is used to find the occurrence, the
|
||||||
|
* latter for highlighting it.
|
||||||
|
*/
|
||||||
|
makeSearchSummary : function(text, keywords, hlwords) {
|
||||||
|
var textLower = text.toLowerCase();
|
||||||
|
var start = 0;
|
||||||
|
$.each(keywords, function() {
|
||||||
|
var i = textLower.indexOf(this.toLowerCase());
|
||||||
|
if (i > -1)
|
||||||
|
start = i;
|
||||||
|
});
|
||||||
|
start = Math.max(start - 120, 0);
|
||||||
|
var excerpt = ((start > 0) ? '...' : '') +
|
||||||
|
$.trim(text.substr(start, 240)) +
|
||||||
|
((start + 240 - text.length) ? '...' : '');
|
||||||
|
var rv = $('<div class="context"></div>').text(excerpt);
|
||||||
|
$.each(hlwords, function() {
|
||||||
|
rv = rv.highlightText(this, 'highlighted');
|
||||||
|
});
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
Search.init();
|
||||||
|
});
|
999
_static/underscore-1.3.1.js
Normal file
|
@ -0,0 +1,999 @@
|
||||||
|
// Underscore.js 1.3.1
|
||||||
|
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||||
|
// Underscore is freely distributable under the MIT license.
|
||||||
|
// Portions of Underscore are inspired or borrowed from Prototype,
|
||||||
|
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||||
|
// For all details and documentation:
|
||||||
|
// http://documentcloud.github.com/underscore
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
// Baseline setup
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
// Establish the root object, `window` in the browser, or `global` on the server.
|
||||||
|
var root = this;
|
||||||
|
|
||||||
|
// Save the previous value of the `_` variable.
|
||||||
|
var previousUnderscore = root._;
|
||||||
|
|
||||||
|
// Establish the object that gets returned to break out of a loop iteration.
|
||||||
|
var breaker = {};
|
||||||
|
|
||||||
|
// Save bytes in the minified (but not gzipped) version:
|
||||||
|
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
||||||
|
|
||||||
|
// Create quick reference variables for speed access to core prototypes.
|
||||||
|
var slice = ArrayProto.slice,
|
||||||
|
unshift = ArrayProto.unshift,
|
||||||
|
toString = ObjProto.toString,
|
||||||
|
hasOwnProperty = ObjProto.hasOwnProperty;
|
||||||
|
|
||||||
|
// All **ECMAScript 5** native function implementations that we hope to use
|
||||||
|
// are declared here.
|
||||||
|
var
|
||||||
|
nativeForEach = ArrayProto.forEach,
|
||||||
|
nativeMap = ArrayProto.map,
|
||||||
|
nativeReduce = ArrayProto.reduce,
|
||||||
|
nativeReduceRight = ArrayProto.reduceRight,
|
||||||
|
nativeFilter = ArrayProto.filter,
|
||||||
|
nativeEvery = ArrayProto.every,
|
||||||
|
nativeSome = ArrayProto.some,
|
||||||
|
nativeIndexOf = ArrayProto.indexOf,
|
||||||
|
nativeLastIndexOf = ArrayProto.lastIndexOf,
|
||||||
|
nativeIsArray = Array.isArray,
|
||||||
|
nativeKeys = Object.keys,
|
||||||
|
nativeBind = FuncProto.bind;
|
||||||
|
|
||||||
|
// Create a safe reference to the Underscore object for use below.
|
||||||
|
var _ = function(obj) { return new wrapper(obj); };
|
||||||
|
|
||||||
|
// Export the Underscore object for **Node.js**, with
|
||||||
|
// backwards-compatibility for the old `require()` API. If we're in
|
||||||
|
// the browser, add `_` as a global object via a string identifier,
|
||||||
|
// for Closure Compiler "advanced" mode.
|
||||||
|
if (typeof exports !== 'undefined') {
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
exports = module.exports = _;
|
||||||
|
}
|
||||||
|
exports._ = _;
|
||||||
|
} else {
|
||||||
|
root['_'] = _;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current version.
|
||||||
|
_.VERSION = '1.3.1';
|
||||||
|
|
||||||
|
// Collection Functions
|
||||||
|
// --------------------
|
||||||
|
|
||||||
|
// The cornerstone, an `each` implementation, aka `forEach`.
|
||||||
|
// Handles objects with the built-in `forEach`, arrays, and raw objects.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
||||||
|
var each = _.each = _.forEach = function(obj, iterator, context) {
|
||||||
|
if (obj == null) return;
|
||||||
|
if (nativeForEach && obj.forEach === nativeForEach) {
|
||||||
|
obj.forEach(iterator, context);
|
||||||
|
} else if (obj.length === +obj.length) {
|
||||||
|
for (var i = 0, l = obj.length; i < l; i++) {
|
||||||
|
if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var key in obj) {
|
||||||
|
if (_.has(obj, key)) {
|
||||||
|
if (iterator.call(context, obj[key], key, obj) === breaker) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the results of applying the iterator to each element.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `map` if available.
|
||||||
|
_.map = _.collect = function(obj, iterator, context) {
|
||||||
|
var results = [];
|
||||||
|
if (obj == null) return results;
|
||||||
|
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
results[results.length] = iterator.call(context, value, index, list);
|
||||||
|
});
|
||||||
|
if (obj.length === +obj.length) results.length = obj.length;
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
||||||
|
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
||||||
|
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
||||||
|
var initial = arguments.length > 2;
|
||||||
|
if (obj == null) obj = [];
|
||||||
|
if (nativeReduce && obj.reduce === nativeReduce) {
|
||||||
|
if (context) iterator = _.bind(iterator, context);
|
||||||
|
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
|
||||||
|
}
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (!initial) {
|
||||||
|
memo = value;
|
||||||
|
initial = true;
|
||||||
|
} else {
|
||||||
|
memo = iterator.call(context, memo, value, index, list);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
|
||||||
|
return memo;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The right-associative version of reduce, also known as `foldr`.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
|
||||||
|
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
||||||
|
var initial = arguments.length > 2;
|
||||||
|
if (obj == null) obj = [];
|
||||||
|
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
||||||
|
if (context) iterator = _.bind(iterator, context);
|
||||||
|
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||||
|
}
|
||||||
|
var reversed = _.toArray(obj).reverse();
|
||||||
|
if (context && !initial) iterator = _.bind(iterator, context);
|
||||||
|
return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the first value which passes a truth test. Aliased as `detect`.
|
||||||
|
_.find = _.detect = function(obj, iterator, context) {
|
||||||
|
var result;
|
||||||
|
any(obj, function(value, index, list) {
|
||||||
|
if (iterator.call(context, value, index, list)) {
|
||||||
|
result = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return all the elements that pass a truth test.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `filter` if available.
|
||||||
|
// Aliased as `select`.
|
||||||
|
_.filter = _.select = function(obj, iterator, context) {
|
||||||
|
var results = [];
|
||||||
|
if (obj == null) return results;
|
||||||
|
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (iterator.call(context, value, index, list)) results[results.length] = value;
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return all the elements for which a truth test fails.
|
||||||
|
_.reject = function(obj, iterator, context) {
|
||||||
|
var results = [];
|
||||||
|
if (obj == null) return results;
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (!iterator.call(context, value, index, list)) results[results.length] = value;
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine whether all of the elements match a truth test.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `every` if available.
|
||||||
|
// Aliased as `all`.
|
||||||
|
_.every = _.all = function(obj, iterator, context) {
|
||||||
|
var result = true;
|
||||||
|
if (obj == null) return result;
|
||||||
|
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine if at least one element in the object matches a truth test.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `some` if available.
|
||||||
|
// Aliased as `any`.
|
||||||
|
var any = _.some = _.any = function(obj, iterator, context) {
|
||||||
|
iterator || (iterator = _.identity);
|
||||||
|
var result = false;
|
||||||
|
if (obj == null) return result;
|
||||||
|
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (result || (result = iterator.call(context, value, index, list))) return breaker;
|
||||||
|
});
|
||||||
|
return !!result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine if a given value is included in the array or object using `===`.
|
||||||
|
// Aliased as `contains`.
|
||||||
|
_.include = _.contains = function(obj, target) {
|
||||||
|
var found = false;
|
||||||
|
if (obj == null) return found;
|
||||||
|
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||||
|
found = any(obj, function(value) {
|
||||||
|
return value === target;
|
||||||
|
});
|
||||||
|
return found;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invoke a method (with arguments) on every item in a collection.
|
||||||
|
_.invoke = function(obj, method) {
|
||||||
|
var args = slice.call(arguments, 2);
|
||||||
|
return _.map(obj, function(value) {
|
||||||
|
return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convenience version of a common use case of `map`: fetching a property.
|
||||||
|
_.pluck = function(obj, key) {
|
||||||
|
return _.map(obj, function(value){ return value[key]; });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the maximum element or (element-based computation).
|
||||||
|
_.max = function(obj, iterator, context) {
|
||||||
|
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
||||||
|
if (!iterator && _.isEmpty(obj)) return -Infinity;
|
||||||
|
var result = {computed : -Infinity};
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||||
|
computed >= result.computed && (result = {value : value, computed : computed});
|
||||||
|
});
|
||||||
|
return result.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the minimum element (or element-based computation).
|
||||||
|
_.min = function(obj, iterator, context) {
|
||||||
|
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
||||||
|
if (!iterator && _.isEmpty(obj)) return Infinity;
|
||||||
|
var result = {computed : Infinity};
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||||
|
computed < result.computed && (result = {value : value, computed : computed});
|
||||||
|
});
|
||||||
|
return result.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shuffle an array.
|
||||||
|
_.shuffle = function(obj) {
|
||||||
|
var shuffled = [], rand;
|
||||||
|
each(obj, function(value, index, list) {
|
||||||
|
if (index == 0) {
|
||||||
|
shuffled[0] = value;
|
||||||
|
} else {
|
||||||
|
rand = Math.floor(Math.random() * (index + 1));
|
||||||
|
shuffled[index] = shuffled[rand];
|
||||||
|
shuffled[rand] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return shuffled;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sort the object's values by a criterion produced by an iterator.
|
||||||
|
_.sortBy = function(obj, iterator, context) {
|
||||||
|
return _.pluck(_.map(obj, function(value, index, list) {
|
||||||
|
return {
|
||||||
|
value : value,
|
||||||
|
criteria : iterator.call(context, value, index, list)
|
||||||
|
};
|
||||||
|
}).sort(function(left, right) {
|
||||||
|
var a = left.criteria, b = right.criteria;
|
||||||
|
return a < b ? -1 : a > b ? 1 : 0;
|
||||||
|
}), 'value');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Groups the object's values by a criterion. Pass either a string attribute
|
||||||
|
// to group by, or a function that returns the criterion.
|
||||||
|
_.groupBy = function(obj, val) {
|
||||||
|
var result = {};
|
||||||
|
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
|
||||||
|
each(obj, function(value, index) {
|
||||||
|
var key = iterator(value, index);
|
||||||
|
(result[key] || (result[key] = [])).push(value);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use a comparator function to figure out at what index an object should
|
||||||
|
// be inserted so as to maintain order. Uses binary search.
|
||||||
|
_.sortedIndex = function(array, obj, iterator) {
|
||||||
|
iterator || (iterator = _.identity);
|
||||||
|
var low = 0, high = array.length;
|
||||||
|
while (low < high) {
|
||||||
|
var mid = (low + high) >> 1;
|
||||||
|
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Safely convert anything iterable into a real, live array.
|
||||||
|
_.toArray = function(iterable) {
|
||||||
|
if (!iterable) return [];
|
||||||
|
if (iterable.toArray) return iterable.toArray();
|
||||||
|
if (_.isArray(iterable)) return slice.call(iterable);
|
||||||
|
if (_.isArguments(iterable)) return slice.call(iterable);
|
||||||
|
return _.values(iterable);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the number of elements in an object.
|
||||||
|
_.size = function(obj) {
|
||||||
|
return _.toArray(obj).length;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Array Functions
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
// Get the first element of an array. Passing **n** will return the first N
|
||||||
|
// values in the array. Aliased as `head`. The **guard** check allows it to work
|
||||||
|
// with `_.map`.
|
||||||
|
_.first = _.head = function(array, n, guard) {
|
||||||
|
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns everything but the last entry of the array. Especcialy useful on
|
||||||
|
// the arguments object. Passing **n** will return all the values in
|
||||||
|
// the array, excluding the last N. The **guard** check allows it to work with
|
||||||
|
// `_.map`.
|
||||||
|
_.initial = function(array, n, guard) {
|
||||||
|
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the last element of an array. Passing **n** will return the last N
|
||||||
|
// values in the array. The **guard** check allows it to work with `_.map`.
|
||||||
|
_.last = function(array, n, guard) {
|
||||||
|
if ((n != null) && !guard) {
|
||||||
|
return slice.call(array, Math.max(array.length - n, 0));
|
||||||
|
} else {
|
||||||
|
return array[array.length - 1];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns everything but the first entry of the array. Aliased as `tail`.
|
||||||
|
// Especially useful on the arguments object. Passing an **index** will return
|
||||||
|
// the rest of the values in the array from that index onward. The **guard**
|
||||||
|
// check allows it to work with `_.map`.
|
||||||
|
_.rest = _.tail = function(array, index, guard) {
|
||||||
|
return slice.call(array, (index == null) || guard ? 1 : index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Trim out all falsy values from an array.
|
||||||
|
_.compact = function(array) {
|
||||||
|
return _.filter(array, function(value){ return !!value; });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a completely flattened version of an array.
|
||||||
|
_.flatten = function(array, shallow) {
|
||||||
|
return _.reduce(array, function(memo, value) {
|
||||||
|
if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
|
||||||
|
memo[memo.length] = value;
|
||||||
|
return memo;
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a version of the array that does not contain the specified value(s).
|
||||||
|
_.without = function(array) {
|
||||||
|
return _.difference(array, slice.call(arguments, 1));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Produce a duplicate-free version of the array. If the array has already
|
||||||
|
// been sorted, you have the option of using a faster algorithm.
|
||||||
|
// Aliased as `unique`.
|
||||||
|
_.uniq = _.unique = function(array, isSorted, iterator) {
|
||||||
|
var initial = iterator ? _.map(array, iterator) : array;
|
||||||
|
var result = [];
|
||||||
|
_.reduce(initial, function(memo, el, i) {
|
||||||
|
if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
|
||||||
|
memo[memo.length] = el;
|
||||||
|
result[result.length] = array[i];
|
||||||
|
}
|
||||||
|
return memo;
|
||||||
|
}, []);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Produce an array that contains the union: each distinct element from all of
|
||||||
|
// the passed-in arrays.
|
||||||
|
_.union = function() {
|
||||||
|
return _.uniq(_.flatten(arguments, true));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Produce an array that contains every item shared between all the
|
||||||
|
// passed-in arrays. (Aliased as "intersect" for back-compat.)
|
||||||
|
_.intersection = _.intersect = function(array) {
|
||||||
|
var rest = slice.call(arguments, 1);
|
||||||
|
return _.filter(_.uniq(array), function(item) {
|
||||||
|
return _.every(rest, function(other) {
|
||||||
|
return _.indexOf(other, item) >= 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Take the difference between one array and a number of other arrays.
|
||||||
|
// Only the elements present in just the first array will remain.
|
||||||
|
_.difference = function(array) {
|
||||||
|
var rest = _.flatten(slice.call(arguments, 1));
|
||||||
|
return _.filter(array, function(value){ return !_.include(rest, value); });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Zip together multiple lists into a single array -- elements that share
|
||||||
|
// an index go together.
|
||||||
|
_.zip = function() {
|
||||||
|
var args = slice.call(arguments);
|
||||||
|
var length = _.max(_.pluck(args, 'length'));
|
||||||
|
var results = new Array(length);
|
||||||
|
for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
|
||||||
|
// we need this function. Return the position of the first occurrence of an
|
||||||
|
// item in an array, or -1 if the item is not included in the array.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
|
||||||
|
// If the array is large and already in sort order, pass `true`
|
||||||
|
// for **isSorted** to use binary search.
|
||||||
|
_.indexOf = function(array, item, isSorted) {
|
||||||
|
if (array == null) return -1;
|
||||||
|
var i, l;
|
||||||
|
if (isSorted) {
|
||||||
|
i = _.sortedIndex(array, item);
|
||||||
|
return array[i] === item ? i : -1;
|
||||||
|
}
|
||||||
|
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
||||||
|
for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
||||||
|
_.lastIndexOf = function(array, item) {
|
||||||
|
if (array == null) return -1;
|
||||||
|
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
|
||||||
|
var i = array.length;
|
||||||
|
while (i--) if (i in array && array[i] === item) return i;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate an integer Array containing an arithmetic progression. A port of
|
||||||
|
// the native Python `range()` function. See
|
||||||
|
// [the Python documentation](http://docs.python.org/library/functions.html#range).
|
||||||
|
_.range = function(start, stop, step) {
|
||||||
|
if (arguments.length <= 1) {
|
||||||
|
stop = start || 0;
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
step = arguments[2] || 1;
|
||||||
|
|
||||||
|
var len = Math.max(Math.ceil((stop - start) / step), 0);
|
||||||
|
var idx = 0;
|
||||||
|
var range = new Array(len);
|
||||||
|
|
||||||
|
while(idx < len) {
|
||||||
|
range[idx++] = start;
|
||||||
|
start += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
return range;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function (ahem) Functions
|
||||||
|
// ------------------
|
||||||
|
|
||||||
|
// Reusable constructor function for prototype setting.
|
||||||
|
var ctor = function(){};
|
||||||
|
|
||||||
|
// Create a function bound to a given object (assigning `this`, and arguments,
|
||||||
|
// optionally). Binding with arguments is also known as `curry`.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `Function.bind` if available.
|
||||||
|
// We check for `func.bind` first, to fail fast when `func` is undefined.
|
||||||
|
_.bind = function bind(func, context) {
|
||||||
|
var bound, args;
|
||||||
|
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
||||||
|
if (!_.isFunction(func)) throw new TypeError;
|
||||||
|
args = slice.call(arguments, 2);
|
||||||
|
return bound = function() {
|
||||||
|
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
|
||||||
|
ctor.prototype = func.prototype;
|
||||||
|
var self = new ctor;
|
||||||
|
var result = func.apply(self, args.concat(slice.call(arguments)));
|
||||||
|
if (Object(result) === result) return result;
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bind all of an object's methods to that object. Useful for ensuring that
|
||||||
|
// all callbacks defined on an object belong to it.
|
||||||
|
_.bindAll = function(obj) {
|
||||||
|
var funcs = slice.call(arguments, 1);
|
||||||
|
if (funcs.length == 0) funcs = _.functions(obj);
|
||||||
|
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Memoize an expensive function by storing its results.
|
||||||
|
_.memoize = function(func, hasher) {
|
||||||
|
var memo = {};
|
||||||
|
hasher || (hasher = _.identity);
|
||||||
|
return function() {
|
||||||
|
var key = hasher.apply(this, arguments);
|
||||||
|
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delays a function for the given number of milliseconds, and then calls
|
||||||
|
// it with the arguments supplied.
|
||||||
|
_.delay = function(func, wait) {
|
||||||
|
var args = slice.call(arguments, 2);
|
||||||
|
return setTimeout(function(){ return func.apply(func, args); }, wait);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defers a function, scheduling it to run after the current call stack has
|
||||||
|
// cleared.
|
||||||
|
_.defer = function(func) {
|
||||||
|
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function, that, when invoked, will only be triggered at most once
|
||||||
|
// during a given window of time.
|
||||||
|
_.throttle = function(func, wait) {
|
||||||
|
var context, args, timeout, throttling, more;
|
||||||
|
var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
|
||||||
|
return function() {
|
||||||
|
context = this; args = arguments;
|
||||||
|
var later = function() {
|
||||||
|
timeout = null;
|
||||||
|
if (more) func.apply(context, args);
|
||||||
|
whenDone();
|
||||||
|
};
|
||||||
|
if (!timeout) timeout = setTimeout(later, wait);
|
||||||
|
if (throttling) {
|
||||||
|
more = true;
|
||||||
|
} else {
|
||||||
|
func.apply(context, args);
|
||||||
|
}
|
||||||
|
whenDone();
|
||||||
|
throttling = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function, that, as long as it continues to be invoked, will not
|
||||||
|
// be triggered. The function will be called after it stops being called for
|
||||||
|
// N milliseconds.
|
||||||
|
_.debounce = function(func, wait) {
|
||||||
|
var timeout;
|
||||||
|
return function() {
|
||||||
|
var context = this, args = arguments;
|
||||||
|
var later = function() {
|
||||||
|
timeout = null;
|
||||||
|
func.apply(context, args);
|
||||||
|
};
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(later, wait);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function that will be executed at most one time, no matter how
|
||||||
|
// often you call it. Useful for lazy initialization.
|
||||||
|
_.once = function(func) {
|
||||||
|
var ran = false, memo;
|
||||||
|
return function() {
|
||||||
|
if (ran) return memo;
|
||||||
|
ran = true;
|
||||||
|
return memo = func.apply(this, arguments);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the first function passed as an argument to the second,
|
||||||
|
// allowing you to adjust arguments, run code before and after, and
|
||||||
|
// conditionally execute the original function.
|
||||||
|
_.wrap = function(func, wrapper) {
|
||||||
|
return function() {
|
||||||
|
var args = [func].concat(slice.call(arguments, 0));
|
||||||
|
return wrapper.apply(this, args);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function that is the composition of a list of functions, each
|
||||||
|
// consuming the return value of the function that follows.
|
||||||
|
_.compose = function() {
|
||||||
|
var funcs = arguments;
|
||||||
|
return function() {
|
||||||
|
var args = arguments;
|
||||||
|
for (var i = funcs.length - 1; i >= 0; i--) {
|
||||||
|
args = [funcs[i].apply(this, args)];
|
||||||
|
}
|
||||||
|
return args[0];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a function that will only be executed after being called N times.
|
||||||
|
_.after = function(times, func) {
|
||||||
|
if (times <= 0) return func();
|
||||||
|
return function() {
|
||||||
|
if (--times < 1) { return func.apply(this, arguments); }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Object Functions
|
||||||
|
// ----------------
|
||||||
|
|
||||||
|
// Retrieve the names of an object's properties.
|
||||||
|
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
||||||
|
_.keys = nativeKeys || function(obj) {
|
||||||
|
if (obj !== Object(obj)) throw new TypeError('Invalid object');
|
||||||
|
var keys = [];
|
||||||
|
for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
|
||||||
|
return keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Retrieve the values of an object's properties.
|
||||||
|
_.values = function(obj) {
|
||||||
|
return _.map(obj, _.identity);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a sorted list of the function names available on the object.
|
||||||
|
// Aliased as `methods`
|
||||||
|
_.functions = _.methods = function(obj) {
|
||||||
|
var names = [];
|
||||||
|
for (var key in obj) {
|
||||||
|
if (_.isFunction(obj[key])) names.push(key);
|
||||||
|
}
|
||||||
|
return names.sort();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extend a given object with all the properties in passed-in object(s).
|
||||||
|
_.extend = function(obj) {
|
||||||
|
each(slice.call(arguments, 1), function(source) {
|
||||||
|
for (var prop in source) {
|
||||||
|
obj[prop] = source[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fill in a given object with default properties.
|
||||||
|
_.defaults = function(obj) {
|
||||||
|
each(slice.call(arguments, 1), function(source) {
|
||||||
|
for (var prop in source) {
|
||||||
|
if (obj[prop] == null) obj[prop] = source[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a (shallow-cloned) duplicate of an object.
|
||||||
|
_.clone = function(obj) {
|
||||||
|
if (!_.isObject(obj)) return obj;
|
||||||
|
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invokes interceptor with the obj, and then returns obj.
|
||||||
|
// The primary purpose of this method is to "tap into" a method chain, in
|
||||||
|
// order to perform operations on intermediate results within the chain.
|
||||||
|
_.tap = function(obj, interceptor) {
|
||||||
|
interceptor(obj);
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal recursive comparison function.
|
||||||
|
function eq(a, b, stack) {
|
||||||
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
||||||
|
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
|
||||||
|
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
||||||
|
// A strict comparison is necessary because `null == undefined`.
|
||||||
|
if (a == null || b == null) return a === b;
|
||||||
|
// Unwrap any wrapped objects.
|
||||||
|
if (a._chain) a = a._wrapped;
|
||||||
|
if (b._chain) b = b._wrapped;
|
||||||
|
// Invoke a custom `isEqual` method if one is provided.
|
||||||
|
if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
|
||||||
|
if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
|
||||||
|
// Compare `[[Class]]` names.
|
||||||
|
var className = toString.call(a);
|
||||||
|
if (className != toString.call(b)) return false;
|
||||||
|
switch (className) {
|
||||||
|
// Strings, numbers, dates, and booleans are compared by value.
|
||||||
|
case '[object String]':
|
||||||
|
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
||||||
|
// equivalent to `new String("5")`.
|
||||||
|
return a == String(b);
|
||||||
|
case '[object Number]':
|
||||||
|
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
|
||||||
|
// other numeric values.
|
||||||
|
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
|
||||||
|
case '[object Date]':
|
||||||
|
case '[object Boolean]':
|
||||||
|
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
|
||||||
|
// millisecond representations. Note that invalid dates with millisecond representations
|
||||||
|
// of `NaN` are not equivalent.
|
||||||
|
return +a == +b;
|
||||||
|
// RegExps are compared by their source patterns and flags.
|
||||||
|
case '[object RegExp]':
|
||||||
|
return a.source == b.source &&
|
||||||
|
a.global == b.global &&
|
||||||
|
a.multiline == b.multiline &&
|
||||||
|
a.ignoreCase == b.ignoreCase;
|
||||||
|
}
|
||||||
|
if (typeof a != 'object' || typeof b != 'object') return false;
|
||||||
|
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
||||||
|
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
||||||
|
var length = stack.length;
|
||||||
|
while (length--) {
|
||||||
|
// Linear search. Performance is inversely proportional to the number of
|
||||||
|
// unique nested structures.
|
||||||
|
if (stack[length] == a) return true;
|
||||||
|
}
|
||||||
|
// Add the first object to the stack of traversed objects.
|
||||||
|
stack.push(a);
|
||||||
|
var size = 0, result = true;
|
||||||
|
// Recursively compare objects and arrays.
|
||||||
|
if (className == '[object Array]') {
|
||||||
|
// Compare array lengths to determine if a deep comparison is necessary.
|
||||||
|
size = a.length;
|
||||||
|
result = size == b.length;
|
||||||
|
if (result) {
|
||||||
|
// Deep compare the contents, ignoring non-numeric properties.
|
||||||
|
while (size--) {
|
||||||
|
// Ensure commutative equality for sparse arrays.
|
||||||
|
if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Objects with different constructors are not equivalent.
|
||||||
|
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
|
||||||
|
// Deep compare objects.
|
||||||
|
for (var key in a) {
|
||||||
|
if (_.has(a, key)) {
|
||||||
|
// Count the expected number of properties.
|
||||||
|
size++;
|
||||||
|
// Deep compare each member.
|
||||||
|
if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure that both objects contain the same number of properties.
|
||||||
|
if (result) {
|
||||||
|
for (key in b) {
|
||||||
|
if (_.has(b, key) && !(size--)) break;
|
||||||
|
}
|
||||||
|
result = !size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove the first object from the stack of traversed objects.
|
||||||
|
stack.pop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a deep comparison to check if two objects are equal.
|
||||||
|
_.isEqual = function(a, b) {
|
||||||
|
return eq(a, b, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given array, string, or object empty?
|
||||||
|
// An "empty" object has no enumerable own-properties.
|
||||||
|
_.isEmpty = function(obj) {
|
||||||
|
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
|
||||||
|
for (var key in obj) if (_.has(obj, key)) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a DOM element?
|
||||||
|
_.isElement = function(obj) {
|
||||||
|
return !!(obj && obj.nodeType == 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value an array?
|
||||||
|
// Delegates to ECMA5's native Array.isArray
|
||||||
|
_.isArray = nativeIsArray || function(obj) {
|
||||||
|
return toString.call(obj) == '[object Array]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given variable an object?
|
||||||
|
_.isObject = function(obj) {
|
||||||
|
return obj === Object(obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given variable an arguments object?
|
||||||
|
_.isArguments = function(obj) {
|
||||||
|
return toString.call(obj) == '[object Arguments]';
|
||||||
|
};
|
||||||
|
if (!_.isArguments(arguments)) {
|
||||||
|
_.isArguments = function(obj) {
|
||||||
|
return !!(obj && _.has(obj, 'callee'));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is a given value a function?
|
||||||
|
_.isFunction = function(obj) {
|
||||||
|
return toString.call(obj) == '[object Function]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a string?
|
||||||
|
_.isString = function(obj) {
|
||||||
|
return toString.call(obj) == '[object String]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a number?
|
||||||
|
_.isNumber = function(obj) {
|
||||||
|
return toString.call(obj) == '[object Number]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is the given value `NaN`?
|
||||||
|
_.isNaN = function(obj) {
|
||||||
|
// `NaN` is the only value for which `===` is not reflexive.
|
||||||
|
return obj !== obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a boolean?
|
||||||
|
_.isBoolean = function(obj) {
|
||||||
|
return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value a date?
|
||||||
|
_.isDate = function(obj) {
|
||||||
|
return toString.call(obj) == '[object Date]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is the given value a regular expression?
|
||||||
|
_.isRegExp = function(obj) {
|
||||||
|
return toString.call(obj) == '[object RegExp]';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given value equal to null?
|
||||||
|
_.isNull = function(obj) {
|
||||||
|
return obj === null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is a given variable undefined?
|
||||||
|
_.isUndefined = function(obj) {
|
||||||
|
return obj === void 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Has own property?
|
||||||
|
_.has = function(obj, key) {
|
||||||
|
return hasOwnProperty.call(obj, key);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Utility Functions
|
||||||
|
// -----------------
|
||||||
|
|
||||||
|
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
|
||||||
|
// previous owner. Returns a reference to the Underscore object.
|
||||||
|
_.noConflict = function() {
|
||||||
|
root._ = previousUnderscore;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keep the identity function around for default iterators.
|
||||||
|
_.identity = function(value) {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run a function **n** times.
|
||||||
|
_.times = function (n, iterator, context) {
|
||||||
|
for (var i = 0; i < n; i++) iterator.call(context, i);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Escape a string for HTML interpolation.
|
||||||
|
_.escape = function(string) {
|
||||||
|
return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add your own custom functions to the Underscore object, ensuring that
|
||||||
|
// they're correctly added to the OOP wrapper as well.
|
||||||
|
_.mixin = function(obj) {
|
||||||
|
each(_.functions(obj), function(name){
|
||||||
|
addToWrapper(name, _[name] = obj[name]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate a unique integer id (unique within the entire client session).
|
||||||
|
// Useful for temporary DOM ids.
|
||||||
|
var idCounter = 0;
|
||||||
|
_.uniqueId = function(prefix) {
|
||||||
|
var id = idCounter++;
|
||||||
|
return prefix ? prefix + id : id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// By default, Underscore uses ERB-style template delimiters, change the
|
||||||
|
// following template settings to use alternative delimiters.
|
||||||
|
_.templateSettings = {
|
||||||
|
evaluate : /<%([\s\S]+?)%>/g,
|
||||||
|
interpolate : /<%=([\s\S]+?)%>/g,
|
||||||
|
escape : /<%-([\s\S]+?)%>/g
|
||||||
|
};
|
||||||
|
|
||||||
|
// When customizing `templateSettings`, if you don't want to define an
|
||||||
|
// interpolation, evaluation or escaping regex, we need one that is
|
||||||
|
// guaranteed not to match.
|
||||||
|
var noMatch = /.^/;
|
||||||
|
|
||||||
|
// Within an interpolation, evaluation, or escaping, remove HTML escaping
|
||||||
|
// that had been previously added.
|
||||||
|
var unescape = function(code) {
|
||||||
|
return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
|
||||||
|
};
|
||||||
|
|
||||||
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
||||||
|
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||||||
|
// and correctly escapes quotes within interpolated code.
|
||||||
|
_.template = function(str, data) {
|
||||||
|
var c = _.templateSettings;
|
||||||
|
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
|
||||||
|
'with(obj||{}){__p.push(\'' +
|
||||||
|
str.replace(/\\/g, '\\\\')
|
||||||
|
.replace(/'/g, "\\'")
|
||||||
|
.replace(c.escape || noMatch, function(match, code) {
|
||||||
|
return "',_.escape(" + unescape(code) + "),'";
|
||||||
|
})
|
||||||
|
.replace(c.interpolate || noMatch, function(match, code) {
|
||||||
|
return "'," + unescape(code) + ",'";
|
||||||
|
})
|
||||||
|
.replace(c.evaluate || noMatch, function(match, code) {
|
||||||
|
return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
|
||||||
|
})
|
||||||
|
.replace(/\r/g, '\\r')
|
||||||
|
.replace(/\n/g, '\\n')
|
||||||
|
.replace(/\t/g, '\\t')
|
||||||
|
+ "');}return __p.join('');";
|
||||||
|
var func = new Function('obj', '_', tmpl);
|
||||||
|
if (data) return func(data, _);
|
||||||
|
return function(data) {
|
||||||
|
return func.call(this, data, _);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a "chain" function, which will delegate to the wrapper.
|
||||||
|
_.chain = function(obj) {
|
||||||
|
return _(obj).chain();
|
||||||
|
};
|
||||||
|
|
||||||
|
// The OOP Wrapper
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
// If Underscore is called as a function, it returns a wrapped object that
|
||||||
|
// can be used OO-style. This wrapper holds altered versions of all the
|
||||||
|
// underscore functions. Wrapped objects may be chained.
|
||||||
|
var wrapper = function(obj) { this._wrapped = obj; };
|
||||||
|
|
||||||
|
// Expose `wrapper.prototype` as `_.prototype`
|
||||||
|
_.prototype = wrapper.prototype;
|
||||||
|
|
||||||
|
// Helper function to continue chaining intermediate results.
|
||||||
|
var result = function(obj, chain) {
|
||||||
|
return chain ? _(obj).chain() : obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A method to easily add functions to the OOP wrapper.
|
||||||
|
var addToWrapper = function(name, func) {
|
||||||
|
wrapper.prototype[name] = function() {
|
||||||
|
var args = slice.call(arguments);
|
||||||
|
unshift.call(args, this._wrapped);
|
||||||
|
return result(func.apply(_, args), this._chain);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add all of the Underscore functions to the wrapper object.
|
||||||
|
_.mixin(_);
|
||||||
|
|
||||||
|
// Add all mutator Array functions to the wrapper.
|
||||||
|
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
||||||
|
var method = ArrayProto[name];
|
||||||
|
wrapper.prototype[name] = function() {
|
||||||
|
var wrapped = this._wrapped;
|
||||||
|
method.apply(wrapped, arguments);
|
||||||
|
var length = wrapped.length;
|
||||||
|
if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
|
||||||
|
return result(wrapped, this._chain);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add all accessor Array functions to the wrapper.
|
||||||
|
each(['concat', 'join', 'slice'], function(name) {
|
||||||
|
var method = ArrayProto[name];
|
||||||
|
wrapper.prototype[name] = function() {
|
||||||
|
return result(method.apply(this._wrapped, arguments), this._chain);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start chaining a wrapped Underscore object.
|
||||||
|
wrapper.prototype.chain = function() {
|
||||||
|
this._chain = true;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extracts the result from a wrapped and chained object.
|
||||||
|
wrapper.prototype.value = function() {
|
||||||
|
return this._wrapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(this);
|
31
_static/underscore.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Underscore.js 1.3.1
|
||||||
|
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||||
|
// Underscore is freely distributable under the MIT license.
|
||||||
|
// Portions of Underscore are inspired or borrowed from Prototype,
|
||||||
|
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||||
|
// For all details and documentation:
|
||||||
|
// http://documentcloud.github.com/underscore
|
||||||
|
(function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
|
||||||
|
c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,
|
||||||
|
h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each=
|
||||||
|
b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===n)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===n)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(x&&a.map===x)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==
|
||||||
|
null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=
|
||||||
|
function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=
|
||||||
|
e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
|
||||||
|
function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&(e={value:a,computed:b})});
|
||||||
|
return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){f==0?b[0]=a:(d=Math.floor(Math.random()*(f+1)),b[f]=b[d],b[d]=a)});return b};b.sortBy=function(a,c,d){return b.pluck(b.map(a,function(a,b,g){return{value:a,criteria:c.call(d,a,b,g)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,
|
||||||
|
c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:a.toArray?a.toArray():b.isArray(a)?i.call(a):b.isArguments(a)?i.call(a):b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=b.head=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=
|
||||||
|
b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,g,h){if(0==h||(c===true?b.last(d)!=g:!b.include(d,g)))d[d.length]=g,e[e.length]=a[h];return d},[]);
|
||||||
|
return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,
|
||||||
|
d){if(a==null)return-1;var e;if(d)return d=b.sortedIndex(a,c),a[d]===c?d:-1;if(p&&a.indexOf===p)return a.indexOf(c);for(d=0,e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(D&&a.lastIndexOf===D)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){arguments.length<=1&&(b=a||0,a=0);for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;)g[f++]=a,a+=d;return g};
|
||||||
|
var F=function(){};b.bind=function(a,c){var d,e;if(a.bind===s&&s)return s.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));F.prototype=a.prototype;var b=new F,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,
|
||||||
|
c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i=b.debounce(function(){h=g=false},c);return function(){d=this;e=arguments;var b;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);i()},c));g?h=true:
|
||||||
|
a.apply(d,e);i();g=true}};b.debounce=function(a,b){var d;return function(){var e=this,f=arguments;clearTimeout(d);d=setTimeout(function(){d=null;a.apply(e,f)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};
|
||||||
|
b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments,
|
||||||
|
1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};
|
||||||
|
b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};
|
||||||
|
b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),
|
||||||
|
function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+
|
||||||
|
u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]=
|
||||||
|
function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=
|
||||||
|
true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
|
BIN
_static/up-pressed.png
Normal file
After Width: | Height: | Size: 214 B |
BIN
_static/up.png
Normal file
After Width: | Height: | Size: 203 B |
808
_static/websupport.js
Normal file
|
@ -0,0 +1,808 @@
|
||||||
|
/*
|
||||||
|
* websupport.js
|
||||||
|
* ~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* sphinx.websupport utilities for all documentation.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
$.fn.autogrow = function() {
|
||||||
|
return this.each(function() {
|
||||||
|
var textarea = this;
|
||||||
|
|
||||||
|
$.fn.autogrow.resize(textarea);
|
||||||
|
|
||||||
|
$(textarea)
|
||||||
|
.focus(function() {
|
||||||
|
textarea.interval = setInterval(function() {
|
||||||
|
$.fn.autogrow.resize(textarea);
|
||||||
|
}, 500);
|
||||||
|
})
|
||||||
|
.blur(function() {
|
||||||
|
clearInterval(textarea.interval);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.autogrow.resize = function(textarea) {
|
||||||
|
var lineHeight = parseInt($(textarea).css('line-height'), 10);
|
||||||
|
var lines = textarea.value.split('\n');
|
||||||
|
var columns = textarea.cols;
|
||||||
|
var lineCount = 0;
|
||||||
|
$.each(lines, function() {
|
||||||
|
lineCount += Math.ceil(this.length / columns) || 1;
|
||||||
|
});
|
||||||
|
var height = lineHeight * (lineCount + 1);
|
||||||
|
$(textarea).css('height', height);
|
||||||
|
};
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
var comp, by;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
initEvents();
|
||||||
|
initComparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
function initEvents() {
|
||||||
|
$(document).on("click", 'a.comment-close', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
hide($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.vote', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
handleVote($(this));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.reply', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
openReply($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.close-reply', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
closeReply($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.sort-option', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
handleReSort($(this));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.show-proposal', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
showProposal($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.hide-proposal', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
hideProposal($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.show-propose-change', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
showProposeChange($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.hide-propose-change', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
hideProposeChange($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.accept-comment', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
acceptComment($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.delete-comment', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
deleteComment($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
$(document).on("click", 'a.comment-markup', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
toggleCommentMarkupBox($(this).attr('id').substring(2));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set comp, which is a comparator function used for sorting and
|
||||||
|
* inserting comments into the list.
|
||||||
|
*/
|
||||||
|
function setComparator() {
|
||||||
|
// If the first three letters are "asc", sort in ascending order
|
||||||
|
// and remove the prefix.
|
||||||
|
if (by.substring(0,3) == 'asc') {
|
||||||
|
var i = by.substring(3);
|
||||||
|
comp = function(a, b) { return a[i] - b[i]; };
|
||||||
|
} else {
|
||||||
|
// Otherwise sort in descending order.
|
||||||
|
comp = function(a, b) { return b[by] - a[by]; };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset link styles and format the selected sort option.
|
||||||
|
$('a.sel').attr('href', '#').removeClass('sel');
|
||||||
|
$('a.by' + by).removeAttr('href').addClass('sel');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a comp function. If the user has preferences stored in
|
||||||
|
* the sortBy cookie, use those, otherwise use the default.
|
||||||
|
*/
|
||||||
|
function initComparator() {
|
||||||
|
by = 'rating'; // Default to sort by rating.
|
||||||
|
// If the sortBy cookie is set, use that instead.
|
||||||
|
if (document.cookie.length > 0) {
|
||||||
|
var start = document.cookie.indexOf('sortBy=');
|
||||||
|
if (start != -1) {
|
||||||
|
start = start + 7;
|
||||||
|
var end = document.cookie.indexOf(";", start);
|
||||||
|
if (end == -1) {
|
||||||
|
end = document.cookie.length;
|
||||||
|
by = unescape(document.cookie.substring(start, end));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setComparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a comment div.
|
||||||
|
*/
|
||||||
|
function show(id) {
|
||||||
|
$('#ao' + id).hide();
|
||||||
|
$('#ah' + id).show();
|
||||||
|
var context = $.extend({id: id}, opts);
|
||||||
|
var popup = $(renderTemplate(popupTemplate, context)).hide();
|
||||||
|
popup.find('textarea[name="proposal"]').hide();
|
||||||
|
popup.find('a.by' + by).addClass('sel');
|
||||||
|
var form = popup.find('#cf' + id);
|
||||||
|
form.submit(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
addComment(form);
|
||||||
|
});
|
||||||
|
$('#s' + id).after(popup);
|
||||||
|
popup.slideDown('fast', function() {
|
||||||
|
getComments(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide a comment div.
|
||||||
|
*/
|
||||||
|
function hide(id) {
|
||||||
|
$('#ah' + id).hide();
|
||||||
|
$('#ao' + id).show();
|
||||||
|
var div = $('#sc' + id);
|
||||||
|
div.slideUp('fast', function() {
|
||||||
|
div.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an ajax request to get comments for a node
|
||||||
|
* and insert the comments into the comments tree.
|
||||||
|
*/
|
||||||
|
function getComments(id) {
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
url: opts.getCommentsURL,
|
||||||
|
data: {node: id},
|
||||||
|
success: function(data, textStatus, request) {
|
||||||
|
var ul = $('#cl' + id);
|
||||||
|
var speed = 100;
|
||||||
|
$('#cf' + id)
|
||||||
|
.find('textarea[name="proposal"]')
|
||||||
|
.data('source', data.source);
|
||||||
|
|
||||||
|
if (data.comments.length === 0) {
|
||||||
|
ul.html('<li>No comments yet.</li>');
|
||||||
|
ul.data('empty', true);
|
||||||
|
} else {
|
||||||
|
// If there are comments, sort them and put them in the list.
|
||||||
|
var comments = sortComments(data.comments);
|
||||||
|
speed = data.comments.length * 100;
|
||||||
|
appendComments(comments, ul);
|
||||||
|
ul.data('empty', false);
|
||||||
|
}
|
||||||
|
$('#cn' + id).slideUp(speed + 200);
|
||||||
|
ul.slideDown(speed);
|
||||||
|
},
|
||||||
|
error: function(request, textStatus, error) {
|
||||||
|
showError('Oops, there was a problem retrieving the comments.');
|
||||||
|
},
|
||||||
|
dataType: 'json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a comment via ajax and insert the comment into the comment tree.
|
||||||
|
*/
|
||||||
|
function addComment(form) {
|
||||||
|
var node_id = form.find('input[name="node"]').val();
|
||||||
|
var parent_id = form.find('input[name="parent"]').val();
|
||||||
|
var text = form.find('textarea[name="comment"]').val();
|
||||||
|
var proposal = form.find('textarea[name="proposal"]').val();
|
||||||
|
|
||||||
|
if (text == '') {
|
||||||
|
showError('Please enter a comment.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable the form that is being submitted.
|
||||||
|
form.find('textarea,input').attr('disabled', 'disabled');
|
||||||
|
|
||||||
|
// Send the comment to the server.
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: opts.addCommentURL,
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
node: node_id,
|
||||||
|
parent: parent_id,
|
||||||
|
text: text,
|
||||||
|
proposal: proposal
|
||||||
|
},
|
||||||
|
success: function(data, textStatus, error) {
|
||||||
|
// Reset the form.
|
||||||
|
if (node_id) {
|
||||||
|
hideProposeChange(node_id);
|
||||||
|
}
|
||||||
|
form.find('textarea')
|
||||||
|
.val('')
|
||||||
|
.add(form.find('input'))
|
||||||
|
.removeAttr('disabled');
|
||||||
|
var ul = $('#cl' + (node_id || parent_id));
|
||||||
|
if (ul.data('empty')) {
|
||||||
|
$(ul).empty();
|
||||||
|
ul.data('empty', false);
|
||||||
|
}
|
||||||
|
insertComment(data.comment);
|
||||||
|
var ao = $('#ao' + node_id);
|
||||||
|
ao.find('img').attr({'src': opts.commentBrightImage});
|
||||||
|
if (node_id) {
|
||||||
|
// if this was a "root" comment, remove the commenting box
|
||||||
|
// (the user can get it back by reopening the comment popup)
|
||||||
|
$('#ca' + node_id).slideUp();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(request, textStatus, error) {
|
||||||
|
form.find('textarea,input').removeAttr('disabled');
|
||||||
|
showError('Oops, there was a problem adding the comment.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively append comments to the main comment list and children
|
||||||
|
* lists, creating the comment tree.
|
||||||
|
*/
|
||||||
|
function appendComments(comments, ul) {
|
||||||
|
$.each(comments, function() {
|
||||||
|
var div = createCommentDiv(this);
|
||||||
|
ul.append($(document.createElement('li')).html(div));
|
||||||
|
appendComments(this.children, div.find('ul.comment-children'));
|
||||||
|
// To avoid stagnating data, don't store the comments children in data.
|
||||||
|
this.children = null;
|
||||||
|
div.data('comment', this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After adding a new comment, it must be inserted in the correct
|
||||||
|
* location in the comment tree.
|
||||||
|
*/
|
||||||
|
function insertComment(comment) {
|
||||||
|
var div = createCommentDiv(comment);
|
||||||
|
|
||||||
|
// To avoid stagnating data, don't store the comments children in data.
|
||||||
|
comment.children = null;
|
||||||
|
div.data('comment', comment);
|
||||||
|
|
||||||
|
var ul = $('#cl' + (comment.node || comment.parent));
|
||||||
|
var siblings = getChildren(ul);
|
||||||
|
|
||||||
|
var li = $(document.createElement('li'));
|
||||||
|
li.hide();
|
||||||
|
|
||||||
|
// Determine where in the parents children list to insert this comment.
|
||||||
|
for(var i=0; i < siblings.length; i++) {
|
||||||
|
if (comp(comment, siblings[i]) <= 0) {
|
||||||
|
$('#cd' + siblings[i].id)
|
||||||
|
.parent()
|
||||||
|
.before(li.html(div));
|
||||||
|
li.slideDown('fast');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, this comment rates lower than all the others,
|
||||||
|
// or it is the only comment in the list.
|
||||||
|
ul.append(li.html(div));
|
||||||
|
li.slideDown('fast');
|
||||||
|
}
|
||||||
|
|
||||||
|
function acceptComment(id) {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: opts.acceptCommentURL,
|
||||||
|
data: {id: id},
|
||||||
|
success: function(data, textStatus, request) {
|
||||||
|
$('#cm' + id).fadeOut('fast');
|
||||||
|
$('#cd' + id).removeClass('moderate');
|
||||||
|
},
|
||||||
|
error: function(request, textStatus, error) {
|
||||||
|
showError('Oops, there was a problem accepting the comment.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteComment(id) {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: opts.deleteCommentURL,
|
||||||
|
data: {id: id},
|
||||||
|
success: function(data, textStatus, request) {
|
||||||
|
var div = $('#cd' + id);
|
||||||
|
if (data == 'delete') {
|
||||||
|
// Moderator mode: remove the comment and all children immediately
|
||||||
|
div.slideUp('fast', function() {
|
||||||
|
div.remove();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// User mode: only mark the comment as deleted
|
||||||
|
div
|
||||||
|
.find('span.user-id:first')
|
||||||
|
.text('[deleted]').end()
|
||||||
|
.find('div.comment-text:first')
|
||||||
|
.text('[deleted]').end()
|
||||||
|
.find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
|
||||||
|
', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
|
||||||
|
.remove();
|
||||||
|
var comment = div.data('comment');
|
||||||
|
comment.username = '[deleted]';
|
||||||
|
comment.text = '[deleted]';
|
||||||
|
div.data('comment', comment);
|
||||||
|
},
|
||||||
|
error: function(request, textStatus, error) {
|
||||||
|
showError('Oops, there was a problem deleting the comment.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showProposal(id) {
|
||||||
|
$('#sp' + id).hide();
|
||||||
|
$('#hp' + id).show();
|
||||||
|
$('#pr' + id).slideDown('fast');
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideProposal(id) {
|
||||||
|
$('#hp' + id).hide();
|
||||||
|
$('#sp' + id).show();
|
||||||
|
$('#pr' + id).slideUp('fast');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showProposeChange(id) {
|
||||||
|
$('#pc' + id).hide();
|
||||||
|
$('#hc' + id).show();
|
||||||
|
var textarea = $('#pt' + id);
|
||||||
|
textarea.val(textarea.data('source'));
|
||||||
|
$.fn.autogrow.resize(textarea[0]);
|
||||||
|
textarea.slideDown('fast');
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideProposeChange(id) {
|
||||||
|
$('#hc' + id).hide();
|
||||||
|
$('#pc' + id).show();
|
||||||
|
var textarea = $('#pt' + id);
|
||||||
|
textarea.val('').removeAttr('disabled');
|
||||||
|
textarea.slideUp('fast');
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleCommentMarkupBox(id) {
|
||||||
|
$('#mb' + id).toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handle when the user clicks on a sort by link. */
|
||||||
|
function handleReSort(link) {
|
||||||
|
var classes = link.attr('class').split(/\s+/);
|
||||||
|
for (var i=0; i<classes.length; i++) {
|
||||||
|
if (classes[i] != 'sort-option') {
|
||||||
|
by = classes[i].substring(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setComparator();
|
||||||
|
// Save/update the sortBy cookie.
|
||||||
|
var expiration = new Date();
|
||||||
|
expiration.setDate(expiration.getDate() + 365);
|
||||||
|
document.cookie= 'sortBy=' + escape(by) +
|
||||||
|
';expires=' + expiration.toUTCString();
|
||||||
|
$('ul.comment-ul').each(function(index, ul) {
|
||||||
|
var comments = getChildren($(ul), true);
|
||||||
|
comments = sortComments(comments);
|
||||||
|
appendComments(comments, $(ul).empty());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to process a vote when a user clicks an arrow.
|
||||||
|
*/
|
||||||
|
function handleVote(link) {
|
||||||
|
if (!opts.voting) {
|
||||||
|
showError("You'll need to login to vote.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = link.attr('id');
|
||||||
|
if (!id) {
|
||||||
|
// Didn't click on one of the voting arrows.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If it is an unvote, the new vote value is 0,
|
||||||
|
// Otherwise it's 1 for an upvote, or -1 for a downvote.
|
||||||
|
var value = 0;
|
||||||
|
if (id.charAt(1) != 'u') {
|
||||||
|
value = id.charAt(0) == 'u' ? 1 : -1;
|
||||||
|
}
|
||||||
|
// The data to be sent to the server.
|
||||||
|
var d = {
|
||||||
|
comment_id: id.substring(2),
|
||||||
|
value: value
|
||||||
|
};
|
||||||
|
|
||||||
|
// Swap the vote and unvote links.
|
||||||
|
link.hide();
|
||||||
|
$('#' + id.charAt(0) + (id.charAt(1) == 'u' ? 'v' : 'u') + d.comment_id)
|
||||||
|
.show();
|
||||||
|
|
||||||
|
// The div the comment is displayed in.
|
||||||
|
var div = $('div#cd' + d.comment_id);
|
||||||
|
var data = div.data('comment');
|
||||||
|
|
||||||
|
// If this is not an unvote, and the other vote arrow has
|
||||||
|
// already been pressed, unpress it.
|
||||||
|
if ((d.value !== 0) && (data.vote === d.value * -1)) {
|
||||||
|
$('#' + (d.value == 1 ? 'd' : 'u') + 'u' + d.comment_id).hide();
|
||||||
|
$('#' + (d.value == 1 ? 'd' : 'u') + 'v' + d.comment_id).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the comments rating in the local data.
|
||||||
|
data.rating += (data.vote === 0) ? d.value : (d.value - data.vote);
|
||||||
|
data.vote = d.value;
|
||||||
|
div.data('comment', data);
|
||||||
|
|
||||||
|
// Change the rating text.
|
||||||
|
div.find('.rating:first')
|
||||||
|
.text(data.rating + ' point' + (data.rating == 1 ? '' : 's'));
|
||||||
|
|
||||||
|
// Send the vote information to the server.
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: opts.processVoteURL,
|
||||||
|
data: d,
|
||||||
|
error: function(request, textStatus, error) {
|
||||||
|
showError('Oops, there was a problem casting that vote.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a reply form used to reply to an existing comment.
|
||||||
|
*/
|
||||||
|
function openReply(id) {
|
||||||
|
// Swap out the reply link for the hide link
|
||||||
|
$('#rl' + id).hide();
|
||||||
|
$('#cr' + id).show();
|
||||||
|
|
||||||
|
// Add the reply li to the children ul.
|
||||||
|
var div = $(renderTemplate(replyTemplate, {id: id})).hide();
|
||||||
|
$('#cl' + id)
|
||||||
|
.prepend(div)
|
||||||
|
// Setup the submit handler for the reply form.
|
||||||
|
.find('#rf' + id)
|
||||||
|
.submit(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
addComment($('#rf' + id));
|
||||||
|
closeReply(id);
|
||||||
|
})
|
||||||
|
.find('input[type=button]')
|
||||||
|
.click(function() {
|
||||||
|
closeReply(id);
|
||||||
|
});
|
||||||
|
div.slideDown('fast', function() {
|
||||||
|
$('#rf' + id).find('textarea').focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the reply form opened with openReply.
|
||||||
|
*/
|
||||||
|
function closeReply(id) {
|
||||||
|
// Remove the reply div from the DOM.
|
||||||
|
$('#rd' + id).slideUp('fast', function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Swap out the hide link for the reply link
|
||||||
|
$('#cr' + id).hide();
|
||||||
|
$('#rl' + id).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively sort a tree of comments using the comp comparator.
|
||||||
|
*/
|
||||||
|
function sortComments(comments) {
|
||||||
|
comments.sort(comp);
|
||||||
|
$.each(comments, function() {
|
||||||
|
this.children = sortComments(this.children);
|
||||||
|
});
|
||||||
|
return comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the children comments from a ul. If recursive is true,
|
||||||
|
* recursively include childrens' children.
|
||||||
|
*/
|
||||||
|
function getChildren(ul, recursive) {
|
||||||
|
var children = [];
|
||||||
|
ul.children().children("[id^='cd']")
|
||||||
|
.each(function() {
|
||||||
|
var comment = $(this).data('comment');
|
||||||
|
if (recursive)
|
||||||
|
comment.children = getChildren($(this).find('#cl' + comment.id), true);
|
||||||
|
children.push(comment);
|
||||||
|
});
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a div to display a comment in. */
|
||||||
|
function createCommentDiv(comment) {
|
||||||
|
if (!comment.displayed && !opts.moderator) {
|
||||||
|
return $('<div class="moderate">Thank you! Your comment will show up '
|
||||||
|
+ 'once it is has been approved by a moderator.</div>');
|
||||||
|
}
|
||||||
|
// Prettify the comment rating.
|
||||||
|
comment.pretty_rating = comment.rating + ' point' +
|
||||||
|
(comment.rating == 1 ? '' : 's');
|
||||||
|
// Make a class (for displaying not yet moderated comments differently)
|
||||||
|
comment.css_class = comment.displayed ? '' : ' moderate';
|
||||||
|
// Create a div for this comment.
|
||||||
|
var context = $.extend({}, opts, comment);
|
||||||
|
var div = $(renderTemplate(commentTemplate, context));
|
||||||
|
|
||||||
|
// If the user has voted on this comment, highlight the correct arrow.
|
||||||
|
if (comment.vote) {
|
||||||
|
var direction = (comment.vote == 1) ? 'u' : 'd';
|
||||||
|
div.find('#' + direction + 'v' + comment.id).hide();
|
||||||
|
div.find('#' + direction + 'u' + comment.id).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.moderator || comment.text != '[deleted]') {
|
||||||
|
div.find('a.reply').show();
|
||||||
|
if (comment.proposal_diff)
|
||||||
|
div.find('#sp' + comment.id).show();
|
||||||
|
if (opts.moderator && !comment.displayed)
|
||||||
|
div.find('#cm' + comment.id).show();
|
||||||
|
if (opts.moderator || (opts.username == comment.username))
|
||||||
|
div.find('#dc' + comment.id).show();
|
||||||
|
}
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple template renderer. Placeholders such as <%id%> are replaced
|
||||||
|
* by context['id'] with items being escaped. Placeholders such as <#id#>
|
||||||
|
* are not escaped.
|
||||||
|
*/
|
||||||
|
function renderTemplate(template, context) {
|
||||||
|
var esc = $(document.createElement('div'));
|
||||||
|
|
||||||
|
function handle(ph, escape) {
|
||||||
|
var cur = context;
|
||||||
|
$.each(ph.split('.'), function() {
|
||||||
|
cur = cur[this];
|
||||||
|
});
|
||||||
|
return escape ? esc.text(cur || "").html() : cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
|
||||||
|
return handle(arguments[2], arguments[1] == '%' ? true : false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Flash an error message briefly. */
|
||||||
|
function showError(message) {
|
||||||
|
$(document.createElement('div')).attr({'class': 'popup-error'})
|
||||||
|
.append($(document.createElement('div'))
|
||||||
|
.attr({'class': 'error-message'}).text(message))
|
||||||
|
.appendTo('body')
|
||||||
|
.fadeIn("slow")
|
||||||
|
.delay(2000)
|
||||||
|
.fadeOut("slow");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add a link the user uses to open the comments popup. */
|
||||||
|
$.fn.comment = function() {
|
||||||
|
return this.each(function() {
|
||||||
|
var id = $(this).attr('id').substring(1);
|
||||||
|
var count = COMMENT_METADATA[id];
|
||||||
|
var title = count + ' comment' + (count == 1 ? '' : 's');
|
||||||
|
var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
|
||||||
|
var addcls = count == 0 ? ' nocomment' : '';
|
||||||
|
$(this)
|
||||||
|
.append(
|
||||||
|
$(document.createElement('a')).attr({
|
||||||
|
href: '#',
|
||||||
|
'class': 'sphinx-comment-open' + addcls,
|
||||||
|
id: 'ao' + id
|
||||||
|
})
|
||||||
|
.append($(document.createElement('img')).attr({
|
||||||
|
src: image,
|
||||||
|
alt: 'comment',
|
||||||
|
title: title
|
||||||
|
}))
|
||||||
|
.click(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
show($(this).attr('id').substring(2));
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.append(
|
||||||
|
$(document.createElement('a')).attr({
|
||||||
|
href: '#',
|
||||||
|
'class': 'sphinx-comment-close hidden',
|
||||||
|
id: 'ah' + id
|
||||||
|
})
|
||||||
|
.append($(document.createElement('img')).attr({
|
||||||
|
src: opts.closeCommentImage,
|
||||||
|
alt: 'close',
|
||||||
|
title: 'close'
|
||||||
|
}))
|
||||||
|
.click(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
hide($(this).attr('id').substring(2));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var opts = {
|
||||||
|
processVoteURL: '/_process_vote',
|
||||||
|
addCommentURL: '/_add_comment',
|
||||||
|
getCommentsURL: '/_get_comments',
|
||||||
|
acceptCommentURL: '/_accept_comment',
|
||||||
|
deleteCommentURL: '/_delete_comment',
|
||||||
|
commentImage: '/static/_static/comment.png',
|
||||||
|
closeCommentImage: '/static/_static/comment-close.png',
|
||||||
|
loadingImage: '/static/_static/ajax-loader.gif',
|
||||||
|
commentBrightImage: '/static/_static/comment-bright.png',
|
||||||
|
upArrow: '/static/_static/up.png',
|
||||||
|
downArrow: '/static/_static/down.png',
|
||||||
|
upArrowPressed: '/static/_static/up-pressed.png',
|
||||||
|
downArrowPressed: '/static/_static/down-pressed.png',
|
||||||
|
voting: false,
|
||||||
|
moderator: false
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof COMMENT_OPTIONS != "undefined") {
|
||||||
|
opts = jQuery.extend(opts, COMMENT_OPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
var popupTemplate = '\
|
||||||
|
<div class="sphinx-comments" id="sc<%id%>">\
|
||||||
|
<p class="sort-options">\
|
||||||
|
Sort by:\
|
||||||
|
<a href="#" class="sort-option byrating">best rated</a>\
|
||||||
|
<a href="#" class="sort-option byascage">newest</a>\
|
||||||
|
<a href="#" class="sort-option byage">oldest</a>\
|
||||||
|
</p>\
|
||||||
|
<div class="comment-header">Comments</div>\
|
||||||
|
<div class="comment-loading" id="cn<%id%>">\
|
||||||
|
loading comments... <img src="<%loadingImage%>" alt="" /></div>\
|
||||||
|
<ul id="cl<%id%>" class="comment-ul"></ul>\
|
||||||
|
<div id="ca<%id%>">\
|
||||||
|
<p class="add-a-comment">Add a comment\
|
||||||
|
(<a href="#" class="comment-markup" id="ab<%id%>">markup</a>):</p>\
|
||||||
|
<div class="comment-markup-box" id="mb<%id%>">\
|
||||||
|
reStructured text markup: <i>*emph*</i>, <b>**strong**</b>, \
|
||||||
|
<code>``code``</code>, \
|
||||||
|
code blocks: <code>::</code> and an indented block after blank line</div>\
|
||||||
|
<form method="post" id="cf<%id%>" class="comment-form" action="">\
|
||||||
|
<textarea name="comment" cols="80"></textarea>\
|
||||||
|
<p class="propose-button">\
|
||||||
|
<a href="#" id="pc<%id%>" class="show-propose-change">\
|
||||||
|
Propose a change ▹\
|
||||||
|
</a>\
|
||||||
|
<a href="#" id="hc<%id%>" class="hide-propose-change">\
|
||||||
|
Propose a change ▿\
|
||||||
|
</a>\
|
||||||
|
</p>\
|
||||||
|
<textarea name="proposal" id="pt<%id%>" cols="80"\
|
||||||
|
spellcheck="false"></textarea>\
|
||||||
|
<input type="submit" value="Add comment" />\
|
||||||
|
<input type="hidden" name="node" value="<%id%>" />\
|
||||||
|
<input type="hidden" name="parent" value="" />\
|
||||||
|
</form>\
|
||||||
|
</div>\
|
||||||
|
</div>';
|
||||||
|
|
||||||
|
var commentTemplate = '\
|
||||||
|
<div id="cd<%id%>" class="sphinx-comment<%css_class%>">\
|
||||||
|
<div class="vote">\
|
||||||
|
<div class="arrow">\
|
||||||
|
<a href="#" id="uv<%id%>" class="vote" title="vote up">\
|
||||||
|
<img src="<%upArrow%>" />\
|
||||||
|
</a>\
|
||||||
|
<a href="#" id="uu<%id%>" class="un vote" title="vote up">\
|
||||||
|
<img src="<%upArrowPressed%>" />\
|
||||||
|
</a>\
|
||||||
|
</div>\
|
||||||
|
<div class="arrow">\
|
||||||
|
<a href="#" id="dv<%id%>" class="vote" title="vote down">\
|
||||||
|
<img src="<%downArrow%>" id="da<%id%>" />\
|
||||||
|
</a>\
|
||||||
|
<a href="#" id="du<%id%>" class="un vote" title="vote down">\
|
||||||
|
<img src="<%downArrowPressed%>" />\
|
||||||
|
</a>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
<div class="comment-content">\
|
||||||
|
<p class="tagline comment">\
|
||||||
|
<span class="user-id"><%username%></span>\
|
||||||
|
<span class="rating"><%pretty_rating%></span>\
|
||||||
|
<span class="delta"><%time.delta%></span>\
|
||||||
|
</p>\
|
||||||
|
<div class="comment-text comment"><#text#></div>\
|
||||||
|
<p class="comment-opts comment">\
|
||||||
|
<a href="#" class="reply hidden" id="rl<%id%>">reply ▹</a>\
|
||||||
|
<a href="#" class="close-reply" id="cr<%id%>">reply ▿</a>\
|
||||||
|
<a href="#" id="sp<%id%>" class="show-proposal">proposal ▹</a>\
|
||||||
|
<a href="#" id="hp<%id%>" class="hide-proposal">proposal ▿</a>\
|
||||||
|
<a href="#" id="dc<%id%>" class="delete-comment hidden">delete</a>\
|
||||||
|
<span id="cm<%id%>" class="moderation hidden">\
|
||||||
|
<a href="#" id="ac<%id%>" class="accept-comment">accept</a>\
|
||||||
|
</span>\
|
||||||
|
</p>\
|
||||||
|
<pre class="proposal" id="pr<%id%>">\
|
||||||
|
<#proposal_diff#>\
|
||||||
|
</pre>\
|
||||||
|
<ul class="comment-children" id="cl<%id%>"></ul>\
|
||||||
|
</div>\
|
||||||
|
<div class="clearleft"></div>\
|
||||||
|
</div>\
|
||||||
|
</div>';
|
||||||
|
|
||||||
|
var replyTemplate = '\
|
||||||
|
<li>\
|
||||||
|
<div class="reply-div" id="rd<%id%>">\
|
||||||
|
<form id="rf<%id%>">\
|
||||||
|
<textarea name="comment" cols="80"></textarea>\
|
||||||
|
<input type="submit" value="Add reply" />\
|
||||||
|
<input type="button" value="Cancel" />\
|
||||||
|
<input type="hidden" name="parent" value="<%id%>" />\
|
||||||
|
<input type="hidden" name="node" value="" />\
|
||||||
|
</form>\
|
||||||
|
</div>\
|
||||||
|
</li>';
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
// add comment anchors for all paragraphs that are commentable
|
||||||
|
$('.sphinx-has-comment').comment();
|
||||||
|
|
||||||
|
// highlight search words in search results
|
||||||
|
$("div.context").each(function() {
|
||||||
|
var params = $.getQueryParameters();
|
||||||
|
var terms = (params.q) ? params.q[0].split(/\s+/) : [];
|
||||||
|
var result = $(this);
|
||||||
|
$.each(terms, function() {
|
||||||
|
result.highlightText(this.toLowerCase(), 'highlighted');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// directly open comment window if requested
|
||||||
|
var anchor = document.location.hash;
|
||||||
|
if (anchor.substring(0, 9) == '#comment-') {
|
||||||
|
$('#ao' + anchor.substring(9)).click();
|
||||||
|
document.location.hash = '#s' + anchor.substring(9);
|
||||||
|
}
|
||||||
|
});
|
592
api.entry.html
Normal file
|
@ -0,0 +1,592 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>feedgen.entry — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="feedgen.util" href="api.util.html" />
|
||||||
|
<link rel="prev" title="feedgen.feed" href="api.feed.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>feedgen.entry</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.feed.html">feedgen.feed</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.util.html">feedgen.util</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<script type=application/javascript src=_static/theme_extras.js></script>
|
||||||
|
<div class="apititle"><b>Contents</b></div>
|
||||||
|
<div class="apitoc"></div><span class="target" id="module-feedgen.entry"></span><div class="section" id="feedgen-entry">
|
||||||
|
<h1>feedgen.entry<a class="headerlink" href="#feedgen-entry" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">copyright:</th><td class="field-body">2013, Lars Kiesow <<a class="reference external" href="mailto:lkiesow%40uos.de">lkiesow<span>@</span>uos<span>.</span>de</a>></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">license:</th><td class="field-body">FreeBSD and LGPL, see license.* for more details.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.entry.FeedEntry">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.entry.</code><code class="descname">FeedEntry</code><a class="headerlink" href="#feedgen.entry.FeedEntry" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>FeedEntry call representing an ATOM feeds entry node or an RSS feeds item
|
||||||
|
node.</p>
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.atom_entry">
|
||||||
|
<code class="descname">atom_entry</code><span class="sig-paren">(</span><em>extensions=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.atom_entry" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Create an ATOM entry and return it.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.author">
|
||||||
|
<code class="descname">author</code><span class="sig-paren">(</span><em>author=None</em>, <em>replace=False</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.author" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set author data. An author element is a dict containing a
|
||||||
|
name, an email address and a uri. Name is mandatory for ATOM, email is
|
||||||
|
mandatory for RSS.</p>
|
||||||
|
<p>This method can be called with:
|
||||||
|
- the fields of an author as keyword arguments
|
||||||
|
- the fields of an author as a dictionary
|
||||||
|
- a list of dictionaries containing the author fields</p>
|
||||||
|
<p>An author has the following fields:
|
||||||
|
- <em>name</em> conveys a human-readable name for the person.
|
||||||
|
- <em>uri</em> contains a home page for the person.
|
||||||
|
- <em>email</em> contains an email address for the person.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
|
||||||
|
<li><strong>author</strong> – Dict or list of dicts with author data.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>Example:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">author</span><span class="p">({</span><span class="s1">'name'</span><span class="p">:</span><span class="s1">'John Doe'</span><span class="p">,</span> <span class="s1">'email'</span><span class="p">:</span><span class="s1">'jdoe@example.com'</span><span class="p">})</span>
|
||||||
|
<span class="go">[{'name':'John Doe','email':'jdoe@example.com'}]</span>
|
||||||
|
|
||||||
|
<span class="gp">>>> </span><span class="n">author</span><span class="p">([{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Mr. X'</span><span class="p">},</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Max'</span><span class="p">}])</span>
|
||||||
|
<span class="go">[{'name':'John Doe','email':'jdoe@example.com'},</span>
|
||||||
|
<span class="go"> {'name':'John Doe'}, {'name':'Max'}]</span>
|
||||||
|
|
||||||
|
<span class="gp">>>> </span><span class="n">author</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'John Doe'</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s1">'jdoe@example.com'</span><span class="p">,</span> <span class="n">replace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||||
|
<span class="go">[{'name':'John Doe','email':'jdoe@example.com'}]</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.category">
|
||||||
|
<code class="descname">category</code><span class="sig-paren">(</span><em>category=None</em>, <em>replace=False</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.category" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set categories that the entry belongs to.</p>
|
||||||
|
<p>This method can be called with:
|
||||||
|
- the fields of a category as keyword arguments
|
||||||
|
- the fields of a category as a dictionary
|
||||||
|
- a list of dictionaries containing the category fields</p>
|
||||||
|
<p>A categories has the following fields:
|
||||||
|
- <em>term</em> identifies the category
|
||||||
|
- <em>scheme</em> identifies the categorization scheme via a URI.
|
||||||
|
- <em>label</em> provides a human-readable label for display</p>
|
||||||
|
<p>If a label is present it is used for the RSS feeds. Otherwise the term
|
||||||
|
is used. The scheme is used for the domain attribute in RSS.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>category</strong> – Dict or list of dicts with data.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of category data.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.comments">
|
||||||
|
<code class="descname">comments</code><span class="sig-paren">(</span><em>comments=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.comments" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the value of comments which is the URL of the comments
|
||||||
|
page for the item. This is a RSS only value.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>comments</strong> – URL to the comments page.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">URL to the comments page.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.content">
|
||||||
|
<code class="descname">content</code><span class="sig-paren">(</span><em>content=None</em>, <em>src=None</em>, <em>type=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.content" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the content of the entry which contains or links to the
|
||||||
|
complete content of the entry. Content must be provided for ATOM
|
||||||
|
entries if there is no alternate link, and should be provided if there
|
||||||
|
is no summary. If the content is set (not linked) it will also set
|
||||||
|
rss:description.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>content</strong> – The content of the feed entry.</li>
|
||||||
|
<li><strong>src</strong> – Link to the entries content.</li>
|
||||||
|
<li><strong>type</strong> – If type is CDATA content would not be escaped.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Content element of the entry.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.contributor">
|
||||||
|
<code class="descname">contributor</code><span class="sig-paren">(</span><em>contributor=None</em>, <em>replace=False</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.contributor" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the contributor data of the feed. This is an ATOM only
|
||||||
|
value.</p>
|
||||||
|
<p>This method can be called with:
|
||||||
|
- the fields of an contributor as keyword arguments
|
||||||
|
- the fields of an contributor as a dictionary
|
||||||
|
- a list of dictionaries containing the contributor fields</p>
|
||||||
|
<p>An contributor has the following fields:
|
||||||
|
- <em>name</em> conveys a human-readable name for the person.
|
||||||
|
- <em>uri</em> contains a home page for the person.
|
||||||
|
- <em>email</em> contains an email address for the person.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>contributor</strong> – Dictionary or list of dictionaries with contributor
|
||||||
|
data.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of contributors as dictionaries.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.description">
|
||||||
|
<code class="descname">description</code><span class="sig-paren">(</span><em>description=None</em>, <em>isSummary=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.description" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the description value which is the item synopsis.
|
||||||
|
Description is an RSS only element. For ATOM feeds it is split in
|
||||||
|
summary and content. The isSummary parameter can be used to control
|
||||||
|
which ATOM value is set when setting description.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>description</strong> – Description of the entry.</li>
|
||||||
|
<li><strong>isSummary</strong> – If the description should be used as content or
|
||||||
|
summary.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">The entries description.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.enclosure">
|
||||||
|
<code class="descname">enclosure</code><span class="sig-paren">(</span><em>url=None</em>, <em>length=None</em>, <em>type=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.enclosure" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the value of enclosure which describes a media object
|
||||||
|
that is attached to the item. This is a RSS only value which is
|
||||||
|
represented by link(rel=enclosure) in ATOM. ATOM feeds can furthermore
|
||||||
|
contain several enclosures while RSS may contain only one. That is why
|
||||||
|
this method, if repeatedly called, will add more than one enclosures to
|
||||||
|
the feed. However, only the last one is used for RSS.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>url</strong> – URL of the media object.</li>
|
||||||
|
<li><strong>length</strong> – Size of the media in bytes.</li>
|
||||||
|
<li><strong>type</strong> – Mimetype of the linked media.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Data of the enclosure element.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.guid">
|
||||||
|
<code class="descname">guid</code><span class="sig-paren">(</span><em>guid=None</em>, <em>permalink=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.guid" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the entries guid which is a string that uniquely
|
||||||
|
identifies the item. This will also set atom:id.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>guid</strong> – Id of the entry.</li>
|
||||||
|
<li><strong>permalink</strong> – If this is a permanent identifier for this item</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Id and permalink setting of the entry.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.id">
|
||||||
|
<code class="descname">id</code><span class="sig-paren">(</span><em>id=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.id" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the entry id which identifies the entry using a
|
||||||
|
universally unique and permanent URI. Two entries in a feed can have
|
||||||
|
the same value for id if they represent the same entry at different
|
||||||
|
points in time. This method will also set rss:guid with permalink set
|
||||||
|
to False. Id is mandatory for an ATOM entry.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>id</strong> – New Id of the entry.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Id of the entry.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.link">
|
||||||
|
<code class="descname">link</code><span class="sig-paren">(</span><em>link=None</em>, <em>replace=False</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.link" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set link data. An link element is a dict with the fields
|
||||||
|
href, rel, type, hreflang, title, and length. Href is mandatory for
|
||||||
|
ATOM.</p>
|
||||||
|
<p>This method can be called with:
|
||||||
|
- the fields of a link as keyword arguments
|
||||||
|
- the fields of a link as a dictionary
|
||||||
|
- a list of dictionaries containing the link fields</p>
|
||||||
|
<p>A link has the following fields:</p>
|
||||||
|
<ul>
|
||||||
|
<li><p class="first"><em>href</em> is the URI of the referenced resource (typically a Web page)</p>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>rel</em> contains a single link relationship type. It can be a full URI,
|
||||||
|
or one of the following predefined values (default=alternate):</p>
|
||||||
|
<blockquote>
|
||||||
|
<div><ul class="simple">
|
||||||
|
<li><em>alternate</em> an alternate representation of the entry or feed, for
|
||||||
|
example a permalink to the html version of the entry, or the
|
||||||
|
front page of the weblog.</li>
|
||||||
|
<li><em>enclosure</em> a related resource which is potentially large in size
|
||||||
|
and might require special handling, for example an audio or video
|
||||||
|
recording.</li>
|
||||||
|
<li><em>related</em> an document related to the entry or feed.</li>
|
||||||
|
<li><em>self</em> the feed itself.</li>
|
||||||
|
<li><em>via</em> the source of the information provided in the entry.</li>
|
||||||
|
</ul>
|
||||||
|
</div></blockquote>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>type</em> indicates the media type of the resource.</p>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>hreflang</em> indicates the language of the referenced resource.</p>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>title</em> human readable information about the link, typically for
|
||||||
|
display purposes.</p>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>length</em> the length of the resource, in bytes.</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>RSS only supports one link with nothing but a URL. So for the RSS link
|
||||||
|
element the last link with rel=alternate is used.</p>
|
||||||
|
<p>RSS also supports one enclusure element per entry which is covered by
|
||||||
|
the link element in ATOM feed entries. So for the RSS enclusure element
|
||||||
|
the last link with rel=enclosure is used.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>link</strong> – Dict or list of dicts with data.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of link data.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.load_extension">
|
||||||
|
<code class="descname">load_extension</code><span class="sig-paren">(</span><em>name</em>, <em>atom=True</em>, <em>rss=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.load_extension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Load a specific extension by name.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
|
||||||
|
<li><strong>name</strong> – Name of the extension to load.</li>
|
||||||
|
<li><strong>atom</strong> – If the extension should be used for ATOM feeds.</li>
|
||||||
|
<li><strong>rss</strong> – If the extension should be used for RSS feeds.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.pubDate">
|
||||||
|
<code class="descname">pubDate</code><span class="sig-paren">(</span><em>pubDate=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.pubDate" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the pubDate of the entry which indicates when the entry
|
||||||
|
was published. This method is just another name for the published(…)
|
||||||
|
method.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.pubdate">
|
||||||
|
<code class="descname">pubdate</code><span class="sig-paren">(</span><em>pubDate=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.pubdate" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the pubDate of the entry which indicates when the entry
|
||||||
|
was published. This method is just another name for the published(…)
|
||||||
|
method.</p>
|
||||||
|
<p>pubdate(…) is deprecated and may be removed in feedgen ≥ 0.8. Use
|
||||||
|
pubDate(…) instead.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.published">
|
||||||
|
<code class="descname">published</code><span class="sig-paren">(</span><em>published=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.published" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set or get the published value which contains the time of the initial
|
||||||
|
creation or first availability of the entry.</p>
|
||||||
|
<p>The value can either be a string which will automatically be parsed or
|
||||||
|
a datetime.datetime object. In any case it is necessary that the value
|
||||||
|
include timezone information.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>published</strong> – The creation date.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Creation date as datetime.datetime</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.register_extension">
|
||||||
|
<code class="descname">register_extension</code><span class="sig-paren">(</span><em>namespace</em>, <em>extension_class_entry=None</em>, <em>atom=True</em>, <em>rss=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.register_extension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Register a specific extension by classes to a namespace.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
|
||||||
|
<li><strong>namespace</strong> – namespace for the extension</li>
|
||||||
|
<li><strong>extension_class_entry</strong> – Class of the entry extension to load.</li>
|
||||||
|
<li><strong>atom</strong> – If the extension should be used for ATOM feeds.</li>
|
||||||
|
<li><strong>rss</strong> – If the extension should be used for RSS feeds.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.rights">
|
||||||
|
<code class="descname">rights</code><span class="sig-paren">(</span><em>rights=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.rights" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the rights value of the entry which conveys information
|
||||||
|
about rights, e.g. copyrights, held in and over the entry. This ATOM
|
||||||
|
value will also set rss:copyright.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>rights</strong> – Rights information of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Rights information of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.rss_entry">
|
||||||
|
<code class="descname">rss_entry</code><span class="sig-paren">(</span><em>extensions=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.rss_entry" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Create a RSS item and return it.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.source">
|
||||||
|
<code class="descname">source</code><span class="sig-paren">(</span><em>url=None</em>, <em>title=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.source" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the source for the current feed entry.</p>
|
||||||
|
<p>Note that ATOM feeds support a lot more sub elements than title and URL
|
||||||
|
(which is what RSS supports) but these are currently not supported.
|
||||||
|
Patches are welcome.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>url</strong> – Link to the source.</li>
|
||||||
|
<li><strong>title</strong> – Title of the linked resource</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Source element as dictionaries.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.summary">
|
||||||
|
<code class="descname">summary</code><span class="sig-paren">(</span><em>summary=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.summary" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the summary element of an entry which conveys a short
|
||||||
|
summary, abstract, or excerpt of the entry. Summary is an ATOM only
|
||||||
|
element and should be provided if there either is no content provided
|
||||||
|
for the entry, or that content is not inline (i.e., contains a src
|
||||||
|
attribute), or if the content is encoded in base64. This method will
|
||||||
|
also set the rss:description field if it wasn’t previously set or
|
||||||
|
contains the old value of summary.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>summary</strong> – Summary of the entries contents.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Summary of the entries contents.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.title">
|
||||||
|
<code class="descname">title</code><span class="sig-paren">(</span><em>title=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.title" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the title value of the entry. It should contain a human
|
||||||
|
readable title for the entry. Title is mandatory for both ATOM and RSS
|
||||||
|
and should not be blank.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>title</strong> – The new title of the entry.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The entriess title.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.ttl">
|
||||||
|
<code class="descname">ttl</code><span class="sig-paren">(</span><em>ttl=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.ttl" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the ttl value. It is an RSS only element. ttl stands for
|
||||||
|
time to live. It’s a number of minutes that indicates how long a
|
||||||
|
channel can be cached before refreshing from the source.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>ttl</strong> – Integer value representing the time to live.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Time to live of of the entry.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.entry.FeedEntry.updated">
|
||||||
|
<code class="descname">updated</code><span class="sig-paren">(</span><em>updated=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.entry.FeedEntry.updated" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set or get the updated value which indicates the last time the entry
|
||||||
|
was modified in a significant way.</p>
|
||||||
|
<p>The value can either be a string which will automatically be parsed or
|
||||||
|
a datetime.datetime object. In any case it is necessary that the value
|
||||||
|
include timezone information.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>updated</strong> – The modification date.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Modification date as datetime.datetime</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.feed.html">feedgen.feed</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.util.html">feedgen.util</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
965
api.feed.html
Normal file
|
@ -0,0 +1,965 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>feedgen.feed — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="feedgen.entry" href="api.entry.html" />
|
||||||
|
<link rel="prev" title="API Documentation" href="api.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>feedgen.feed</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.html">API Documentation</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.entry.html">feedgen.entry</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<script type=application/javascript src=_static/theme_extras.js></script>
|
||||||
|
<div class="apititle"><b>Contents</b></div>
|
||||||
|
<div class="apitoc"></div><span class="target" id="module-feedgen.feed"></span><div class="section" id="feedgen-feed">
|
||||||
|
<h1>feedgen.feed<a class="headerlink" href="#feedgen-feed" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">copyright:</th><td class="field-body">2013-2016, Lars Kiesow <<a class="reference external" href="mailto:lkiesow%40uos.de">lkiesow<span>@</span>uos<span>.</span>de</a>></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">license:</th><td class="field-body">FreeBSD and LGPL, see license.* for more details.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.feed.</code><code class="descname">FeedGenerator</code><a class="headerlink" href="#feedgen.feed.FeedGenerator" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>FeedGenerator for generating ATOM and RSS feeds.</p>
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.add_entry">
|
||||||
|
<code class="descname">add_entry</code><span class="sig-paren">(</span><em>feedEntry=None</em>, <em>order='prepend'</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.add_entry" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>This method will add a new entry to the feed. If the feedEntry
|
||||||
|
argument is omittet a new Entry object is created automatically. This
|
||||||
|
is the preferred way to add new entries to a feed.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>feedEntry</strong> – FeedEntry object to add.</li>
|
||||||
|
<li><strong>order</strong> – If <cite>prepend</cite> is chosen, the entry will be inserted
|
||||||
|
at the beginning of the feed. If <cite>append</cite> is chosen,
|
||||||
|
the entry will be appended to the feed.
|
||||||
|
(default: <cite>prepend</cite>).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">FeedEntry object created or passed to this function.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>Example:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">...</span>
|
||||||
|
<span class="o">>>></span> <span class="n">entry</span> <span class="o">=</span> <span class="n">feedgen</span><span class="o">.</span><span class="n">add_entry</span><span class="p">()</span>
|
||||||
|
<span class="o">>>></span> <span class="n">entry</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'First feed entry'</span><span class="p">)</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.add_item">
|
||||||
|
<code class="descname">add_item</code><span class="sig-paren">(</span><em>item=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.add_item" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>This method will add a new item to the feed. If the item argument is
|
||||||
|
omittet a new FeedEntry object is created automatically. This is just
|
||||||
|
another name for add_entry(…)</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.atom_file">
|
||||||
|
<code class="descname">atom_file</code><span class="sig-paren">(</span><em>filename</em>, <em>extensions=True</em>, <em>pretty=False</em>, <em>encoding='UTF-8'</em>, <em>xml_declaration=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.atom_file" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Generates an ATOM feed and write the resulting XML to a file.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
|
||||||
|
<li><strong>filename</strong> – Name of file to write or a file-like object or a URL.</li>
|
||||||
|
<li><strong>extensions</strong> – Enable or disable the loaded extensions for the xml
|
||||||
|
generation (default: enabled).</li>
|
||||||
|
<li><strong>pretty</strong> – If the feed should be split into multiple lines and
|
||||||
|
properly indented.</li>
|
||||||
|
<li><strong>encoding</strong> – Encoding used in the XML file (default: UTF-8).</li>
|
||||||
|
<li><strong>xml_declaration</strong> – If an XML declaration should be added to the
|
||||||
|
output (Default: enabled).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.atom_str">
|
||||||
|
<code class="descname">atom_str</code><span class="sig-paren">(</span><em>pretty=False</em>, <em>extensions=True</em>, <em>encoding='UTF-8'</em>, <em>xml_declaration=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.atom_str" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Generates an ATOM feed and returns the feed XML as string.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>pretty</strong> – If the feed should be split into multiple lines and
|
||||||
|
properly indented.</li>
|
||||||
|
<li><strong>extensions</strong> – Enable or disable the loaded extensions for the xml
|
||||||
|
generation (default: enabled).</li>
|
||||||
|
<li><strong>encoding</strong> – Encoding used in the XML file (default: UTF-8).</li>
|
||||||
|
<li><strong>xml_declaration</strong> – If an XML declaration should be added to the
|
||||||
|
output (Default: enabled).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">String representation of the ATOM feed.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p><strong>Return type:</strong> The return type may vary between different Python
|
||||||
|
versions and your encoding parameters passed to this method. For
|
||||||
|
details have a look at the <a class="reference external" href="https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.tostring">lxml documentation</a></p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.author">
|
||||||
|
<code class="descname">author</code><span class="sig-paren">(</span><em>author=None</em>, <em>replace=False</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.author" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set author data. An author element is a dictionary containing
|
||||||
|
a name, an email address and a URI. Name is mandatory for ATOM, email
|
||||||
|
is mandatory for RSS.</p>
|
||||||
|
<p>This method can be called with:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>the fields of an author as keyword arguments</li>
|
||||||
|
<li>the fields of an author as a dictionary</li>
|
||||||
|
<li>a list of dictionaries containing the author fields</li>
|
||||||
|
</ul>
|
||||||
|
<p>An author has the following fields:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><em>name</em> conveys a human-readable name for the person.</li>
|
||||||
|
<li><em>uri</em> contains a home page for the person.</li>
|
||||||
|
<li><em>email</em> contains an email address for the person.</li>
|
||||||
|
</ul>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>author</strong> – Dictionary or list of dictionaries with author data.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of authors as dictionaries.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>Example:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">feedgen</span><span class="o">.</span><span class="n">author</span><span class="p">({</span><span class="s1">'name'</span><span class="p">:</span><span class="s1">'John Doe'</span><span class="p">,</span> <span class="s1">'email'</span><span class="p">:</span><span class="s1">'jdoe@example.com'</span><span class="p">})</span>
|
||||||
|
<span class="go">[{'name':'John Doe','email':'jdoe@example.com'}]</span>
|
||||||
|
|
||||||
|
<span class="gp">>>> </span><span class="n">feedgen</span><span class="o">.</span><span class="n">author</span><span class="p">([{</span><span class="s1">'name'</span><span class="p">:</span><span class="s1">'Mr. X'</span><span class="p">},{</span><span class="s1">'name'</span><span class="p">:</span><span class="s1">'Max'</span><span class="p">}])</span>
|
||||||
|
<span class="go">[{'name':'John Doe','email':'jdoe@example.com'},</span>
|
||||||
|
<span class="go"> {'name':'John Doe'}, {'name':'Max'}]</span>
|
||||||
|
|
||||||
|
<span class="gp">>>> </span><span class="n">feedgen</span><span class="o">.</span><span class="n">author</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'John Doe'</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s1">'jdoe@example.com'</span><span class="p">,</span>
|
||||||
|
<span class="go"> replace=True)</span>
|
||||||
|
<span class="go">[{'name':'John Doe','email':'jdoe@example.com'}]</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.category">
|
||||||
|
<code class="descname">category</code><span class="sig-paren">(</span><em>category=None</em>, <em>replace=False</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.category" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set categories that the feed belongs to.</p>
|
||||||
|
<p>This method can be called with:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>the fields of a category as keyword arguments</li>
|
||||||
|
<li>the fields of a category as a dictionary</li>
|
||||||
|
<li>a list of dictionaries containing the category fields</li>
|
||||||
|
</ul>
|
||||||
|
<p>A categories has the following fields:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><em>term</em> identifies the category</li>
|
||||||
|
<li><em>scheme</em> identifies the categorization scheme via a URI.</li>
|
||||||
|
<li><em>label</em> provides a human-readable label for display</li>
|
||||||
|
</ul>
|
||||||
|
<p>If a label is present it is used for the RSS feeds. Otherwise the term
|
||||||
|
is used. The scheme is used for the domain attribute in RSS.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>link</strong> – Dict or list of dicts with data.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of category data.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.cloud">
|
||||||
|
<code class="descname">cloud</code><span class="sig-paren">(</span><em>domain=None</em>, <em>port=None</em>, <em>path=None</em>, <em>registerProcedure=None</em>, <em>protocol=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.cloud" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set or get the cloud data of the feed. It is an RSS only attribute.
|
||||||
|
It specifies a web service that supports the rssCloud interface which
|
||||||
|
can be implemented in HTTP-POST, XML-RPC or SOAP 1.1.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>domain</strong> – The domain where the webservice can be found.</li>
|
||||||
|
<li><strong>port</strong> – The port the webservice listens to.</li>
|
||||||
|
<li><strong>path</strong> – The path of the webservice.</li>
|
||||||
|
<li><strong>registerProcedure</strong> – The procedure to call.</li>
|
||||||
|
<li><strong>protocol</strong> – Can be either HTTP-POST, XML-RPC or SOAP 1.1.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Dictionary containing the cloud data.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.contributor">
|
||||||
|
<code class="descname">contributor</code><span class="sig-paren">(</span><em>contributor=None</em>, <em>replace=False</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.contributor" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the contributor data of the feed. This is an ATOM only
|
||||||
|
value.</p>
|
||||||
|
<p>This method can be called with:
|
||||||
|
- the fields of an contributor as keyword arguments
|
||||||
|
- the fields of an contributor as a dictionary
|
||||||
|
- a list of dictionaries containing the contributor fields</p>
|
||||||
|
<p>An contributor has the following fields:
|
||||||
|
- <em>name</em> conveys a human-readable name for the person.
|
||||||
|
- <em>uri</em> contains a home page for the person.
|
||||||
|
- <em>email</em> contains an email address for the person.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>contributor</strong> – Dictionary or list of dictionaries with contributor
|
||||||
|
data.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of contributors as dictionaries.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.copyright">
|
||||||
|
<code class="descname">copyright</code><span class="sig-paren">(</span><em>copyright=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.copyright" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the copyright notice for content in the channel. This RSS
|
||||||
|
value will also set the atom:rights value.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>copyright</strong> – The copyright notice.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The copyright notice.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.description">
|
||||||
|
<code class="descname">description</code><span class="sig-paren">(</span><em>description=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.description" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set and get the description of the feed. This is an RSS only element
|
||||||
|
which is a phrase or sentence describing the channel. It is mandatory
|
||||||
|
for RSS feeds. It is roughly the same as atom:subtitle. Thus setting
|
||||||
|
this will also set atom:subtitle.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>description</strong> – Description of the channel.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Description of the channel.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.docs">
|
||||||
|
<code class="descname">docs</code><span class="sig-paren">(</span><em>docs=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.docs" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the docs value of the feed. This is an RSS only value. It
|
||||||
|
is a URL that points to the documentation for the format used in the
|
||||||
|
RSS file. It is probably a pointer to [1]. It is for people who might
|
||||||
|
stumble across an RSS file on a Web server 25 years from now and wonder
|
||||||
|
what it is.</p>
|
||||||
|
<p>[1]: <a class="reference external" href="http://www.rssboard.org/rss-specification">http://www.rssboard.org/rss-specification</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>docs</strong> – URL of the format documentation.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">URL of the format documentation.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.entry">
|
||||||
|
<code class="descname">entry</code><span class="sig-paren">(</span><em>entry=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.entry" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set feed entries. Use the add_entry() method instead to
|
||||||
|
automatically create the FeedEntry objects.</p>
|
||||||
|
<p>This method takes both a single FeedEntry object or a list of objects.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>entry</strong> – FeedEntry object or list of FeedEntry objects.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">List ob all feed entries.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.generator">
|
||||||
|
<code class="descname">generator</code><span class="sig-paren">(</span><em>generator=None</em>, <em>version=None</em>, <em>uri=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.generator" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the generator of the feed which identifies the software
|
||||||
|
used to generate the feed, for debugging and other purposes. Both the
|
||||||
|
uri and version attributes are optional and only available in the ATOM
|
||||||
|
feed.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
|
||||||
|
<li><strong>generator</strong> – Software used to create the feed.</li>
|
||||||
|
<li><strong>version</strong> – Version of the software.</li>
|
||||||
|
<li><strong>uri</strong> – URI the software can be found.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.icon">
|
||||||
|
<code class="descname">icon</code><span class="sig-paren">(</span><em>icon=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.icon" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the icon of the feed which is a small image which
|
||||||
|
provides iconic visual identification for the feed. Icons should be
|
||||||
|
square. This is an ATOM only value.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>icon</strong> – URI of the feeds icon.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">URI of the feeds icon.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.id">
|
||||||
|
<code class="descname">id</code><span class="sig-paren">(</span><em>id=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.id" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the feed id which identifies the feed using a universally
|
||||||
|
unique and permanent URI. If you have a long-term, renewable lease on
|
||||||
|
your Internet domain name, then you can feel free to use your website’s
|
||||||
|
address. This field is for ATOM only. It is mandatory for ATOM.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>id</strong> – New Id of the ATOM feed.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Id of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.image">
|
||||||
|
<code class="descname">image</code><span class="sig-paren">(</span><em>url=None</em>, <em>title=None</em>, <em>link=None</em>, <em>width=None</em>, <em>height=None</em>, <em>description=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.image" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set the image of the feed. This element is roughly equivalent to
|
||||||
|
atom:logo.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>url</strong> – The URL of a GIF, JPEG or PNG image.</li>
|
||||||
|
<li><strong>title</strong> – Describes the image. The default value is the feeds
|
||||||
|
title.</li>
|
||||||
|
<li><strong>link</strong> – URL of the site the image will link to. The default is to
|
||||||
|
use the feeds first altertate link.</li>
|
||||||
|
<li><strong>width</strong> – Width of the image in pixel. The maximum is 144.</li>
|
||||||
|
<li><strong>height</strong> – The height of the image. The maximum is 400.</li>
|
||||||
|
<li><strong>description</strong> – Title of the link.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Data of the image as dictionary.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.item">
|
||||||
|
<code class="descname">item</code><span class="sig-paren">(</span><em>item=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.item" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set feed items. This is just another name for entry(…)</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.language">
|
||||||
|
<code class="descname">language</code><span class="sig-paren">(</span><em>language=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.language" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the language of the feed. It indicates the language the
|
||||||
|
channel is written in. This allows aggregators to group all Italian
|
||||||
|
language sites, for example, on a single page. This is an RSS only
|
||||||
|
field. However, this value will also be used to set the xml:lang
|
||||||
|
property of the ATOM feed node.
|
||||||
|
The value should be an IETF language tag.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>language</strong> – Language of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Language of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.lastBuildDate">
|
||||||
|
<code class="descname">lastBuildDate</code><span class="sig-paren">(</span><em>lastBuildDate=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.lastBuildDate" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set or get the lastBuildDate value which indicates the last time the
|
||||||
|
content of the channel changed.</p>
|
||||||
|
<p>The value can either be a string which will automatically be parsed or
|
||||||
|
a datetime.datetime object. In any case it is necessary that the value
|
||||||
|
include timezone information.</p>
|
||||||
|
<p>This will set both atom:updated and rss:lastBuildDate.</p>
|
||||||
|
<dl class="docutils">
|
||||||
|
<dt>Default value</dt>
|
||||||
|
<dd>If not set, lastBuildDate has as value the current date and time.</dd>
|
||||||
|
</dl>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>lastBuildDate</strong> – The modification date.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Modification date as datetime.datetime</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.link">
|
||||||
|
<code class="descname">link</code><span class="sig-paren">(</span><em>link=None</em>, <em>replace=False</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.link" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set link data. An link element is a dict with the fields
|
||||||
|
href, rel, type, hreflang, title, and length. Href is mandatory for
|
||||||
|
ATOM.</p>
|
||||||
|
<p>This method can be called with:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>the fields of a link as keyword arguments</li>
|
||||||
|
<li>the fields of a link as a dictionary</li>
|
||||||
|
<li>a list of dictionaries containing the link fields</li>
|
||||||
|
</ul>
|
||||||
|
<p>A link has the following fields:</p>
|
||||||
|
<ul>
|
||||||
|
<li><p class="first"><em>href</em> is the URI of the referenced resource (typically a Web page)</p>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>rel</em> contains a single link relationship type. It can be a full URI,
|
||||||
|
or one of the following predefined values (default=alternate):</p>
|
||||||
|
<blockquote>
|
||||||
|
<div><ul class="simple">
|
||||||
|
<li><em>alternate</em> an alternate representation of the entry or feed, for
|
||||||
|
example a permalink to the html version of the entry, or the
|
||||||
|
front page of the weblog.</li>
|
||||||
|
<li><em>enclosure</em> a related resource which is potentially large in size
|
||||||
|
and might require special handling, for example an audio or video
|
||||||
|
recording.</li>
|
||||||
|
<li><em>related</em> an document related to the entry or feed.</li>
|
||||||
|
<li><em>self</em> the feed itself.</li>
|
||||||
|
<li><em>via</em> the source of the information provided in the entry.</li>
|
||||||
|
</ul>
|
||||||
|
</div></blockquote>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>type</em> indicates the media type of the resource.</p>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>hreflang</em> indicates the language of the referenced resource.</p>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>title</em> human readable information about the link, typically for
|
||||||
|
display purposes.</p>
|
||||||
|
</li>
|
||||||
|
<li><p class="first"><em>length</em> the length of the resource, in bytes.</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>RSS only supports one link with URL only.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>link</strong> – Dict or list of dicts with data.</li>
|
||||||
|
<li><strong>replace</strong> – If old links are to be replaced (default: False)</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Current set of link data</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>Example:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">feedgen</span><span class="o">.</span><span class="n">link</span><span class="p">(</span> <span class="n">href</span><span class="o">=</span><span class="s1">'http://example.com/'</span><span class="p">,</span> <span class="n">rel</span><span class="o">=</span><span class="s1">'self'</span><span class="p">)</span>
|
||||||
|
<span class="go">[{'href':'http://example.com/', 'rel':'self'}]</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.load_extension">
|
||||||
|
<code class="descname">load_extension</code><span class="sig-paren">(</span><em>name</em>, <em>atom=True</em>, <em>rss=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.load_extension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Load a specific extension by name.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
|
||||||
|
<li><strong>name</strong> – Name of the extension to load.</li>
|
||||||
|
<li><strong>atom</strong> – If the extension should be used for ATOM feeds.</li>
|
||||||
|
<li><strong>rss</strong> – If the extension should be used for RSS feeds.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.logo">
|
||||||
|
<code class="descname">logo</code><span class="sig-paren">(</span><em>logo=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.logo" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the logo of the feed which is a larger image which
|
||||||
|
provides visual identification for the feed. Images should be twice as
|
||||||
|
wide as they are tall. This is an ATOM value but will also set the
|
||||||
|
rss:image value.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>logo</strong> – Logo of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Logo of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.managingEditor">
|
||||||
|
<code class="descname">managingEditor</code><span class="sig-paren">(</span><em>managingEditor=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.managingEditor" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set or get the value for managingEditor which is the email address
|
||||||
|
for person responsible for editorial content. This is a RSS only
|
||||||
|
value.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>managingEditor</strong> – Email address of the managing editor.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Email address of the managing editor.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.pubDate">
|
||||||
|
<code class="descname">pubDate</code><span class="sig-paren">(</span><em>pubDate=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.pubDate" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set or get the publication date for the content in the channel. For
|
||||||
|
example, the New York Times publishes on a daily basis, the publication
|
||||||
|
date flips once every 24 hours. That’s when the pubDate of the channel
|
||||||
|
changes.</p>
|
||||||
|
<p>The value can either be a string which will automatically be parsed or
|
||||||
|
a datetime.datetime object. In any case it is necessary that the value
|
||||||
|
include timezone information.</p>
|
||||||
|
<p>This will set both atom:updated and rss:lastBuildDate.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>pubDate</strong> – The publication date.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Publication date as datetime.datetime</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.rating">
|
||||||
|
<code class="descname">rating</code><span class="sig-paren">(</span><em>rating=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.rating" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set and get the PICS rating for the channel. It is an RSS only
|
||||||
|
value.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.register_extension">
|
||||||
|
<code class="descname">register_extension</code><span class="sig-paren">(</span><em>namespace</em>, <em>extension_class_feed=None</em>, <em>extension_class_entry=None</em>, <em>atom=True</em>, <em>rss=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.register_extension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Registers an extension by class.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
|
||||||
|
<li><strong>namespace</strong> – namespace for the extension</li>
|
||||||
|
<li><strong>extension_class_feed</strong> – Class of the feed extension to load.</li>
|
||||||
|
<li><strong>extension_class_entry</strong> – Class of the entry extension to load</li>
|
||||||
|
<li><strong>atom</strong> – If the extension should be used for ATOM feeds.</li>
|
||||||
|
<li><strong>rss</strong> – If the extension should be used for RSS feeds.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.remove_entry">
|
||||||
|
<code class="descname">remove_entry</code><span class="sig-paren">(</span><em>entry</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.remove_entry" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Remove a single entry from the feed. This method accepts both the
|
||||||
|
FeedEntry object to remove or the index of the entry as argument.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>entry</strong> – Entry or index of entry to remove.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.remove_item">
|
||||||
|
<code class="descname">remove_item</code><span class="sig-paren">(</span><em>item</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.remove_item" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Remove a single item from the feed. This is another name for
|
||||||
|
remove_entry.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.rights">
|
||||||
|
<code class="descname">rights</code><span class="sig-paren">(</span><em>rights=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.rights" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the rights value of the feed which conveys information
|
||||||
|
about rights, e.g. copyrights, held in and over the feed. This ATOM
|
||||||
|
value will also set rss:copyright.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>rights</strong> – Rights information of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.rss_file">
|
||||||
|
<code class="descname">rss_file</code><span class="sig-paren">(</span><em>filename</em>, <em>extensions=True</em>, <em>pretty=False</em>, <em>encoding='UTF-8'</em>, <em>xml_declaration=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.rss_file" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Generates an RSS feed and write the resulting XML to a file.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
|
||||||
|
<li><strong>filename</strong> – Name of file to write or a file-like object or a URL.</li>
|
||||||
|
<li><strong>extensions</strong> – Enable or disable the loaded extensions for the xml
|
||||||
|
generation (default: enabled).</li>
|
||||||
|
<li><strong>pretty</strong> – If the feed should be split into multiple lines and
|
||||||
|
properly indented.</li>
|
||||||
|
<li><strong>encoding</strong> – Encoding used in the XML file (default: UTF-8).</li>
|
||||||
|
<li><strong>xml_declaration</strong> – If an XML declaration should be added to the
|
||||||
|
output (Default: enabled).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.rss_str">
|
||||||
|
<code class="descname">rss_str</code><span class="sig-paren">(</span><em>pretty=False</em>, <em>extensions=True</em>, <em>encoding='UTF-8'</em>, <em>xml_declaration=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.rss_str" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Generates an RSS feed and returns the feed XML as string.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>pretty</strong> – If the feed should be split into multiple lines and
|
||||||
|
properly indented.</li>
|
||||||
|
<li><strong>extensions</strong> – Enable or disable the loaded extensions for the xml
|
||||||
|
generation (default: enabled).</li>
|
||||||
|
<li><strong>encoding</strong> – Encoding used in the XML file (default: UTF-8).</li>
|
||||||
|
<li><strong>xml_declaration</strong> – If an XML declaration should be added to the
|
||||||
|
output (Default: enabled).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">String representation of the RSS feed.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p><strong>Return type:</strong> The return type may vary between different Python
|
||||||
|
versions and your encoding parameters passed to this method. For
|
||||||
|
details have a look at the <a class="reference external" href="https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.tostring">lxml documentation</a></p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.skipDays">
|
||||||
|
<code class="descname">skipDays</code><span class="sig-paren">(</span><em>days=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.skipDays" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set or get the value of skipDays, a hint for aggregators telling
|
||||||
|
them which days they can skip This is an RSS only value.</p>
|
||||||
|
<p>This method can be called with a day name or a list of day names. The
|
||||||
|
days are represented as strings from ‘Monday’ to ‘Sunday’.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>hours</strong> – List of days the feedreaders should not check the feed.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of days the feedreaders should not check the feed.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.skipHours">
|
||||||
|
<code class="descname">skipHours</code><span class="sig-paren">(</span><em>hours=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.skipHours" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set or get the value of skipHours, a hint for aggregators telling
|
||||||
|
them which hours they can skip. This is an RSS only value.</p>
|
||||||
|
<p>This method can be called with an hour or a list of hours. The hours
|
||||||
|
are represented as integer values from 0 to 23.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>hours</strong> – List of hours the feedreaders should not check the feed.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of hours the feedreaders should not check the feed.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.subtitle">
|
||||||
|
<code class="descname">subtitle</code><span class="sig-paren">(</span><em>subtitle=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.subtitle" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the subtitle value of the cannel which contains a
|
||||||
|
human-readable description or subtitle for the feed. This ATOM property
|
||||||
|
will also set the value for rss:description.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>subtitle</strong> – The subtitle of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The subtitle of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.textInput">
|
||||||
|
<code class="descname">textInput</code><span class="sig-paren">(</span><em>title=None</em>, <em>description=None</em>, <em>name=None</em>, <em>link=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.textInput" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the value of textInput. This is an RSS only field. The
|
||||||
|
purpose of the <textInput> element is something of a mystery. You can
|
||||||
|
use it to specify a search engine box. Or to allow a reader to provide
|
||||||
|
feedback. Most aggregators ignore it.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>title</strong> – The label of the Submit button in the text input area.</li>
|
||||||
|
<li><strong>description</strong> – Explains the text input area.</li>
|
||||||
|
<li><strong>name</strong> – The name of the text object in the text input area.</li>
|
||||||
|
<li><strong>link</strong> – The URL of the CGI script that processes text input
|
||||||
|
requests.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Dictionary containing textInput values.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.title">
|
||||||
|
<code class="descname">title</code><span class="sig-paren">(</span><em>title=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.title" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the title value of the feed. It should contain a human
|
||||||
|
readable title for the feed. Often the same as the title of the
|
||||||
|
associated website. Title is mandatory for both ATOM and RSS and should
|
||||||
|
not be blank.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>title</strong> – The new title of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The feeds title.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.ttl">
|
||||||
|
<code class="descname">ttl</code><span class="sig-paren">(</span><em>ttl=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.ttl" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the ttl value. It is an RSS only element. ttl stands for
|
||||||
|
time to live. It’s a number of minutes that indicates how long a
|
||||||
|
channel can be cached before refreshing from the source.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>ttl</strong> – Integer value indicating how long the channel may be
|
||||||
|
cached.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Time to live.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.updated">
|
||||||
|
<code class="descname">updated</code><span class="sig-paren">(</span><em>updated=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.updated" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Set or get the updated value which indicates the last time the feed
|
||||||
|
was modified in a significant way.</p>
|
||||||
|
<p>The value can either be a string which will automatically be parsed or
|
||||||
|
a datetime.datetime object. In any case it is necessary that the value
|
||||||
|
include timezone information.</p>
|
||||||
|
<p>This will set both atom:updated and rss:lastBuildDate.</p>
|
||||||
|
<dl class="docutils">
|
||||||
|
<dt>Default value</dt>
|
||||||
|
<dd>If not set, updated has as value the current date and time.</dd>
|
||||||
|
</dl>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>updated</strong> – The modification date.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Modification date as datetime.datetime</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.feed.FeedGenerator.webMaster">
|
||||||
|
<code class="descname">webMaster</code><span class="sig-paren">(</span><em>webMaster=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.feed.FeedGenerator.webMaster" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get and set the value of webMaster, which represents the email
|
||||||
|
address for the person responsible for technical issues relating to the
|
||||||
|
feed. This is an RSS only value.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>webMaster</strong> – Email address of the webmaster.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Email address of the webmaster.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.html">API Documentation</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.entry.html">feedgen.entry</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
200
api.html
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>API Documentation — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="feedgen.feed" href="api.feed.html" />
|
||||||
|
<link rel="prev" title="Feedgenerator" href="index.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>API Documentation</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="index.html">Feedgenerator</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.feed.html">feedgen.feed</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="section" id="module-feedgen">
|
||||||
|
<span id="api-documentation"></span><h1>API Documentation<a class="headerlink" href="#module-feedgen" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<div class="section" id="feedgen">
|
||||||
|
<h2>feedgen<a class="headerlink" href="#feedgen" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>This module can be used to generate web feeds in both ATOM and RSS format.
|
||||||
|
It has support for extensions. Included is for example an extension to
|
||||||
|
produce Podcasts.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">copyright:</th><td class="field-body">2013 by Lars Kiesow</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">license:</th><td class="field-body">FreeBSD and LGPL, see license.* for more details.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="section" id="create-a-feed">
|
||||||
|
<h3>Create a Feed<a class="headerlink" href="#create-a-feed" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>To create a feed simply instantiate the FeedGenerator class and insert some
|
||||||
|
data:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">feedgen.feed</span> <span class="k">import</span> <span class="n">FeedGenerator</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span> <span class="o">=</span> <span class="n">FeedGenerator</span><span class="p">()</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">id</span><span class="p">(</span><span class="s1">'http://lernfunk.de/media/654321'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'Some Testfeed'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">author</span><span class="p">(</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span><span class="s1">'John Doe'</span><span class="p">,</span><span class="s1">'email'</span><span class="p">:</span><span class="s1">'john@example.de'</span><span class="p">}</span> <span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">link</span><span class="p">(</span> <span class="n">href</span><span class="o">=</span><span class="s1">'http://example.com'</span><span class="p">,</span> <span class="n">rel</span><span class="o">=</span><span class="s1">'alternate'</span> <span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">logo</span><span class="p">(</span><span class="s1">'http://ex.com/logo.jpg'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">subtitle</span><span class="p">(</span><span class="s1">'This is a cool feed!'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">link</span><span class="p">(</span> <span class="n">href</span><span class="o">=</span><span class="s1">'http://larskiesow.de/test.atom'</span><span class="p">,</span> <span class="n">rel</span><span class="o">=</span><span class="s1">'self'</span> <span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">language</span><span class="p">(</span><span class="s1">'en'</span><span class="p">)</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>Note that for the methods which set fields that can occur more than once in
|
||||||
|
a feed you can use all of the following ways to provide data:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>Provide the data for that element as keyword arguments</li>
|
||||||
|
<li>Provide the data for that element as dictionary</li>
|
||||||
|
<li>Provide a list of dictionaries with the data for several elements</li>
|
||||||
|
</ul>
|
||||||
|
<p>Example:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>>>> fg.contributor(name='John Doe', email='jdoe@example.com' )
|
||||||
|
>>> fg.contributor({'name':'John Doe', 'email':'jdoe@example.com'})
|
||||||
|
>>> fg.contributor([{'name':'John', 'email':'jdoe@example.com'}, …])
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="generate-the-feed">
|
||||||
|
<h3>Generate the Feed<a class="headerlink" href="#generate-the-feed" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>After that you can generate both RSS or ATOM by calling the respective
|
||||||
|
method:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">atomfeed</span> <span class="o">=</span> <span class="n">fg</span><span class="o">.</span><span class="n">atom_str</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># Get the ATOM feed as string</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">rssfeed</span> <span class="o">=</span> <span class="n">fg</span><span class="o">.</span><span class="n">rss_str</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># Get the RSS feed as string</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">atom_file</span><span class="p">(</span><span class="s1">'atom.xml'</span><span class="p">)</span> <span class="c1"># Write the ATOM feed to a file</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">rss_file</span><span class="p">(</span><span class="s1">'rss.xml'</span><span class="p">)</span> <span class="c1"># Write the RSS feed to a file</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="add-feed-entries">
|
||||||
|
<h3>Add Feed Entries<a class="headerlink" href="#add-feed-entries" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>To add entries (items) to a feed you need to create new FeedEntry objects
|
||||||
|
and append them to the list of entries in the FeedGenerator. The most
|
||||||
|
convenient way to go is to use the FeedGenerator itself for the
|
||||||
|
instantiation of the FeedEntry object:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">fe</span> <span class="o">=</span> <span class="n">fg</span><span class="o">.</span><span class="n">add_entry</span><span class="p">()</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span><span class="o">.</span><span class="n">id</span><span class="p">(</span><span class="s1">'http://lernfunk.de/media/654321/1'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'The First Episode'</span><span class="p">)</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>The FeedGenerators method add_entry(…) without argument provides will
|
||||||
|
automatically generate a new FeedEntry object, append it to the feeds
|
||||||
|
internal list of entries and return it, so that additional data can be
|
||||||
|
added.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="extensions">
|
||||||
|
<h3>Extensions<a class="headerlink" href="#extensions" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>The FeedGenerator supports extension to include additional data into the
|
||||||
|
XML structure of the feeds. Extensions can be loaded like this:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">load_extension</span><span class="p">(</span><span class="s1">'someext'</span><span class="p">,</span> <span class="n">atom</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">rss</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>This will try to load the extension “someext” from the file
|
||||||
|
<cite>ext/someext.py</cite>. It is required that <cite>someext.py</cite> contains a class named
|
||||||
|
“SomextExtension” which is required to have at least the two methods
|
||||||
|
<cite>extend_rss(…)</cite> and <cite>extend_atom(…)</cite>. Although not required, it is
|
||||||
|
strongly suggested to use BaseExtension from <cite>ext/base.py</cite> as superclass.</p>
|
||||||
|
<p><cite>load_extension(‘someext’, …)</cite> will also try to load a class named
|
||||||
|
“SomextEntryExtension” for every entry of the feed. This class can be
|
||||||
|
located either in the same file as SomextExtension or in
|
||||||
|
<cite>ext/someext_entry.py</cite> which is suggested especially for large extensions.</p>
|
||||||
|
<p>The parameters <cite>atom</cite> and <cite>rss</cite> tell the FeedGenerator if the extensions
|
||||||
|
should only be used for either ATOM or RSS feeds. The default value for
|
||||||
|
both parameters is true which means that the extension would be used for
|
||||||
|
both kinds of feeds.</p>
|
||||||
|
<p><strong>Example: Producing a Podcast</strong></p>
|
||||||
|
<p>One extension already provided is the podcast extension. A podcast is an
|
||||||
|
RSS feed with some additional elements for ITunes.</p>
|
||||||
|
<p>To produce a podcast simply load the <cite>podcast</cite> extension:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">feedgen.feed</span> <span class="k">import</span> <span class="n">FeedGenerator</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span> <span class="o">=</span> <span class="n">FeedGenerator</span><span class="p">()</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">load_extension</span><span class="p">(</span><span class="s1">'podcast'</span><span class="p">)</span>
|
||||||
|
<span class="gp">...</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">podcast</span><span class="o">.</span><span class="n">itunes_category</span><span class="p">(</span><span class="s1">'Technology'</span><span class="p">,</span> <span class="s1">'Podcasting'</span><span class="p">)</span>
|
||||||
|
<span class="gp">...</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">rss_str</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">rss_file</span><span class="p">(</span><span class="s1">'podcast.xml'</span><span class="p">)</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>Of cause the extension has to be loaded for the FeedEntry objects as well
|
||||||
|
but this is done automatically by the FeedGenerator for every feed entry if
|
||||||
|
the extension is loaded for the whole feed. You can, however, load an
|
||||||
|
extension for a specific FeedEntry by calling <cite>load_extension(…)</cite> on that
|
||||||
|
entry. But this is a rather uncommon use.</p>
|
||||||
|
<p>Of cause you can still produce a normal ATOM or RSS feed, even if you have
|
||||||
|
loaded some plugins by temporary disabling them during the feed generation.
|
||||||
|
This can be done by calling the generating method with the keyword argument
|
||||||
|
<cite>extensions</cite> set to <cite>False</cite>.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="testing-the-generator">
|
||||||
|
<h3>Testing the Generator<a class="headerlink" href="#testing-the-generator" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>You can test the module by simply executing:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ python -m feedgen
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Contents:</p>
|
||||||
|
<div class="toctree-wrapper compound">
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="api.feed.html">feedgen.feed</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="api.entry.html">feedgen.entry</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="api.util.html">feedgen.util</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="ext/api.ext.base.html">feedgen.ext.base</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="ext/api.ext.dc.html">feedgen.ext.dc</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="ext/api.ext.podcast.html">feedgen.ext.podcast</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="ext/api.ext.podcast_entry.html">feedgen.ext.podcast_entry</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="ext/api.ext.torrent.html">feedgen.ext.torrent</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="index.html">Feedgenerator</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.feed.html">feedgen.feed</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
109
api.util.html
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>feedgen.util — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="feedgen.ext.base" href="ext/api.ext.base.html" />
|
||||||
|
<link rel="prev" title="feedgen.entry" href="api.entry.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>feedgen.util</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.entry.html">feedgen.entry</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="ext/api.ext.base.html">feedgen.ext.base</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<script type=application/javascript src=_static/theme_extras.js></script>
|
||||||
|
<div class="apititle"><b>Contents</b></div>
|
||||||
|
<div class="apitoc"></div><span class="target" id="module-feedgen.util"></span><div class="section" id="feedgen-util">
|
||||||
|
<h1>feedgen.util<a class="headerlink" href="#feedgen-util" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>This file contains helper functions for the feed generator module.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">copyright:</th><td class="field-body">2013, Lars Kiesow <<a class="reference external" href="mailto:lkiesow%40uos.de">lkiesow<span>@</span>uos<span>.</span>de</a>></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">license:</th><td class="field-body">FreeBSD and LGPL, see license.* for more details.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<dl class="function">
|
||||||
|
<dt id="feedgen.util.ensure_format">
|
||||||
|
<code class="descclassname">feedgen.util.</code><code class="descname">ensure_format</code><span class="sig-paren">(</span><em>val</em>, <em>allowed</em>, <em>required</em>, <em>allowed_values=None</em>, <em>defaults=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.util.ensure_format" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Takes a dictionary or a list of dictionaries and check if all keys are in
|
||||||
|
the set of allowed keys, if all required keys are present and if the values
|
||||||
|
of a specific key are ok.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>val</strong> – Dictionaries to check.</li>
|
||||||
|
<li><strong>allowed</strong> – Set of allowed keys.</li>
|
||||||
|
<li><strong>required</strong> – Set of required keys.</li>
|
||||||
|
<li><strong>allowed_values</strong> – Dictionary with keys and sets of their allowed
|
||||||
|
values.</li>
|
||||||
|
<li><strong>defaults</strong> – Dictionary with default values.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of checked dictionaries.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="function">
|
||||||
|
<dt id="feedgen.util.formatRFC2822">
|
||||||
|
<code class="descclassname">feedgen.util.</code><code class="descname">formatRFC2822</code><span class="sig-paren">(</span><em>date</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.util.formatRFC2822" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Make sure the locale setting do not interfere with the time format.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.entry.html">feedgen.entry</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="ext/api.ext.base.html">feedgen.ext.base</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
155
doc/Makefile
|
@ -1,155 +0,0 @@
|
||||||
# Makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
|
||||||
SPHINXOPTS =
|
|
||||||
SPHINXBUILD = sphinx-build
|
|
||||||
#SPHINXBUILD = python /home/lars/master-thesis/code/modules/core/venv/bin/sphinx-build
|
|
||||||
PAPER =
|
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# Internal variables.
|
|
||||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
|
||||||
PAPEROPT_letter = -D latex_paper_size=letter
|
|
||||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
|
||||||
# the i18n builder cannot share the environment and doctrees with the others
|
|
||||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
|
||||||
|
|
||||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
|
||||||
|
|
||||||
help:
|
|
||||||
@echo "Please use \`make <target>' where <target> is one of"
|
|
||||||
@echo " html to make standalone HTML files"
|
|
||||||
@echo " dirhtml to make HTML files named index.html in directories"
|
|
||||||
@echo " singlehtml to make a single large HTML file"
|
|
||||||
@echo " pickle to make pickle files"
|
|
||||||
@echo " json to make JSON files"
|
|
||||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
|
||||||
@echo " qthelp to make HTML files and a qthelp project"
|
|
||||||
@echo " devhelp to make HTML files and a Devhelp project"
|
|
||||||
@echo " epub to make an epub"
|
|
||||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
|
||||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
|
||||||
@echo " text to make text files"
|
|
||||||
@echo " man to make manual pages"
|
|
||||||
@echo " texinfo to make Texinfo files"
|
|
||||||
@echo " info to make Texinfo files and run them through makeinfo"
|
|
||||||
@echo " gettext to make PO message catalogs"
|
|
||||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
|
||||||
@echo " linkcheck to check all external links for integrity"
|
|
||||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@echo 'Cleaning build directory'
|
|
||||||
@rm -rf $(BUILDDIR)/*
|
|
||||||
|
|
||||||
html:
|
|
||||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
|
||||||
|
|
||||||
dirhtml:
|
|
||||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
|
||||||
|
|
||||||
singlehtml:
|
|
||||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
|
||||||
|
|
||||||
pickle:
|
|
||||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the pickle files."
|
|
||||||
|
|
||||||
json:
|
|
||||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the JSON files."
|
|
||||||
|
|
||||||
htmlhelp:
|
|
||||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
|
||||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
|
||||||
|
|
||||||
qthelp:
|
|
||||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
|
||||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
|
||||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Lernfunk3.qhcp"
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Lernfunk3.qhc"
|
|
||||||
|
|
||||||
devhelp:
|
|
||||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished."
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/Lernfunk3"
|
|
||||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Lernfunk3"
|
|
||||||
@echo "# devhelp"
|
|
||||||
|
|
||||||
epub:
|
|
||||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
|
||||||
|
|
||||||
latex:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
|
||||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
|
||||||
"(use \`make latexpdf' here to do that automatically)."
|
|
||||||
|
|
||||||
latexpdf:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo "Running LaTeX files through pdflatex..."
|
|
||||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
|
||||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
|
||||||
|
|
||||||
text:
|
|
||||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
|
||||||
|
|
||||||
man:
|
|
||||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
|
||||||
|
|
||||||
texinfo:
|
|
||||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
|
||||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
|
||||||
"(use \`make info' here to do that automatically)."
|
|
||||||
|
|
||||||
info:
|
|
||||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
|
||||||
@echo "Running Texinfo files through makeinfo..."
|
|
||||||
make -C $(BUILDDIR)/texinfo info
|
|
||||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
|
||||||
|
|
||||||
gettext:
|
|
||||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
|
||||||
|
|
||||||
changes:
|
|
||||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
|
||||||
@echo
|
|
||||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
|
||||||
|
|
||||||
linkcheck:
|
|
||||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
|
||||||
@echo
|
|
||||||
@echo "Link check complete; look for any errors in the above output " \
|
|
||||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
|
||||||
|
|
||||||
doctest:
|
|
||||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
|
||||||
@echo "Testing of doctests in the sources finished, look at the " \
|
|
||||||
"results in $(BUILDDIR)/doctest/output.txt."
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<script type=application/javascript src=_static/theme_extras.js></script>
|
|
||||||
<div class="apititle"><b>Contents</b></div>
|
|
||||||
<div class="apitoc"></div>
|
|
||||||
|
|
||||||
.. automodule:: feedgen.entry
|
|
||||||
:members:
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<script type=application/javascript src=_static/theme_extras.js></script>
|
|
||||||
<div class="apititle"><b>Contents</b></div>
|
|
||||||
<div class="apitoc"></div>
|
|
||||||
|
|
||||||
.. automodule:: feedgen.feed
|
|
||||||
:members:
|
|
20
doc/api.rst
|
@ -1,20 +0,0 @@
|
||||||
=================
|
|
||||||
API Documentation
|
|
||||||
=================
|
|
||||||
|
|
||||||
.. automodule:: feedgen
|
|
||||||
:members:
|
|
||||||
|
|
||||||
Contents:
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
api.feed
|
|
||||||
api.entry
|
|
||||||
api.util
|
|
||||||
ext/api.ext.base
|
|
||||||
ext/api.ext.dc
|
|
||||||
ext/api.ext.podcast
|
|
||||||
ext/api.ext.podcast_entry
|
|
||||||
ext/api.ext.torrent
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<script type=application/javascript src=_static/theme_extras.js></script>
|
|
||||||
<div class="apititle"><b>Contents</b></div>
|
|
||||||
<div class="apitoc"></div>
|
|
||||||
|
|
||||||
.. automodule:: feedgen.util
|
|
||||||
:members:
|
|
269
doc/conf.py
|
@ -1,269 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# All configuration values have a default; values that are commented out
|
|
||||||
# serve to show the default.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import codecs
|
|
||||||
import re
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
||||||
sys.path.insert(0, os.path.abspath('../'))
|
|
||||||
sys.path.insert(0, os.path.abspath('.'))
|
|
||||||
|
|
||||||
import feedgen.version
|
|
||||||
|
|
||||||
# -- General configuration ----------------------------------------------------
|
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
|
||||||
#needs_sphinx = '1.0'
|
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
|
||||||
extensions = [
|
|
||||||
'sphinx.ext.intersphinx',
|
|
||||||
'sphinx.ext.coverage',
|
|
||||||
'sphinx.ext.autodoc'
|
|
||||||
]
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# The suffix of source filenames.
|
|
||||||
source_suffix = '.rst'
|
|
||||||
|
|
||||||
# The encoding of source files.
|
|
||||||
source_encoding = 'utf-8-sig'
|
|
||||||
|
|
||||||
# The master toctree document.
|
|
||||||
master_doc = 'index'
|
|
||||||
|
|
||||||
# General information about the project.
|
|
||||||
project = u'python-feedgen'
|
|
||||||
copyright = u'2013-2016, Lars Kiesow'
|
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
|
||||||
# |version| and |release|, also used in various other places throughout the
|
|
||||||
# built documents.
|
|
||||||
#
|
|
||||||
# The short X.Y version.
|
|
||||||
version = feedgen.version.version_minor_str
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
|
||||||
release = feedgen.version.version_full_str
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
||||||
# for a list of supported languages.
|
|
||||||
#language = None
|
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
|
||||||
# non-false value, then it is used:
|
|
||||||
#today = ''
|
|
||||||
# Else, today_fmt is used as the format for a strftime call.
|
|
||||||
#today_fmt = '%B %d, %Y'
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
exclude_patterns = ['_build']
|
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all
|
|
||||||
# documents.
|
|
||||||
#default_role = None
|
|
||||||
|
|
||||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
|
||||||
#add_function_parentheses = True
|
|
||||||
|
|
||||||
# If true, the current module name will be prepended to all description
|
|
||||||
# unit titles (such as .. function::).
|
|
||||||
#add_module_names = True
|
|
||||||
|
|
||||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
|
||||||
# output. They are ignored by default.
|
|
||||||
#show_authors = False
|
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
|
||||||
pygments_style = 'sphinx'
|
|
||||||
|
|
||||||
# A list of ignored prefixes for module index sorting.
|
|
||||||
#modindex_common_prefix = []
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output --------------------------------------------------
|
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
html_theme = 'default'
|
|
||||||
html_theme = 'haiku'
|
|
||||||
|
|
||||||
html_style = 'lernfunk.css'
|
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
|
||||||
# further. For a list of options available for each theme, see the
|
|
||||||
# documentation.
|
|
||||||
#html_theme_options = {}
|
|
||||||
|
|
||||||
# Add any paths that contain custom themes here, relative to this directory.
|
|
||||||
#html_theme_path = []
|
|
||||||
|
|
||||||
# The name for this set of Sphinx documents. If None, it defaults to
|
|
||||||
# "<project> v<release> documentation".
|
|
||||||
#html_title = None
|
|
||||||
|
|
||||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
|
||||||
#html_short_title = None
|
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top
|
|
||||||
# of the sidebar.
|
|
||||||
#html_logo = '_static/logo.png'
|
|
||||||
|
|
||||||
# The name of an image file (within the static path) to use as favicon of the
|
|
||||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
|
||||||
# pixels large.
|
|
||||||
#html_favicon = None
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
||||||
html_static_path = ['_static']
|
|
||||||
|
|
||||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
|
||||||
# using the given strftime format.
|
|
||||||
#html_last_updated_fmt = '%b %d, %Y'
|
|
||||||
|
|
||||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
|
||||||
# typographically correct entities.
|
|
||||||
#html_use_smartypants = True
|
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
|
||||||
#html_sidebars = {}
|
|
||||||
|
|
||||||
# Additional templates that should be rendered to pages, maps page names to
|
|
||||||
# template names.
|
|
||||||
#html_additional_pages = {}
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#html_domain_indices = True
|
|
||||||
|
|
||||||
# If false, no index is generated.
|
|
||||||
#html_use_index = True
|
|
||||||
|
|
||||||
# If true, the index is split into individual pages for each letter.
|
|
||||||
#html_split_index = False
|
|
||||||
|
|
||||||
# If true, links to the reST sources are added to the pages.
|
|
||||||
#html_show_sourcelink = True
|
|
||||||
|
|
||||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
|
||||||
#html_show_sphinx = True
|
|
||||||
|
|
||||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
|
||||||
#html_show_copyright = True
|
|
||||||
|
|
||||||
# If true, an OpenSearch description file will be output, and all pages will
|
|
||||||
# contain a <link> tag referring to it. The value of this option must be the
|
|
||||||
# base URL from which the finished HTML is served.
|
|
||||||
#html_use_opensearch = ''
|
|
||||||
|
|
||||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
|
||||||
#html_file_suffix = None
|
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
|
||||||
htmlhelp_basename = 'pyFeedGen'
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output -------------------------------------------------
|
|
||||||
|
|
||||||
latex_elements = {
|
|
||||||
# The paper size ('letterpaper' or 'a4paper').
|
|
||||||
#'papersize': 'letterpaper',
|
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
|
||||||
#'pointsize': '10pt',
|
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
|
||||||
#'preamble': '',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples (source start
|
|
||||||
# file, target name, title, author, documentclass [howto/manual]).
|
|
||||||
latex_documents = [
|
|
||||||
('index', 'pyFeedGen.tex', u'pyFeedGen Documentation', u'Lars Kiesow',
|
|
||||||
'manual'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
|
||||||
# the title page.
|
|
||||||
#latex_logo = None
|
|
||||||
|
|
||||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
|
||||||
# not chapters.
|
|
||||||
#latex_use_parts = False
|
|
||||||
|
|
||||||
# If true, show page references after internal links.
|
|
||||||
#latex_show_pagerefs = False
|
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
|
||||||
#latex_show_urls = False
|
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
|
||||||
#latex_appendices = []
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#latex_domain_indices = True
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output -------------------------------------------
|
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
|
||||||
# (source start file, name, description, authors, manual section).
|
|
||||||
man_pages = [
|
|
||||||
('index', 'pyFeedGen.tex', u'pyFeedGen Documentation',
|
|
||||||
[u'Lars Kiesow'], 1)
|
|
||||||
]
|
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
|
||||||
#man_show_urls = False
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output -----------------------------------------------
|
|
||||||
|
|
||||||
# Grouping the document tree into Texinfo files. List of tuples
|
|
||||||
# (source start file, target name, title, author,
|
|
||||||
# dir menu entry, description, category)
|
|
||||||
texinfo_documents = [
|
|
||||||
('index', 'pyFeedGen.tex', u'pyFeedGen Documentation',
|
|
||||||
u'Lars Kiesow', 'Lernfunk3', 'One line description of project.',
|
|
||||||
'Miscellaneous'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
|
||||||
#texinfo_appendices = []
|
|
||||||
|
|
||||||
# If false, no module index is generated.
|
|
||||||
#texinfo_domain_indices = True
|
|
||||||
|
|
||||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
|
||||||
#texinfo_show_urls = 'footnote'
|
|
||||||
|
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
|
||||||
intersphinx_mapping = {'http://docs.python.org/': None}
|
|
||||||
|
|
||||||
|
|
||||||
# Include the GitHub readme file in index.rst
|
|
||||||
r = re.compile(r'\[`*([^\]`]+)`*\]\(([^\)]+)\)')
|
|
||||||
r2 = re.compile(r'.. include-github-readme')
|
|
||||||
|
|
||||||
|
|
||||||
def substitute_link(app, docname, text):
|
|
||||||
if docname == 'index':
|
|
||||||
readme_text = ''
|
|
||||||
with codecs.open(os.path.abspath('../readme.rst'), 'r', 'utf-8') as f:
|
|
||||||
readme_text = r.sub(r'`\1 <\2>`_', f.read())
|
|
||||||
text[0] = r2.sub(readme_text, text[0])
|
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
|
||||||
app.connect('source-read', substitute_link)
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<script type=application/javascript src=_static/theme_extras.js></script>
|
|
||||||
<div class="apititle"><b>Contents</b></div>
|
|
||||||
<div class="apitoc"></div>
|
|
||||||
|
|
||||||
.. automodule:: feedgen.ext.base
|
|
||||||
:members:
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<script type=application/javascript src=_static/theme_extras.js></script>
|
|
||||||
<div class="apititle"><b>Contents</b></div>
|
|
||||||
<div class="apitoc"></div>
|
|
||||||
|
|
||||||
.. automodule:: feedgen.ext.dc
|
|
||||||
:members:
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<script type=application/javascript src=_static/theme_extras.js></script>
|
|
||||||
<div class="apititle"><b>Contents</b></div>
|
|
||||||
<div class="apitoc"></div>
|
|
||||||
|
|
||||||
.. automodule:: feedgen.ext.podcast
|
|
||||||
:members:
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<script type=application/javascript src=_static/theme_extras.js></script>
|
|
||||||
<div class="apititle"><b>Contents</b></div>
|
|
||||||
<div class="apitoc"></div>
|
|
||||||
|
|
||||||
.. automodule:: feedgen.ext.podcast_entry
|
|
||||||
:members:
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<script type=application/javascript src=_static/theme_extras.js></script>
|
|
||||||
<div class="apititle"><b>Contents</b></div>
|
|
||||||
<div class="apitoc"></div>
|
|
||||||
|
|
||||||
.. automodule:: feedgen.ext.torrent
|
|
||||||
:members:
|
|
|
@ -1,25 +0,0 @@
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
.. include-github-readme
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
====================
|
|
||||||
Module documentation
|
|
||||||
====================
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
api
|
|
||||||
|
|
||||||
==================
|
|
||||||
Indices and tables
|
|
||||||
==================
|
|
||||||
|
|
||||||
* :ref:`genindex`
|
|
||||||
* :ref:`modindex`
|
|
||||||
* :ref:`search`
|
|
||||||
|
|
128
ext/api.ext.base.html
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>feedgen.ext.base — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="../_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="../genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="../search.html" />
|
||||||
|
<link rel="next" title="feedgen.ext.dc" href="api.ext.dc.html" />
|
||||||
|
<link rel="prev" title="feedgen.util" href="../api.util.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="../index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>feedgen.ext.base</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="../api.util.html">feedgen.util</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.ext.dc.html">feedgen.ext.dc</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<script type=application/javascript src=_static/theme_extras.js></script>
|
||||||
|
<div class="apititle"><b>Contents</b></div>
|
||||||
|
<div class="apitoc"></div><span class="target" id="module-feedgen.ext.base"></span><div class="section" id="feedgen-ext-base">
|
||||||
|
<h1>feedgen.ext.base<a class="headerlink" href="#feedgen-ext-base" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>Basic FeedGenerator extension which does nothing but provides all necessary
|
||||||
|
methods.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">copyright:</th><td class="field-body">2013, Lars Kiesow <<a class="reference external" href="mailto:lkiesow%40uos.de">lkiesow<span>@</span>uos<span>.</span>de</a>></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">license:</th><td class="field-body">FreeBSD and LGPL, see license.* for more details.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.ext.base.BaseEntryExtension">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.ext.base.</code><code class="descname">BaseEntryExtension</code><a class="headerlink" href="#feedgen.ext.base.BaseEntryExtension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Basic FeedEntry extension.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.ext.base.BaseExtension">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.ext.base.</code><code class="descname">BaseExtension</code><a class="headerlink" href="#feedgen.ext.base.BaseExtension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Basic FeedGenerator extension.</p>
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.base.BaseExtension.extend_atom">
|
||||||
|
<code class="descname">extend_atom</code><span class="sig-paren">(</span><em>feed</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.base.BaseExtension.extend_atom" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Extend an ATOM feed xml structure containing all previously set
|
||||||
|
fields.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>feed</strong> – The feed xml root element.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The feed root element.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.base.BaseExtension.extend_ns">
|
||||||
|
<code class="descname">extend_ns</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.base.BaseExtension.extend_ns" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Returns a dict that will be used in the namespace map for the feed.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.base.BaseExtension.extend_rss">
|
||||||
|
<code class="descname">extend_rss</code><span class="sig-paren">(</span><em>feed</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.base.BaseExtension.extend_rss" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Extend a RSS feed xml structure containing all previously set fields.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>feed</strong> – The feed xml root element.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The feed root element.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="../api.util.html">feedgen.util</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.ext.dc.html">feedgen.ext.dc</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
535
ext/api.ext.dc.html
Normal file
|
@ -0,0 +1,535 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>feedgen.ext.dc — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="../_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="../genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="../search.html" />
|
||||||
|
<link rel="next" title="feedgen.ext.podcast" href="api.ext.podcast.html" />
|
||||||
|
<link rel="prev" title="feedgen.ext.base" href="api.ext.base.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="../index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>feedgen.ext.dc</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.ext.base.html">feedgen.ext.base</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.ext.podcast.html">feedgen.ext.podcast</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<script type=application/javascript src=_static/theme_extras.js></script>
|
||||||
|
<div class="apititle"><b>Contents</b></div>
|
||||||
|
<div class="apitoc"></div><span class="target" id="module-feedgen.ext.dc"></span><div class="section" id="feedgen-ext-dc">
|
||||||
|
<h1>feedgen.ext.dc<a class="headerlink" href="#feedgen-ext-dc" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>Extends the FeedGenerator to add Dubline Core Elements to the feeds.</p>
|
||||||
|
<p>Descriptions partly taken from
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-coverage">http://dublincore.org/documents/dcmi-terms/#elements-coverage</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">copyright:</th><td class="field-body">2013-2017, Lars Kiesow <<a class="reference external" href="mailto:lkiesow%40uos.de">lkiesow<span>@</span>uos<span>.</span>de</a>></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">license:</th><td class="field-body">FreeBSD and LGPL, see license.* for more details.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.ext.dc.</code><code class="descname">DcBaseExtension</code><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Dublin Core Elements extension for podcasts.</p>
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_contributor">
|
||||||
|
<code class="descname">dc_contributor</code><span class="sig-paren">(</span><em>contributor=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_contributor" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:contributor which is an entity responsible for
|
||||||
|
making contributions to the resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-contributor">http://dublincore.org/documents/dcmi-terms/#elements-contributor</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>contributor</strong> – Contributor or list of contributors.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set contributors (deault: False).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of contributors.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_coverage">
|
||||||
|
<code class="descname">dc_coverage</code><span class="sig-paren">(</span><em>coverage=None</em>, <em>replace=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_coverage" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:coverage which indicated the spatial or temporal
|
||||||
|
topic of the resource, the spatial applicability of the resource, or
|
||||||
|
the jurisdiction under which the resource is relevant.</p>
|
||||||
|
<p>Spatial topic and spatial applicability may be a named place or a
|
||||||
|
location specified by its geographic coordinates. Temporal topic may be
|
||||||
|
a named period, date, or date range. A jurisdiction may be a named
|
||||||
|
administrative entity or a geographic place to which the resource
|
||||||
|
applies. Recommended best practice is to use a controlled vocabulary
|
||||||
|
such as the Thesaurus of Geographic Names [TGN]. Where appropriate,
|
||||||
|
named places or time periods can be used in preference to numeric
|
||||||
|
identifiers such as sets of coordinates or date ranges.</p>
|
||||||
|
<p>References:
|
||||||
|
[TGN] <a class="reference external" href="http://www.getty.edu/research/tools/vocabulary/tgn/index.html">http://www.getty.edu/research/tools/vocabulary/tgn/index.html</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>coverage</strong> – Coverage of the feed.</li>
|
||||||
|
<li><strong>replace</strong> – Replace already set coverage (default: True).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Coverage of the feed.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_creator">
|
||||||
|
<code class="descname">dc_creator</code><span class="sig-paren">(</span><em>creator=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_creator" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:creator which is an entity primarily responsible
|
||||||
|
for making the resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-creator">http://dublincore.org/documents/dcmi-terms/#elements-creator</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>creator</strong> – Creator or list of creators.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set creators (deault: False).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of creators.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_date">
|
||||||
|
<code class="descname">dc_date</code><span class="sig-paren">(</span><em>date=None</em>, <em>replace=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_date" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:date which describes a point or period of time
|
||||||
|
associated with an event in the lifecycle of the resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-date">http://dublincore.org/documents/dcmi-terms/#elements-date</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>date</strong> – Date or list of dates.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set dates (deault: True).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of dates.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_description">
|
||||||
|
<code class="descname">dc_description</code><span class="sig-paren">(</span><em>description=None</em>, <em>replace=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_description" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:description which is an account of the resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-description">http://dublincore.org/documents/dcmi-terms/#elements-description</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>description</strong> – Description or list of descriptions.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set descriptions (deault: True).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of descriptions.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_format">
|
||||||
|
<code class="descname">dc_format</code><span class="sig-paren">(</span><em>format=None</em>, <em>replace=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_format" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:format which describes the file format, physical
|
||||||
|
medium, or dimensions of the resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-format">http://dublincore.org/documents/dcmi-terms/#elements-format</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>format</strong> – Format of the resource or list of formats.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set format (deault: True).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Format of the resource.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_identifier">
|
||||||
|
<code class="descname">dc_identifier</code><span class="sig-paren">(</span><em>identifier=None</em>, <em>replace=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_identifier" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:identifier which should be an unambiguous
|
||||||
|
reference to the resource within a given context.</p>
|
||||||
|
<p>For more inidentifierion see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-identifier">http://dublincore.org/documents/dcmi-terms/#elements-identifier</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>identifier</strong> – Identifier of the resource or list of identifiers.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set identifier (deault: True).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Identifiers of the resource.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_language">
|
||||||
|
<code class="descname">dc_language</code><span class="sig-paren">(</span><em>language=None</em>, <em>replace=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_language" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:language which describes a language of the
|
||||||
|
resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-language">http://dublincore.org/documents/dcmi-terms/#elements-language</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>language</strong> – Language or list of languages.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set languages (deault: True).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of languages.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_publisher">
|
||||||
|
<code class="descname">dc_publisher</code><span class="sig-paren">(</span><em>publisher=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_publisher" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:publisher which is an entity responsible for
|
||||||
|
making the resource available.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-publisher">http://dublincore.org/documents/dcmi-terms/#elements-publisher</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>publisher</strong> – Publisher or list of publishers.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set publishers (deault: False).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of publishers.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_relation">
|
||||||
|
<code class="descname">dc_relation</code><span class="sig-paren">(</span><em>relation=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_relation" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:relation which describes a related resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-relation">http://dublincore.org/documents/dcmi-terms/#elements-relation</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>relation</strong> – Relation or list of relations.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set relations (deault: False).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of relations.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_rights">
|
||||||
|
<code class="descname">dc_rights</code><span class="sig-paren">(</span><em>rights=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_rights" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:rights which may contain information about rights
|
||||||
|
held in and over the resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-rights">http://dublincore.org/documents/dcmi-terms/#elements-rights</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>rights</strong> – Rights information or list of rights information.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set rightss (deault: False).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of rights information.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_source">
|
||||||
|
<code class="descname">dc_source</code><span class="sig-paren">(</span><em>source=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_source" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:source which is a related resource from which the
|
||||||
|
described resource is derived.</p>
|
||||||
|
<p>The described resource may be derived from the related resource in
|
||||||
|
whole or in part. Recommended best practice is to identify the related
|
||||||
|
resource by means of a string conforming to a formal identification
|
||||||
|
system.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-source">http://dublincore.org/documents/dcmi-terms/#elements-source</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>source</strong> – Source or list of sources.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set sources (deault: False).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of sources.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_subject">
|
||||||
|
<code class="descname">dc_subject</code><span class="sig-paren">(</span><em>subject=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_subject" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:subject which describes the topic of the resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-subject">http://dublincore.org/documents/dcmi-terms/#elements-subject</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>subject</strong> – Subject or list of subjects.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set subjects (deault: False).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of subjects.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_title">
|
||||||
|
<code class="descname">dc_title</code><span class="sig-paren">(</span><em>title=None</em>, <em>replace=True</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_title" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:title which is a name given to the resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-title">http://dublincore.org/documents/dcmi-terms/#elements-title</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>title</strong> – Title or list of titles.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set titles (deault: False).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of titles.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.dc_type">
|
||||||
|
<code class="descname">dc_type</code><span class="sig-paren">(</span><em>type=None</em>, <em>replace=False</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.dc_type" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the dc:type which describes the nature or genre of the
|
||||||
|
resource.</p>
|
||||||
|
<p>For more information see:
|
||||||
|
<a class="reference external" href="http://dublincore.org/documents/dcmi-terms/#elements-type">http://dublincore.org/documents/dcmi-terms/#elements-type</a></p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>type</strong> – Type or list of types.</li>
|
||||||
|
<li><strong>replace</strong> – Replace alredy set types (deault: False).</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of types.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.extend_atom">
|
||||||
|
<code class="descname">extend_atom</code><span class="sig-paren">(</span><em>atom_feed</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.extend_atom" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Extend an Atom feed with the set DC fields.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>atom_feed</strong> – The feed root element</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The feed root element</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.extend_ns">
|
||||||
|
<code class="descname">extend_ns</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.extend_ns" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Returns a dict that will be used in the namespace map for the feed.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcBaseExtension.extend_rss">
|
||||||
|
<code class="descname">extend_rss</code><span class="sig-paren">(</span><em>rss_feed</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcBaseExtension.extend_rss" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Extend a RSS feed with the set DC fields.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>rss_feed</strong> – The feed root element</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The feed root element.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.ext.dc.DcEntryExtension">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.ext.dc.</code><code class="descname">DcEntryExtension</code><a class="headerlink" href="#feedgen.ext.dc.DcEntryExtension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Dublin Core Elements extension for podcasts.</p>
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcEntryExtension.extend_atom">
|
||||||
|
<code class="descname">extend_atom</code><span class="sig-paren">(</span><em>entry</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcEntryExtension.extend_atom" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Add dc elements to an atom item. Alters the item itself.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>entry</strong> – An atom entry element.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The entry element.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.dc.DcEntryExtension.extend_rss">
|
||||||
|
<code class="descname">extend_rss</code><span class="sig-paren">(</span><em>item</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.dc.DcEntryExtension.extend_rss" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Add dc elements to a RSS item. Alters the item itself.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>item</strong> – A RSS item element.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The item element.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.ext.dc.DcExtension">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.ext.dc.</code><code class="descname">DcExtension</code><a class="headerlink" href="#feedgen.ext.dc.DcExtension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Dublin Core Elements extension for podcasts.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.ext.base.html">feedgen.ext.base</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.ext.podcast.html">feedgen.ext.podcast</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
347
ext/api.ext.podcast.html
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>feedgen.ext.podcast — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="../_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="../genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="../search.html" />
|
||||||
|
<link rel="next" title="feedgen.ext.podcast_entry" href="api.ext.podcast_entry.html" />
|
||||||
|
<link rel="prev" title="feedgen.ext.dc" href="api.ext.dc.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="../index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>feedgen.ext.podcast</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.ext.dc.html">feedgen.ext.dc</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.ext.podcast_entry.html">feedgen.ext.podcast_entry</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<script type=application/javascript src=_static/theme_extras.js></script>
|
||||||
|
<div class="apititle"><b>Contents</b></div>
|
||||||
|
<div class="apitoc"></div><span class="target" id="module-feedgen.ext.podcast"></span><div class="section" id="feedgen-ext-podcast">
|
||||||
|
<h1>feedgen.ext.podcast<a class="headerlink" href="#feedgen-ext-podcast" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>Extends the FeedGenerator to produce podcasts.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">copyright:</th><td class="field-body">2013, Lars Kiesow <<a class="reference external" href="mailto:lkiesow%40uos.de">lkiesow<span>@</span>uos<span>.</span>de</a>></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">license:</th><td class="field-body">FreeBSD and LGPL, see license.* for more details.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.ext.podcast.</code><code class="descname">PodcastExtension</code><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>FeedGenerator extension for podcasts.</p>
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.extend_ns">
|
||||||
|
<code class="descname">extend_ns</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.extend_ns" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Returns a dict that will be used in the namespace map for the feed.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.extend_rss">
|
||||||
|
<code class="descname">extend_rss</code><span class="sig-paren">(</span><em>rss_feed</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.extend_rss" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Extend an RSS feed root with set itunes fields.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Returns:</th><td class="field-body">The feed root element.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_author">
|
||||||
|
<code class="descname">itunes_author</code><span class="sig-paren">(</span><em>itunes_author=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_author" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the itunes:author. The content of this tag is shown in
|
||||||
|
the Artist column in iTunes. If the tag is not present, iTunes uses the
|
||||||
|
contents of the <author> tag. If <itunes:author> is not present at the
|
||||||
|
feed level, iTunes will use the contents of <managingEditor>.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_author</strong> – The author of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The author of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_block">
|
||||||
|
<code class="descname">itunes_block</code><span class="sig-paren">(</span><em>itunes_block=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_block" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the ITunes block attribute. Use this to prevent the
|
||||||
|
entire podcast from appearing in the iTunes podcast directory.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_block</strong> – Block the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">If the podcast is blocked.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_category">
|
||||||
|
<code class="descname">itunes_category</code><span class="sig-paren">(</span><em>itunes_category=None</em>, <em>replace=False</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_category" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the ITunes category which appears in the category column
|
||||||
|
and in iTunes Store Browser.</p>
|
||||||
|
<p>The (sub-)category has to be one from the values defined at
|
||||||
|
<a class="reference external" href="http://www.apple.com/itunes/podcasts/specs.html#categories">http://www.apple.com/itunes/podcasts/specs.html#categories</a></p>
|
||||||
|
<p>This method can be called with:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>the fields of an itunes_category as keyword arguments</li>
|
||||||
|
<li>the fields of an itunes_category as a dictionary</li>
|
||||||
|
<li>a list of dictionaries containing the itunes_category fields</li>
|
||||||
|
</ul>
|
||||||
|
<p>An itunes_category has the following fields:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><em>cat</em> name for a category.</li>
|
||||||
|
<li><em>sub</em> name for a subcategory, child of category</li>
|
||||||
|
</ul>
|
||||||
|
<p>If a podcast has more than one subcategory from the same category, the
|
||||||
|
category is called more than once.</p>
|
||||||
|
<p>Likei the parameter:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[{</span><span class="s2">"cat"</span><span class="p">:</span><span class="s2">"Arts"</span><span class="p">,</span><span class="s2">"sub"</span><span class="p">:</span><span class="s2">"Design"</span><span class="p">},{</span><span class="s2">"cat"</span><span class="p">:</span><span class="s2">"Arts"</span><span class="p">,</span><span class="s2">"sub"</span><span class="p">:</span><span class="s2">"Food"</span><span class="p">}]</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>…would become:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="n">itunes</span><span class="p">:</span><span class="n">category</span> <span class="n">text</span><span class="o">=</span><span class="s2">"Arts"</span><span class="o">></span>
|
||||||
|
<span class="o"><</span><span class="n">itunes</span><span class="p">:</span><span class="n">category</span> <span class="n">text</span><span class="o">=</span><span class="s2">"Design"</span><span class="o">/></span>
|
||||||
|
<span class="o"><</span><span class="n">itunes</span><span class="p">:</span><span class="n">category</span> <span class="n">text</span><span class="o">=</span><span class="s2">"Food"</span><span class="o">/></span>
|
||||||
|
<span class="o"></</span><span class="n">itunes</span><span class="p">:</span><span class="n">category</span><span class="o">></span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||||
|
<li><strong>itunes_category</strong> – Dictionary or list of dictionaries with
|
||||||
|
itunes_category data.</li>
|
||||||
|
<li><strong>replace</strong> – Add or replace old data.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">List of itunes_categories as dictionaries.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>—</p>
|
||||||
|
<p><strong>Important note about deprecated parameter syntax:</strong> Old version of
|
||||||
|
the feedgen did only support one category plus one subcategory which
|
||||||
|
would be passed to this ducntion as first two parameters. For
|
||||||
|
compatibility reasons, this still works but should not be used any may
|
||||||
|
be removed at any time.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_complete">
|
||||||
|
<code class="descname">itunes_complete</code><span class="sig-paren">(</span><em>itunes_complete=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_complete" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the itunes:complete value of the podcast. This tag can be
|
||||||
|
used to indicate the completion of a podcast.</p>
|
||||||
|
<p>If you populate this tag with “yes”, you are indicating that no more
|
||||||
|
episodes will be added to the podcast. If the <itunes:complete> tag is
|
||||||
|
present and has any other value (e.g. “no”), it will have no effect on
|
||||||
|
the podcast.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_complete</strong> – If the podcast is complete.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">If the podcast is complete.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_explicit">
|
||||||
|
<code class="descname">itunes_explicit</code><span class="sig-paren">(</span><em>itunes_explicit=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_explicit" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or the the itunes:explicit value of the podcast. This tag should
|
||||||
|
be used to indicate whether your podcast contains explicit material.
|
||||||
|
The three values for this tag are “yes”, “no”, and “clean”.</p>
|
||||||
|
<p>If you populate this tag with “yes”, an “explicit” parental advisory
|
||||||
|
graphic will appear next to your podcast artwork on the iTunes Store
|
||||||
|
and in the Name column in iTunes. If the value is “clean”, the parental
|
||||||
|
advisory type is considered Clean, meaning that no explicit language or
|
||||||
|
adult content is included anywhere in the episodes, and a “clean”
|
||||||
|
graphic will appear. If the explicit tag is present and has any other
|
||||||
|
value (e.g., “no”), you see no indicator — blank is the default
|
||||||
|
advisory type.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_explicit</strong> – If the podcast contains explicit material.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">If the podcast contains explicit material.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_image">
|
||||||
|
<code class="descname">itunes_image</code><span class="sig-paren">(</span><em>itunes_image=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_image" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the image for the podcast. This tag specifies the artwork
|
||||||
|
for your podcast. Put the URL to the image in the href attribute.
|
||||||
|
iTunes prefers square .jpg images that are at least 1400x1400 pixels,
|
||||||
|
which is different from what is specified for the standard RSS image
|
||||||
|
tag. In order for a podcast to be eligible for an iTunes Store feature,
|
||||||
|
the accompanying image must be at least 1400x1400 pixels.</p>
|
||||||
|
<p>iTunes supports images in JPEG and PNG formats with an RGB color space
|
||||||
|
(CMYK is not supported). The URL must end in “.jpg” or “.png”. If the
|
||||||
|
<itunes:image> tag is not present, iTunes will use the contents of the
|
||||||
|
RSS image tag.</p>
|
||||||
|
<p>If you change your podcast’s image, also change the file’s name. iTunes
|
||||||
|
may not change the image if it checks your feed and the image URL is
|
||||||
|
the same. The server hosting your cover art image must allow HTTP head
|
||||||
|
requests for iTS to be able to automatically update your cover art.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_image</strong> – Image of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Image of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_new_feed_url">
|
||||||
|
<code class="descname">itunes_new_feed_url</code><span class="sig-paren">(</span><em>itunes_new_feed_url=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_new_feed_url" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the new-feed-url property of the podcast. This tag allows
|
||||||
|
you to change the URL where the podcast feed is located</p>
|
||||||
|
<p>After adding the tag to your old feed, you should maintain the old feed
|
||||||
|
for 48 hours before retiring it. At that point, iTunes will have
|
||||||
|
updated the directory with the new feed URL.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_new_feed_url</strong> – New feed URL.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">New feed URL.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_owner">
|
||||||
|
<code class="descname">itunes_owner</code><span class="sig-paren">(</span><em>name=None</em>, <em>email=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_owner" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the itunes:owner of the podcast. This tag contains
|
||||||
|
information that will be used to contact the owner of the podcast for
|
||||||
|
communication specifically about the podcast. It will not be publicly
|
||||||
|
displayed.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_owner</strong> – The owner of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Data of the owner of the feed.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_subtitle">
|
||||||
|
<code class="descname">itunes_subtitle</code><span class="sig-paren">(</span><em>itunes_subtitle=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_subtitle" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the itunes:subtitle value for the podcast. The contents of
|
||||||
|
this tag are shown in the Description column in iTunes. The subtitle
|
||||||
|
displays best if it is only a few words long.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_subtitle</strong> – Subtitle of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Subtitle of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast.PodcastExtension.itunes_summary">
|
||||||
|
<code class="descname">itunes_summary</code><span class="sig-paren">(</span><em>itunes_summary=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast.PodcastExtension.itunes_summary" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the itunes:summary value for the podcast. The contents of
|
||||||
|
this tag are shown in a separate window that appears when the “circled
|
||||||
|
i” in the Description column is clicked. It also appears on the iTunes
|
||||||
|
page for your podcast. This field can be up to 4000 characters. If
|
||||||
|
<cite><itunes:summary></cite> is not included, the contents of the <description>
|
||||||
|
tag are used.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_summary</strong> – Summary of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Summary of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.ext.dc.html">feedgen.ext.dc</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.ext.podcast_entry.html">feedgen.ext.podcast_entry</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
298
ext/api.ext.podcast_entry.html
Normal file
|
@ -0,0 +1,298 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>feedgen.ext.podcast_entry — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="../_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="../genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="../search.html" />
|
||||||
|
<link rel="next" title="feedgen.ext.torrent" href="api.ext.torrent.html" />
|
||||||
|
<link rel="prev" title="feedgen.ext.podcast" href="api.ext.podcast.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="../index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>feedgen.ext.podcast_entry</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.ext.podcast.html">feedgen.ext.podcast</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.ext.torrent.html">feedgen.ext.torrent</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<script type=application/javascript src=_static/theme_extras.js></script>
|
||||||
|
<div class="apititle"><b>Contents</b></div>
|
||||||
|
<div class="apitoc"></div><span class="target" id="module-feedgen.ext.podcast_entry"></span><div class="section" id="feedgen-ext-podcast-entry">
|
||||||
|
<h1>feedgen.ext.podcast_entry<a class="headerlink" href="#feedgen-ext-podcast-entry" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>Extends the feedgen to produce podcasts.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">copyright:</th><td class="field-body">2013-2016, Lars Kiesow <<a class="reference external" href="mailto:lkiesow%40uos.de">lkiesow<span>@</span>uos<span>.</span>de</a>></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">license:</th><td class="field-body">FreeBSD and LGPL, see license.* for more details.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.ext.podcast_entry.</code><code class="descname">PodcastEntryExtension</code><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>FeedEntry extension for podcasts.</p>
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.extend_rss">
|
||||||
|
<code class="descname">extend_rss</code><span class="sig-paren">(</span><em>entry</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.extend_rss" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Add additional fields to an RSS item.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>feed</strong> – The RSS item XML element to use.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_author">
|
||||||
|
<code class="descname">itunes_author</code><span class="sig-paren">(</span><em>itunes_author=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_author" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the itunes:author of the podcast episode. The content of
|
||||||
|
this tag is shown in the Artist column in iTunes. If the tag is not
|
||||||
|
present, iTunes uses the contents of the <author> tag. If
|
||||||
|
<itunes:author> is not present at the feed level, iTunes will use the
|
||||||
|
contents of <managingEditor>.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_author</strong> – The author of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The author of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_block">
|
||||||
|
<code class="descname">itunes_block</code><span class="sig-paren">(</span><em>itunes_block=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_block" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the ITunes block attribute. Use this to prevent episodes
|
||||||
|
from appearing in the iTunes podcast directory.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_block</strong> – Block podcast episodes.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">If the podcast episode is blocked.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_duration">
|
||||||
|
<code class="descname">itunes_duration</code><span class="sig-paren">(</span><em>itunes_duration=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_duration" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the duration of the podcast episode. The content of this
|
||||||
|
tag is shown in the Time column in iTunes.</p>
|
||||||
|
<p>The tag can be formatted HH:MM:SS, H:MM:SS, MM:SS, or M:SS (H = hours,
|
||||||
|
M = minutes, S = seconds). If an integer is provided (no colon
|
||||||
|
present), the value is assumed to be in seconds. If one colon is
|
||||||
|
present, the number to the left is assumed to be minutes, and the
|
||||||
|
number to the right is assumed to be seconds. If more than two colons
|
||||||
|
are present, the numbers farthest to the right are ignored.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_duration</strong> – Duration of the podcast episode.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Duration of the podcast episode.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_explicit">
|
||||||
|
<code class="descname">itunes_explicit</code><span class="sig-paren">(</span><em>itunes_explicit=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_explicit" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or the the itunes:explicit value of the podcast episode. This
|
||||||
|
tag should be used to indicate whether your podcast episode contains
|
||||||
|
explicit material. The three values for this tag are “yes”, “no”, and
|
||||||
|
“clean”.</p>
|
||||||
|
<p>If you populate this tag with “yes”, an “explicit” parental advisory
|
||||||
|
graphic will appear next to your podcast artwork on the iTunes Store
|
||||||
|
and in the Name column in iTunes. If the value is “clean”, the parental
|
||||||
|
advisory type is considered Clean, meaning that no explicit language or
|
||||||
|
adult content is included anywhere in the episodes, and a “clean”
|
||||||
|
graphic will appear. If the explicit tag is present and has any other
|
||||||
|
value (e.g., “no”), you see no indicator — blank is the default
|
||||||
|
advisory type.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_explicit</strong> – If the podcast episode contains explicit
|
||||||
|
material.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">If the podcast episode contains explicit material.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_image">
|
||||||
|
<code class="descname">itunes_image</code><span class="sig-paren">(</span><em>itunes_image=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_image" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the image for the podcast episode. This tag specifies the
|
||||||
|
artwork for your podcast. Put the URL to the image in the href
|
||||||
|
attribute. iTunes prefers square .jpg images that are at least
|
||||||
|
1400x1400 pixels, which is different from what is specified for the
|
||||||
|
standard RSS image tag. In order for a podcast to be eligible for an
|
||||||
|
iTunes Store feature, the accompanying image must be at least 1400x1400
|
||||||
|
pixels.</p>
|
||||||
|
<p>iTunes supports images in JPEG and PNG formats with an RGB color space
|
||||||
|
(CMYK is not supported). The URL must end in “.jpg” or “.png”. If the
|
||||||
|
<itunes:image> tag is not present, iTunes will use the contents of the
|
||||||
|
RSS image tag.</p>
|
||||||
|
<p>If you change your podcast’s image, also change the file’s name. iTunes
|
||||||
|
may not change the image if it checks your feed and the image URL is
|
||||||
|
the same. The server hosting your cover art image must allow HTTP head
|
||||||
|
requests for iTS to be able to automatically update your cover art.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_image</strong> – Image of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Image of the podcast.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_is_closed_captioned">
|
||||||
|
<code class="descname">itunes_is_closed_captioned</code><span class="sig-paren">(</span><em>itunes_is_closed_captioned=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_is_closed_captioned" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the is_closed_captioned value of the podcast episode.
|
||||||
|
This tag should be used if your podcast includes a video episode with
|
||||||
|
embedded closed captioning support. The two values for this tag are
|
||||||
|
“yes” and “no”.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>is_closed_captioned</strong> – If the episode has closed captioning
|
||||||
|
support.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">If the episode has closed captioning support.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_order">
|
||||||
|
<code class="descname">itunes_order</code><span class="sig-paren">(</span><em>itunes_order=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_order" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the itunes:order value of the podcast episode. This tag
|
||||||
|
can be used to override the default ordering of episodes on the store.</p>
|
||||||
|
<p>This tag is used at an <item> level by populating with the number value
|
||||||
|
in which you would like the episode to appear on the store. For
|
||||||
|
example, if you would like an <item> to appear as the first episode in
|
||||||
|
the podcast, you would populate the <itunes:order> tag with “1”. If
|
||||||
|
conflicting order values are present in multiple episodes, the store
|
||||||
|
will use default ordering (pubDate).</p>
|
||||||
|
<p>To remove the order from the episode set the order to a value below
|
||||||
|
zero.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_order</strong> – The order of the episode.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The order of the episode.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_subtitle">
|
||||||
|
<code class="descname">itunes_subtitle</code><span class="sig-paren">(</span><em>itunes_subtitle=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_subtitle" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the itunes:subtitle value for the podcast episode. The
|
||||||
|
contents of this tag are shown in the Description column in iTunes. The
|
||||||
|
subtitle displays best if it is only a few words long.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_subtitle</strong> – Subtitle of the podcast episode.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Subtitle of the podcast episode.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_summary">
|
||||||
|
<code class="descname">itunes_summary</code><span class="sig-paren">(</span><em>itunes_summary=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_summary" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the itunes:summary value for the podcast episode. The
|
||||||
|
contents of this tag are shown in a separate window that appears when
|
||||||
|
the “circled i” in the Description column is clicked. It also appears
|
||||||
|
on the iTunes page for your podcast. This field can be up to 4000
|
||||||
|
characters. If <itunes:summary> is not included, the contents of the
|
||||||
|
<description> tag are used.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>itunes_summary</strong> – Summary of the podcast episode.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">Summary of the podcast episode.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.ext.podcast.html">feedgen.ext.podcast</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.ext.torrent.html">feedgen.ext.torrent</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
199
ext/api.ext.torrent.html
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>feedgen.ext.torrent — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="../_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="../_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="../genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="../search.html" />
|
||||||
|
<link rel="prev" title="feedgen.ext.podcast_entry" href="api.ext.podcast_entry.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="../index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>feedgen.ext.torrent</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.ext.podcast_entry.html">feedgen.ext.podcast_entry</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<script type=application/javascript src=_static/theme_extras.js></script>
|
||||||
|
<div class="apititle"><b>Contents</b></div>
|
||||||
|
<div class="apitoc"></div><span class="target" id="module-feedgen.ext.torrent"></span><div class="section" id="feedgen-ext-torrent">
|
||||||
|
<h1>feedgen.ext.torrent<a class="headerlink" href="#feedgen-ext-torrent" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>Extends the FeedGenerator to produce torrent feeds.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">copyright:</th><td class="field-body">2016, Raspbeguy <<a class="reference external" href="mailto:raspbeguy%40hashtagueule.fr">raspbeguy<span>@</span>hashtagueule<span>.</span>fr</a>></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">license:</th><td class="field-body">FreeBSD and LGPL, see license.* for more details.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentEntryExtension">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.ext.torrent.</code><code class="descname">TorrentEntryExtension</code><a class="headerlink" href="#feedgen.ext.torrent.TorrentEntryExtension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>FeedEntry extension for torrent feeds</p>
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentEntryExtension.contentlength">
|
||||||
|
<code class="descname">contentlength</code><span class="sig-paren">(</span><em>torrent_contentlength=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.torrent.TorrentEntryExtension.contentlength" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the size of the target file.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>torrent_contentlength</strong> – The target file size.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The target file size.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentEntryExtension.extend_rss">
|
||||||
|
<code class="descname">extend_rss</code><span class="sig-paren">(</span><em>entry</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.torrent.TorrentEntryExtension.extend_rss" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Add additional fields to an RSS item.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>feed</strong> – The RSS item XML element to use.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentEntryExtension.filename">
|
||||||
|
<code class="descname">filename</code><span class="sig-paren">(</span><em>torrent_filename=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.torrent.TorrentEntryExtension.filename" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the name of the torrent file.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>torrent_filename</strong> – The name of the torrent file.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The name of the torrent file.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentEntryExtension.infohash">
|
||||||
|
<code class="descname">infohash</code><span class="sig-paren">(</span><em>torrent_infohash=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.torrent.TorrentEntryExtension.infohash" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the hash of the target file.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>torrent_infohash</strong> – The target file hash.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The target hash file.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentEntryExtension.peers">
|
||||||
|
<code class="descname">peers</code><span class="sig-paren">(</span><em>torrent_peers=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.torrent.TorrentEntryExtension.peers" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the number od peers</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>torrent_infohash</strong> – The peers number.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The peers number.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentEntryExtension.seeds">
|
||||||
|
<code class="descname">seeds</code><span class="sig-paren">(</span><em>torrent_seeds=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.torrent.TorrentEntryExtension.seeds" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the number of seeds.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>torrent_seeds</strong> – The seeds number.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The seeds number.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentEntryExtension.verified">
|
||||||
|
<code class="descname">verified</code><span class="sig-paren">(</span><em>torrent_verified=None</em><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.torrent.TorrentEntryExtension.verified" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Get or set the number of verified peers.</p>
|
||||||
|
<table class="docutils field-list" frame="void" rules="none">
|
||||||
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>torrent_infohash</strong> – The verified peers number.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">The verified peers number.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="class">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentExtension">
|
||||||
|
<em class="property">class </em><code class="descclassname">feedgen.ext.torrent.</code><code class="descname">TorrentExtension</code><a class="headerlink" href="#feedgen.ext.torrent.TorrentExtension" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>FeedGenerator extension for torrent feeds.</p>
|
||||||
|
<dl class="method">
|
||||||
|
<dt id="feedgen.ext.torrent.TorrentExtension.extend_ns">
|
||||||
|
<code class="descname">extend_ns</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#feedgen.ext.torrent.TorrentExtension.extend_ns" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Returns a dict that will be used in the namespace map for the feed.</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
«  <a href="api.ext.podcast_entry.html">feedgen.ext.podcast_entry</a>
|
||||||
|
  ::  
|
||||||
|
<a class="uplink" href="../index.html">Contents</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,137 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
=======
|
|
||||||
feedgen
|
|
||||||
=======
|
|
||||||
|
|
||||||
This module can be used to generate web feeds in both ATOM and RSS format.
|
|
||||||
It has support for extensions. Included is for example an extension to
|
|
||||||
produce Podcasts.
|
|
||||||
|
|
||||||
:copyright: 2013 by Lars Kiesow
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
|
|
||||||
|
|
||||||
-------------
|
|
||||||
Create a Feed
|
|
||||||
-------------
|
|
||||||
|
|
||||||
To create a feed simply instantiate the FeedGenerator class and insert some
|
|
||||||
data::
|
|
||||||
|
|
||||||
>>> from feedgen.feed import FeedGenerator
|
|
||||||
>>> fg = FeedGenerator()
|
|
||||||
>>> fg.id('http://lernfunk.de/media/654321')
|
|
||||||
>>> fg.title('Some Testfeed')
|
|
||||||
>>> fg.author( {'name':'John Doe','email':'john@example.de'} )
|
|
||||||
>>> fg.link( href='http://example.com', rel='alternate' )
|
|
||||||
>>> fg.logo('http://ex.com/logo.jpg')
|
|
||||||
>>> fg.subtitle('This is a cool feed!')
|
|
||||||
>>> fg.link( href='http://larskiesow.de/test.atom', rel='self' )
|
|
||||||
>>> fg.language('en')
|
|
||||||
|
|
||||||
Note that for the methods which set fields that can occur more than once in
|
|
||||||
a feed you can use all of the following ways to provide data:
|
|
||||||
|
|
||||||
- Provide the data for that element as keyword arguments
|
|
||||||
- Provide the data for that element as dictionary
|
|
||||||
- Provide a list of dictionaries with the data for several elements
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
>>> fg.contributor(name='John Doe', email='jdoe@example.com' )
|
|
||||||
>>> fg.contributor({'name':'John Doe', 'email':'jdoe@example.com'})
|
|
||||||
>>> fg.contributor([{'name':'John', 'email':'jdoe@example.com'}, …])
|
|
||||||
|
|
||||||
-----------------
|
|
||||||
Generate the Feed
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
After that you can generate both RSS or ATOM by calling the respective
|
|
||||||
method::
|
|
||||||
|
|
||||||
>>> atomfeed = fg.atom_str(pretty=True) # Get the ATOM feed as string
|
|
||||||
>>> rssfeed = fg.rss_str(pretty=True) # Get the RSS feed as string
|
|
||||||
>>> fg.atom_file('atom.xml') # Write the ATOM feed to a file
|
|
||||||
>>> fg.rss_file('rss.xml') # Write the RSS feed to a file
|
|
||||||
|
|
||||||
|
|
||||||
----------------
|
|
||||||
Add Feed Entries
|
|
||||||
----------------
|
|
||||||
|
|
||||||
To add entries (items) to a feed you need to create new FeedEntry objects
|
|
||||||
and append them to the list of entries in the FeedGenerator. The most
|
|
||||||
convenient way to go is to use the FeedGenerator itself for the
|
|
||||||
instantiation of the FeedEntry object::
|
|
||||||
|
|
||||||
>>> fe = fg.add_entry()
|
|
||||||
>>> fe.id('http://lernfunk.de/media/654321/1')
|
|
||||||
>>> fe.title('The First Episode')
|
|
||||||
|
|
||||||
The FeedGenerators method add_entry(...) without argument provides will
|
|
||||||
automatically generate a new FeedEntry object, append it to the feeds
|
|
||||||
internal list of entries and return it, so that additional data can be
|
|
||||||
added.
|
|
||||||
|
|
||||||
----------
|
|
||||||
Extensions
|
|
||||||
----------
|
|
||||||
|
|
||||||
The FeedGenerator supports extension to include additional data into the
|
|
||||||
XML structure of the feeds. Extensions can be loaded like this::
|
|
||||||
|
|
||||||
>>> fg.load_extension('someext', atom=True, rss=True)
|
|
||||||
|
|
||||||
This will try to load the extension “someext” from the file
|
|
||||||
`ext/someext.py`. It is required that `someext.py` contains a class named
|
|
||||||
“SomextExtension” which is required to have at least the two methods
|
|
||||||
`extend_rss(...)` and `extend_atom(...)`. Although not required, it is
|
|
||||||
strongly suggested to use BaseExtension from `ext/base.py` as superclass.
|
|
||||||
|
|
||||||
`load_extension('someext', ...)` will also try to load a class named
|
|
||||||
“SomextEntryExtension” for every entry of the feed. This class can be
|
|
||||||
located either in the same file as SomextExtension or in
|
|
||||||
`ext/someext_entry.py` which is suggested especially for large extensions.
|
|
||||||
|
|
||||||
The parameters `atom` and `rss` tell the FeedGenerator if the extensions
|
|
||||||
should only be used for either ATOM or RSS feeds. The default value for
|
|
||||||
both parameters is true which means that the extension would be used for
|
|
||||||
both kinds of feeds.
|
|
||||||
|
|
||||||
**Example: Producing a Podcast**
|
|
||||||
|
|
||||||
One extension already provided is the podcast extension. A podcast is an
|
|
||||||
RSS feed with some additional elements for ITunes.
|
|
||||||
|
|
||||||
To produce a podcast simply load the `podcast` extension::
|
|
||||||
|
|
||||||
>>> from feedgen.feed import FeedGenerator
|
|
||||||
>>> fg = FeedGenerator()
|
|
||||||
>>> fg.load_extension('podcast')
|
|
||||||
...
|
|
||||||
>>> fg.podcast.itunes_category('Technology', 'Podcasting')
|
|
||||||
...
|
|
||||||
>>> fg.rss_str(pretty=True)
|
|
||||||
>>> fg.rss_file('podcast.xml')
|
|
||||||
|
|
||||||
Of cause the extension has to be loaded for the FeedEntry objects as well
|
|
||||||
but this is done automatically by the FeedGenerator for every feed entry if
|
|
||||||
the extension is loaded for the whole feed. You can, however, load an
|
|
||||||
extension for a specific FeedEntry by calling `load_extension(...)` on that
|
|
||||||
entry. But this is a rather uncommon use.
|
|
||||||
|
|
||||||
Of cause you can still produce a normal ATOM or RSS feed, even if you have
|
|
||||||
loaded some plugins by temporary disabling them during the feed generation.
|
|
||||||
This can be done by calling the generating method with the keyword argument
|
|
||||||
`extensions` set to `False`.
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
Testing the Generator
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
You can test the module by simply executing::
|
|
||||||
|
|
||||||
$ python -m feedgen
|
|
||||||
|
|
||||||
"""
|
|
|
@ -1,145 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen
|
|
||||||
~~~~~~~
|
|
||||||
|
|
||||||
:copyright: 2013-2016, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
|
|
||||||
|
|
||||||
USAGE = '''
|
|
||||||
Usage: python -m feedgen [OPTION]
|
|
||||||
|
|
||||||
Use one of the following options:
|
|
||||||
|
|
||||||
File options:
|
|
||||||
<file>.atom -- Generate ATOM test feed
|
|
||||||
<file>.rss -- Generate RSS test teed
|
|
||||||
|
|
||||||
Stdout options:
|
|
||||||
atom -- Generate ATOM test output
|
|
||||||
rss -- Generate RSS test output
|
|
||||||
podcast -- Generate Podcast test output
|
|
||||||
dc.atom -- Generate DC extension test output (atom format)
|
|
||||||
dc.rss -- Generate DC extension test output (rss format)
|
|
||||||
syndication.atom -- Generate syndication extension test output (atom format)
|
|
||||||
syndication.rss -- Generate syndication extension test output (rss format)
|
|
||||||
torrent -- Generate Torrent test output
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
def print_enc(s):
|
|
||||||
'''Print function compatible with both python2 and python3 accepting strings
|
|
||||||
and byte arrays.
|
|
||||||
'''
|
|
||||||
if sys.version_info[0] >= 3:
|
|
||||||
print(s.decode('utf-8') if isinstance(s, bytes) else s)
|
|
||||||
else:
|
|
||||||
print(s)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if len(sys.argv) != 2 or not (
|
|
||||||
sys.argv[1].endswith('rss') or
|
|
||||||
sys.argv[1].endswith('atom') or
|
|
||||||
sys.argv[1] == 'torrent' or
|
|
||||||
sys.argv[1] == 'podcast'):
|
|
||||||
print(USAGE)
|
|
||||||
exit()
|
|
||||||
|
|
||||||
arg = sys.argv[1]
|
|
||||||
|
|
||||||
fg = FeedGenerator()
|
|
||||||
fg.id('http://lernfunk.de/_MEDIAID_123')
|
|
||||||
fg.title('Testfeed')
|
|
||||||
fg.author({'name': 'Lars Kiesow', 'email': 'lkiesow@uos.de'})
|
|
||||||
fg.link(href='http://example.com', rel='alternate')
|
|
||||||
fg.category(term='test')
|
|
||||||
fg.contributor(name='Lars Kiesow', email='lkiesow@uos.de')
|
|
||||||
fg.contributor(name='John Doe', email='jdoe@example.com')
|
|
||||||
fg.icon('http://ex.com/icon.jpg')
|
|
||||||
fg.logo('http://ex.com/logo.jpg')
|
|
||||||
fg.rights('cc-by')
|
|
||||||
fg.subtitle('This is a cool feed!')
|
|
||||||
fg.link(href='http://larskiesow.de/test.atom', rel='self')
|
|
||||||
fg.language('de')
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/_MEDIAID_123#1')
|
|
||||||
fe.title('First Element')
|
|
||||||
fe.content('''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Tamen
|
|
||||||
aberramus a proposito, et, ne longius, prorsus, inquam, Piso, si
|
|
||||||
ista mala sunt, placet. Aut etiam, ut vestitum, sic sententiam
|
|
||||||
habeas aliam domesticam, aliam forensem, ut in fronte ostentatio
|
|
||||||
sit, intus veritas occultetur? Cum id fugiunt, re eadem defendunt,
|
|
||||||
quae Peripatetici, verba.''')
|
|
||||||
fe.summary(u'Lorem ipsum dolor sit amet, consectetur adipiscing elit…')
|
|
||||||
fe.link(href='http://example.com', rel='alternate')
|
|
||||||
fe.author(name='Lars Kiesow', email='lkiesow@uos.de')
|
|
||||||
|
|
||||||
if arg == 'atom':
|
|
||||||
print_enc(fg.atom_str(pretty=True))
|
|
||||||
elif arg == 'rss':
|
|
||||||
print_enc(fg.rss_str(pretty=True))
|
|
||||||
elif arg == 'podcast':
|
|
||||||
# Load the podcast extension. It will automatically be loaded for all
|
|
||||||
# entries in the feed, too. Thus also for our “fe”.
|
|
||||||
fg.load_extension('podcast')
|
|
||||||
fg.podcast.itunes_author('Lars Kiesow')
|
|
||||||
fg.podcast.itunes_category('Technology', 'Podcasting')
|
|
||||||
fg.podcast.itunes_explicit('no')
|
|
||||||
fg.podcast.itunes_complete('no')
|
|
||||||
fg.podcast.itunes_new_feed_url('http://example.com/new-feed.rss')
|
|
||||||
fg.podcast.itunes_owner('John Doe', 'john@example.com')
|
|
||||||
fg.podcast.itunes_summary('Lorem ipsum dolor sit amet, consectetur ' +
|
|
||||||
'adipiscing elit. Verba tu fingas et ea ' +
|
|
||||||
'dicas, quae non sentias?')
|
|
||||||
fe.podcast.itunes_author('Lars Kiesow')
|
|
||||||
print_enc(fg.rss_str(pretty=True))
|
|
||||||
|
|
||||||
elif arg == 'torrent':
|
|
||||||
fg.load_extension('torrent')
|
|
||||||
fe.link(href='http://example.com/torrent/debian-8-netint.iso.torrent',
|
|
||||||
rel='alternate',
|
|
||||||
type='application/x-bittorrent, length=1000')
|
|
||||||
fe.torrent.filename('debian-8.4.0-i386-netint.iso.torrent')
|
|
||||||
fe.torrent.infohash('7661229811ef32014879ceedcdf4a48f256c88ba')
|
|
||||||
fe.torrent.contentlength('331350016')
|
|
||||||
fe.torrent.seeds('789')
|
|
||||||
fe.torrent.peers('456')
|
|
||||||
fe.torrent.verified('123')
|
|
||||||
print_enc(fg.rss_str(pretty=True))
|
|
||||||
|
|
||||||
elif arg.startswith('dc.'):
|
|
||||||
fg.load_extension('dc')
|
|
||||||
fg.dc.dc_contributor('Lars Kiesow')
|
|
||||||
if arg.endswith('.atom'):
|
|
||||||
print_enc(fg.atom_str(pretty=True))
|
|
||||||
else:
|
|
||||||
print_enc(fg.rss_str(pretty=True))
|
|
||||||
|
|
||||||
elif arg.startswith('syndication'):
|
|
||||||
fg.load_extension('syndication')
|
|
||||||
fg.syndication.update_period('daily')
|
|
||||||
fg.syndication.update_frequency(2)
|
|
||||||
fg.syndication.update_base('2000-01-01T12:00+00:00')
|
|
||||||
if arg.endswith('.rss'):
|
|
||||||
print_enc(fg.rss_str(pretty=True))
|
|
||||||
else:
|
|
||||||
print_enc(fg.atom_str(pretty=True))
|
|
||||||
|
|
||||||
elif arg.endswith('atom'):
|
|
||||||
fg.atom_file(arg)
|
|
||||||
|
|
||||||
elif arg.endswith('rss'):
|
|
||||||
fg.rss_file(arg)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,8 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
if sys.version_info[0] >= 3:
|
|
||||||
string_types = str
|
|
||||||
else:
|
|
||||||
string_types = basestring # noqa: F821
|
|
738
feedgen/entry.py
|
@ -1,738 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.entry
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
:copyright: 2013-2020, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import dateutil.parser
|
|
||||||
import dateutil.tz
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from lxml.etree import CDATA # nosec - adding CDATA entry is safe
|
|
||||||
|
|
||||||
from feedgen.compat import string_types
|
|
||||||
from feedgen.util import ensure_format, formatRFC2822, xml_fromstring, xml_elem
|
|
||||||
|
|
||||||
|
|
||||||
def _add_text_elm(entry, data, name):
|
|
||||||
"""Add a text subelement to an entry"""
|
|
||||||
if not data:
|
|
||||||
return
|
|
||||||
|
|
||||||
elm = xml_elem(name, entry)
|
|
||||||
type_ = data.get('type')
|
|
||||||
if data.get('src'):
|
|
||||||
if name != 'content':
|
|
||||||
raise ValueError("Only the 'content' element of an entry can "
|
|
||||||
"contain a 'src' attribute")
|
|
||||||
elm.attrib['src'] = data['src']
|
|
||||||
elif data.get(name):
|
|
||||||
# Surround xhtml with a div tag, parse it and embed it
|
|
||||||
if type_ == 'xhtml':
|
|
||||||
xhtml = '<div xmlns="http://www.w3.org/1999/xhtml">' \
|
|
||||||
+ data.get(name) + '</div>'
|
|
||||||
elm.append(xml_fromstring(xhtml))
|
|
||||||
elif type_ == 'CDATA':
|
|
||||||
elm.text = CDATA(data.get(name))
|
|
||||||
# Parse XML and embed it
|
|
||||||
elif type_ and (type_.endswith('/xml') or type_.endswith('+xml')):
|
|
||||||
elm.append(xml_fromstring(data[name]))
|
|
||||||
# Embed the text in escaped form
|
|
||||||
elif not type_ or type_.startswith('text') or type_ == 'html':
|
|
||||||
elm.text = data.get(name)
|
|
||||||
# Everything else should be included base64 encoded
|
|
||||||
else:
|
|
||||||
raise NotImplementedError(
|
|
||||||
'base64 encoded {} is not supported at the moment. '
|
|
||||||
'Pull requests adding support are welcome.'.format(name)
|
|
||||||
)
|
|
||||||
# Add type description of the content
|
|
||||||
if type_:
|
|
||||||
elm.attrib['type'] = type_
|
|
||||||
|
|
||||||
|
|
||||||
class FeedEntry(object):
|
|
||||||
'''FeedEntry call representing an ATOM feeds entry node or an RSS feeds item
|
|
||||||
node.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# ATOM
|
|
||||||
# required
|
|
||||||
self.__atom_id = None
|
|
||||||
self.__atom_title = None
|
|
||||||
self.__atom_updated = datetime.now(dateutil.tz.tzutc())
|
|
||||||
|
|
||||||
# recommended
|
|
||||||
self.__atom_author = None
|
|
||||||
self.__atom_content = None
|
|
||||||
self.__atom_link = None
|
|
||||||
self.__atom_summary = None
|
|
||||||
|
|
||||||
# optional
|
|
||||||
self.__atom_category = None
|
|
||||||
self.__atom_contributor = None
|
|
||||||
self.__atom_published = None
|
|
||||||
self.__atom_source = None
|
|
||||||
self.__atom_rights = None
|
|
||||||
|
|
||||||
# RSS
|
|
||||||
self.__rss_author = None
|
|
||||||
self.__rss_category = None
|
|
||||||
self.__rss_comments = None
|
|
||||||
self.__rss_description = None
|
|
||||||
self.__rss_content = None
|
|
||||||
self.__rss_enclosure = None
|
|
||||||
self.__rss_guid = {}
|
|
||||||
self.__rss_link = None
|
|
||||||
self.__rss_pubDate = None
|
|
||||||
self.__rss_source = None
|
|
||||||
self.__rss_title = None
|
|
||||||
|
|
||||||
# Extension list:
|
|
||||||
self.__extensions = {}
|
|
||||||
self.__extensions_register = {}
|
|
||||||
|
|
||||||
def atom_entry(self, extensions=True):
|
|
||||||
'''Create an ATOM entry and return it.'''
|
|
||||||
entry = xml_elem('entry')
|
|
||||||
if not (self.__atom_id and self.__atom_title and self.__atom_updated):
|
|
||||||
raise ValueError('Required fields not set')
|
|
||||||
id = xml_elem('id', entry)
|
|
||||||
id.text = self.__atom_id
|
|
||||||
title = xml_elem('title', entry)
|
|
||||||
title.text = self.__atom_title
|
|
||||||
updated = xml_elem('updated', entry)
|
|
||||||
updated.text = self.__atom_updated.isoformat()
|
|
||||||
|
|
||||||
# An entry must contain an alternate link if there is no content
|
|
||||||
# element.
|
|
||||||
if not self.__atom_content:
|
|
||||||
links = self.__atom_link or []
|
|
||||||
if not [l for l in links if l.get('rel') == 'alternate']:
|
|
||||||
raise ValueError('Entry must contain an alternate link or ' +
|
|
||||||
'a content element.')
|
|
||||||
|
|
||||||
# Add author elements
|
|
||||||
for a in self.__atom_author or []:
|
|
||||||
# Atom requires a name. Skip elements without.
|
|
||||||
if not a.get('name'):
|
|
||||||
continue
|
|
||||||
author = xml_elem('author', entry)
|
|
||||||
name = xml_elem('name', author)
|
|
||||||
name.text = a.get('name')
|
|
||||||
if a.get('email'):
|
|
||||||
email = xml_elem('email', author)
|
|
||||||
email.text = a.get('email')
|
|
||||||
if a.get('uri'):
|
|
||||||
uri = xml_elem('uri', author)
|
|
||||||
uri.text = a.get('uri')
|
|
||||||
|
|
||||||
_add_text_elm(entry, self.__atom_content, 'content')
|
|
||||||
|
|
||||||
for l in self.__atom_link or []:
|
|
||||||
link = xml_elem('link', entry, href=l['href'])
|
|
||||||
if l.get('rel'):
|
|
||||||
link.attrib['rel'] = l['rel']
|
|
||||||
if l.get('type'):
|
|
||||||
link.attrib['type'] = l['type']
|
|
||||||
if l.get('hreflang'):
|
|
||||||
link.attrib['hreflang'] = l['hreflang']
|
|
||||||
if l.get('title'):
|
|
||||||
link.attrib['title'] = l['title']
|
|
||||||
if l.get('length'):
|
|
||||||
link.attrib['length'] = l['length']
|
|
||||||
|
|
||||||
_add_text_elm(entry, self.__atom_summary, 'summary')
|
|
||||||
|
|
||||||
for c in self.__atom_category or []:
|
|
||||||
cat = xml_elem('category', entry, term=c['term'])
|
|
||||||
if c.get('scheme'):
|
|
||||||
cat.attrib['scheme'] = c['scheme']
|
|
||||||
if c.get('label'):
|
|
||||||
cat.attrib['label'] = c['label']
|
|
||||||
|
|
||||||
# Add author elements
|
|
||||||
for c in self.__atom_contributor or []:
|
|
||||||
# Atom requires a name. Skip elements without.
|
|
||||||
if not c.get('name'):
|
|
||||||
continue
|
|
||||||
contrib = xml_elem('contributor', entry)
|
|
||||||
name = xml_elem('name', contrib)
|
|
||||||
name.text = c.get('name')
|
|
||||||
if c.get('email'):
|
|
||||||
email = xml_elem('email', contrib)
|
|
||||||
email.text = c.get('email')
|
|
||||||
if c.get('uri'):
|
|
||||||
uri = xml_elem('uri', contrib)
|
|
||||||
uri.text = c.get('uri')
|
|
||||||
|
|
||||||
if self.__atom_published:
|
|
||||||
published = xml_elem('published', entry)
|
|
||||||
published.text = self.__atom_published.isoformat()
|
|
||||||
|
|
||||||
if self.__atom_rights:
|
|
||||||
rights = xml_elem('rights', entry)
|
|
||||||
rights.text = self.__atom_rights
|
|
||||||
|
|
||||||
if self.__atom_source:
|
|
||||||
source = xml_elem('source', entry)
|
|
||||||
if self.__atom_source.get('title'):
|
|
||||||
source_title = xml_elem('title', source)
|
|
||||||
source_title.text = self.__atom_source['title']
|
|
||||||
if self.__atom_source.get('link'):
|
|
||||||
xml_elem('link', source, href=self.__atom_source['link'])
|
|
||||||
|
|
||||||
if extensions:
|
|
||||||
for ext in self.__extensions.values() or []:
|
|
||||||
if ext.get('atom'):
|
|
||||||
ext['inst'].extend_atom(entry)
|
|
||||||
|
|
||||||
return entry
|
|
||||||
|
|
||||||
def rss_entry(self, extensions=True):
|
|
||||||
'''Create a RSS item and return it.'''
|
|
||||||
entry = xml_elem('item')
|
|
||||||
if not (self.__rss_title or
|
|
||||||
self.__rss_description or
|
|
||||||
self.__rss_content):
|
|
||||||
raise ValueError('Required fields not set')
|
|
||||||
if self.__rss_title:
|
|
||||||
title = xml_elem('title', entry)
|
|
||||||
title.text = self.__rss_title
|
|
||||||
if self.__rss_link:
|
|
||||||
link = xml_elem('link', entry)
|
|
||||||
link.text = self.__rss_link
|
|
||||||
if self.__rss_description and self.__rss_content:
|
|
||||||
description = xml_elem('description', entry)
|
|
||||||
description.text = self.__rss_description
|
|
||||||
XMLNS_CONTENT = 'http://purl.org/rss/1.0/modules/content/'
|
|
||||||
content = xml_elem('{%s}encoded' % XMLNS_CONTENT, entry)
|
|
||||||
content.text = CDATA(self.__rss_content['content']) \
|
|
||||||
if self.__rss_content.get('type', '') == 'CDATA' \
|
|
||||||
else self.__rss_content['content']
|
|
||||||
elif self.__rss_description:
|
|
||||||
description = xml_elem('description', entry)
|
|
||||||
description.text = self.__rss_description
|
|
||||||
elif self.__rss_content:
|
|
||||||
description = xml_elem('description', entry)
|
|
||||||
description.text = CDATA(self.__rss_content['content']) \
|
|
||||||
if self.__rss_content.get('type', '') == 'CDATA' \
|
|
||||||
else self.__rss_content['content']
|
|
||||||
for a in self.__rss_author or []:
|
|
||||||
author = xml_elem('author', entry)
|
|
||||||
author.text = a
|
|
||||||
if self.__rss_guid.get('guid'):
|
|
||||||
guid = xml_elem('guid', entry)
|
|
||||||
guid.text = self.__rss_guid['guid']
|
|
||||||
permaLink = str(self.__rss_guid.get('permalink', False)).lower()
|
|
||||||
guid.attrib['isPermaLink'] = permaLink
|
|
||||||
for cat in self.__rss_category or []:
|
|
||||||
category = xml_elem('category', entry)
|
|
||||||
category.text = cat['value']
|
|
||||||
if cat.get('domain'):
|
|
||||||
category.attrib['domain'] = cat['domain']
|
|
||||||
if self.__rss_comments:
|
|
||||||
comments = xml_elem('comments', entry)
|
|
||||||
comments.text = self.__rss_comments
|
|
||||||
if self.__rss_enclosure:
|
|
||||||
enclosure = xml_elem('enclosure', entry)
|
|
||||||
enclosure.attrib['url'] = self.__rss_enclosure['url']
|
|
||||||
enclosure.attrib['length'] = self.__rss_enclosure['length']
|
|
||||||
enclosure.attrib['type'] = self.__rss_enclosure['type']
|
|
||||||
if self.__rss_pubDate:
|
|
||||||
pubDate = xml_elem('pubDate', entry)
|
|
||||||
pubDate.text = formatRFC2822(self.__rss_pubDate)
|
|
||||||
if self.__rss_source:
|
|
||||||
source = xml_elem('source', entry, url=self.__rss_source['url'])
|
|
||||||
source.text = self.__rss_source['title']
|
|
||||||
|
|
||||||
if extensions:
|
|
||||||
for ext in self.__extensions.values() or []:
|
|
||||||
if ext.get('rss'):
|
|
||||||
ext['inst'].extend_rss(entry)
|
|
||||||
|
|
||||||
return entry
|
|
||||||
|
|
||||||
def title(self, title=None):
|
|
||||||
'''Get or set the title value of the entry. It should contain a human
|
|
||||||
readable title for the entry. Title is mandatory for both ATOM and RSS
|
|
||||||
and should not be blank.
|
|
||||||
|
|
||||||
:param title: The new title of the entry.
|
|
||||||
:returns: The entriess title.
|
|
||||||
'''
|
|
||||||
if title is not None:
|
|
||||||
self.__atom_title = title
|
|
||||||
self.__rss_title = title
|
|
||||||
return self.__atom_title
|
|
||||||
|
|
||||||
def id(self, id=None):
|
|
||||||
'''Get or set the entry id which identifies the entry using a
|
|
||||||
universally unique and permanent URI. Two entries in a feed can have
|
|
||||||
the same value for id if they represent the same entry at different
|
|
||||||
points in time. This method will also set rss:guid with permalink set
|
|
||||||
to False. Id is mandatory for an ATOM entry.
|
|
||||||
|
|
||||||
:param id: New Id of the entry.
|
|
||||||
:returns: Id of the entry.
|
|
||||||
'''
|
|
||||||
if id is not None:
|
|
||||||
self.__atom_id = id
|
|
||||||
self.__rss_guid = {'guid': id, 'permalink': False}
|
|
||||||
return self.__atom_id
|
|
||||||
|
|
||||||
def guid(self, guid=None, permalink=False):
|
|
||||||
'''Get or set the entries guid which is a string that uniquely
|
|
||||||
identifies the item. This will also set atom:id.
|
|
||||||
|
|
||||||
:param guid: Id of the entry.
|
|
||||||
:param permalink: If this is a permanent identifier for this item
|
|
||||||
:returns: Id and permalink setting of the entry.
|
|
||||||
'''
|
|
||||||
if guid is not None:
|
|
||||||
self.__atom_id = guid
|
|
||||||
self.__rss_guid = {'guid': guid, 'permalink': permalink}
|
|
||||||
return self.__rss_guid
|
|
||||||
|
|
||||||
def updated(self, updated=None):
|
|
||||||
'''Set or get the updated value which indicates the last time the entry
|
|
||||||
was modified in a significant way.
|
|
||||||
|
|
||||||
The value can either be a string which will automatically be parsed or
|
|
||||||
a datetime.datetime object. In any case it is necessary that the value
|
|
||||||
include timezone information.
|
|
||||||
|
|
||||||
:param updated: The modification date.
|
|
||||||
:returns: Modification date as datetime.datetime
|
|
||||||
'''
|
|
||||||
if updated is not None:
|
|
||||||
if isinstance(updated, string_types):
|
|
||||||
updated = dateutil.parser.parse(updated)
|
|
||||||
if not isinstance(updated, datetime):
|
|
||||||
raise ValueError('Invalid datetime format')
|
|
||||||
if updated.tzinfo is None:
|
|
||||||
raise ValueError('Datetime object has no timezone info')
|
|
||||||
self.__atom_updated = updated
|
|
||||||
self.__rss_lastBuildDate = updated
|
|
||||||
|
|
||||||
return self.__atom_updated
|
|
||||||
|
|
||||||
def author(self, author=None, replace=False, **kwargs):
|
|
||||||
'''Get or set author data. An author element is a dict containing a
|
|
||||||
name, an email address and a uri. Name is mandatory for ATOM, email is
|
|
||||||
mandatory for RSS.
|
|
||||||
|
|
||||||
This method can be called with:
|
|
||||||
- the fields of an author as keyword arguments
|
|
||||||
- the fields of an author as a dictionary
|
|
||||||
- a list of dictionaries containing the author fields
|
|
||||||
|
|
||||||
An author has the following fields:
|
|
||||||
- *name* conveys a human-readable name for the person.
|
|
||||||
- *uri* contains a home page for the person.
|
|
||||||
- *email* contains an email address for the person.
|
|
||||||
|
|
||||||
:param author: Dict or list of dicts with author data.
|
|
||||||
:param replace: Add or replace old data.
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
>>> author({'name':'John Doe', 'email':'jdoe@example.com'})
|
|
||||||
[{'name':'John Doe','email':'jdoe@example.com'}]
|
|
||||||
|
|
||||||
>>> author([{'name': 'Mr. X'}, {'name': 'Max'}])
|
|
||||||
[{'name':'John Doe','email':'jdoe@example.com'},
|
|
||||||
{'name':'John Doe'}, {'name':'Max'}]
|
|
||||||
|
|
||||||
>>> author(name='John Doe', email='jdoe@example.com', replace=True)
|
|
||||||
[{'name':'John Doe','email':'jdoe@example.com'}]
|
|
||||||
|
|
||||||
'''
|
|
||||||
if author is None and kwargs:
|
|
||||||
author = kwargs
|
|
||||||
if author is not None:
|
|
||||||
if replace or self.__atom_author is None:
|
|
||||||
self.__atom_author = []
|
|
||||||
self.__atom_author += ensure_format(author,
|
|
||||||
set(['name', 'email', 'uri']),
|
|
||||||
set())
|
|
||||||
self.__rss_author = []
|
|
||||||
for a in self.__atom_author:
|
|
||||||
if a.get('email'):
|
|
||||||
if a.get('name'):
|
|
||||||
self.__rss_author.append('%(email)s (%(name)s)' % a)
|
|
||||||
else:
|
|
||||||
self.__rss_author.append('%(email)s' % a)
|
|
||||||
return self.__atom_author
|
|
||||||
|
|
||||||
def content(self, content=None, src=None, type=None):
|
|
||||||
'''Get or set the content of the entry which contains or links to the
|
|
||||||
complete content of the entry. Content must be provided for ATOM
|
|
||||||
entries if there is no alternate link, and should be provided if there
|
|
||||||
is no summary. If the content is set (not linked) it will also set
|
|
||||||
rss:description.
|
|
||||||
|
|
||||||
:param content: The content of the feed entry.
|
|
||||||
:param src: Link to the entries content.
|
|
||||||
:param type: If type is CDATA content would not be escaped.
|
|
||||||
:returns: Content element of the entry.
|
|
||||||
'''
|
|
||||||
if src is not None:
|
|
||||||
self.__atom_content = {'src': src}
|
|
||||||
elif content is not None:
|
|
||||||
self.__atom_content = {'content': content}
|
|
||||||
self.__rss_content = {'content': content}
|
|
||||||
if type is not None:
|
|
||||||
self.__atom_content['type'] = type
|
|
||||||
self.__rss_content['type'] = type
|
|
||||||
return self.__atom_content
|
|
||||||
|
|
||||||
def link(self, link=None, replace=False, **kwargs):
|
|
||||||
'''Get or set link data. An link element is a dict with the fields
|
|
||||||
href, rel, type, hreflang, title, and length. Href is mandatory for
|
|
||||||
ATOM.
|
|
||||||
|
|
||||||
This method can be called with:
|
|
||||||
- the fields of a link as keyword arguments
|
|
||||||
- the fields of a link as a dictionary
|
|
||||||
- a list of dictionaries containing the link fields
|
|
||||||
|
|
||||||
A link has the following fields:
|
|
||||||
|
|
||||||
- *href* is the URI of the referenced resource (typically a Web page)
|
|
||||||
- *rel* contains a single link relationship type. It can be a full URI,
|
|
||||||
or one of the following predefined values (default=alternate):
|
|
||||||
|
|
||||||
- *alternate* an alternate representation of the entry or feed, for
|
|
||||||
example a permalink to the html version of the entry, or the
|
|
||||||
front page of the weblog.
|
|
||||||
- *enclosure* a related resource which is potentially large in size
|
|
||||||
and might require special handling, for example an audio or video
|
|
||||||
recording.
|
|
||||||
- *related* an document related to the entry or feed.
|
|
||||||
- *self* the feed itself.
|
|
||||||
- *via* the source of the information provided in the entry.
|
|
||||||
|
|
||||||
- *type* indicates the media type of the resource.
|
|
||||||
- *hreflang* indicates the language of the referenced resource.
|
|
||||||
- *title* human readable information about the link, typically for
|
|
||||||
display purposes.
|
|
||||||
- *length* the length of the resource, in bytes.
|
|
||||||
|
|
||||||
RSS only supports one link with nothing but a URL. So for the RSS link
|
|
||||||
element the last link with rel=alternate is used.
|
|
||||||
|
|
||||||
RSS also supports one enclusure element per entry which is covered by
|
|
||||||
the link element in ATOM feed entries. So for the RSS enclusure element
|
|
||||||
the last link with rel=enclosure is used.
|
|
||||||
|
|
||||||
:param link: Dict or list of dicts with data.
|
|
||||||
:param replace: Add or replace old data.
|
|
||||||
:returns: List of link data.
|
|
||||||
'''
|
|
||||||
if link is None and kwargs:
|
|
||||||
link = kwargs
|
|
||||||
if link is not None:
|
|
||||||
if replace or self.__atom_link is None:
|
|
||||||
self.__atom_link = []
|
|
||||||
self.__atom_link += ensure_format(
|
|
||||||
link,
|
|
||||||
set(['href', 'rel', 'type', 'hreflang', 'title', 'length']),
|
|
||||||
set(['href']),
|
|
||||||
{'rel': ['alternate', 'enclosure', 'related', 'self', 'via']},
|
|
||||||
{'rel': 'alternate'})
|
|
||||||
# RSS only needs one URL. We use the first link for RSS:
|
|
||||||
for l in self.__atom_link:
|
|
||||||
if l.get('rel') == 'alternate':
|
|
||||||
self.__rss_link = l['href']
|
|
||||||
elif l.get('rel') == 'enclosure':
|
|
||||||
self.__rss_enclosure = {'url': l['href']}
|
|
||||||
self.__rss_enclosure['type'] = l.get('type')
|
|
||||||
self.__rss_enclosure['length'] = l.get('length') or '0'
|
|
||||||
# return the set with more information (atom)
|
|
||||||
return self.__atom_link
|
|
||||||
|
|
||||||
def summary(self, summary=None, type=None):
|
|
||||||
'''Get or set the summary element of an entry which conveys a short
|
|
||||||
summary, abstract, or excerpt of the entry. Summary is an ATOM only
|
|
||||||
element and should be provided if there either is no content provided
|
|
||||||
for the entry, or that content is not inline (i.e., contains a src
|
|
||||||
attribute), or if the content is encoded in base64. This method will
|
|
||||||
also set the rss:description field if it wasn't previously set or
|
|
||||||
contains the old value of summary.
|
|
||||||
|
|
||||||
:param summary: Summary of the entries contents.
|
|
||||||
:returns: Summary of the entries contents.
|
|
||||||
'''
|
|
||||||
if summary is not None:
|
|
||||||
# Replace the RSS description with the summary if it was the
|
|
||||||
# summary before. Not if it is the description.
|
|
||||||
if not self.__rss_description or (
|
|
||||||
self.__atom_summary and
|
|
||||||
self.__rss_description == self.__atom_summary.get("summary")
|
|
||||||
):
|
|
||||||
self.__rss_description = summary
|
|
||||||
|
|
||||||
self.__atom_summary = {'summary': summary}
|
|
||||||
if type is not None:
|
|
||||||
self.__atom_summary['type'] = type
|
|
||||||
return self.__atom_summary
|
|
||||||
|
|
||||||
def description(self, description=None, isSummary=False):
|
|
||||||
'''Get or set the description value which is the item synopsis.
|
|
||||||
Description is an RSS only element. For ATOM feeds it is split in
|
|
||||||
summary and content. The isSummary parameter can be used to control
|
|
||||||
which ATOM value is set when setting description.
|
|
||||||
|
|
||||||
:param description: Description of the entry.
|
|
||||||
:param isSummary: If the description should be used as content or
|
|
||||||
summary.
|
|
||||||
:returns: The entries description.
|
|
||||||
'''
|
|
||||||
if description is not None:
|
|
||||||
self.__rss_description = description
|
|
||||||
if isSummary:
|
|
||||||
self.__atom_summary = description
|
|
||||||
else:
|
|
||||||
self.__atom_content = {'content': description}
|
|
||||||
return self.__rss_description
|
|
||||||
|
|
||||||
def category(self, category=None, replace=False, **kwargs):
|
|
||||||
'''Get or set categories that the entry belongs to.
|
|
||||||
|
|
||||||
This method can be called with:
|
|
||||||
- the fields of a category as keyword arguments
|
|
||||||
- the fields of a category as a dictionary
|
|
||||||
- a list of dictionaries containing the category fields
|
|
||||||
|
|
||||||
A categories has the following fields:
|
|
||||||
- *term* identifies the category
|
|
||||||
- *scheme* identifies the categorization scheme via a URI.
|
|
||||||
- *label* provides a human-readable label for display
|
|
||||||
|
|
||||||
If a label is present it is used for the RSS feeds. Otherwise the term
|
|
||||||
is used. The scheme is used for the domain attribute in RSS.
|
|
||||||
|
|
||||||
:param category: Dict or list of dicts with data.
|
|
||||||
:param replace: Add or replace old data.
|
|
||||||
:returns: List of category data.
|
|
||||||
'''
|
|
||||||
if category is None and kwargs:
|
|
||||||
category = kwargs
|
|
||||||
if category is not None:
|
|
||||||
if replace or self.__atom_category is None:
|
|
||||||
self.__atom_category = []
|
|
||||||
self.__atom_category += ensure_format(
|
|
||||||
category,
|
|
||||||
set(['term', 'scheme', 'label']),
|
|
||||||
set(['term']))
|
|
||||||
# Map the ATOM categories to RSS categories. Use the atom:label as
|
|
||||||
# name or if not present the atom:term. The atom:scheme is the
|
|
||||||
# rss:domain.
|
|
||||||
self.__rss_category = []
|
|
||||||
for cat in self.__atom_category:
|
|
||||||
rss_cat = {}
|
|
||||||
rss_cat['value'] = cat.get('label', cat['term'])
|
|
||||||
if cat.get('scheme'):
|
|
||||||
rss_cat['domain'] = cat['scheme']
|
|
||||||
self.__rss_category.append(rss_cat)
|
|
||||||
return self.__atom_category
|
|
||||||
|
|
||||||
def contributor(self, contributor=None, replace=False, **kwargs):
|
|
||||||
'''Get or set the contributor data of the feed. This is an ATOM only
|
|
||||||
value.
|
|
||||||
|
|
||||||
This method can be called with:
|
|
||||||
- the fields of an contributor as keyword arguments
|
|
||||||
- the fields of an contributor as a dictionary
|
|
||||||
- a list of dictionaries containing the contributor fields
|
|
||||||
|
|
||||||
An contributor has the following fields:
|
|
||||||
- *name* conveys a human-readable name for the person.
|
|
||||||
- *uri* contains a home page for the person.
|
|
||||||
- *email* contains an email address for the person.
|
|
||||||
|
|
||||||
:param contributor: Dictionary or list of dictionaries with contributor
|
|
||||||
data.
|
|
||||||
:param replace: Add or replace old data.
|
|
||||||
:returns: List of contributors as dictionaries.
|
|
||||||
'''
|
|
||||||
if contributor is None and kwargs:
|
|
||||||
contributor = kwargs
|
|
||||||
if contributor is not None:
|
|
||||||
if replace or self.__atom_contributor is None:
|
|
||||||
self.__atom_contributor = []
|
|
||||||
self.__atom_contributor += ensure_format(
|
|
||||||
contributor, set(['name', 'email', 'uri']), set(['name']))
|
|
||||||
return self.__atom_contributor
|
|
||||||
|
|
||||||
def published(self, published=None):
|
|
||||||
'''Set or get the published value which contains the time of the initial
|
|
||||||
creation or first availability of the entry.
|
|
||||||
|
|
||||||
The value can either be a string which will automatically be parsed or
|
|
||||||
a datetime.datetime object. In any case it is necessary that the value
|
|
||||||
include timezone information.
|
|
||||||
|
|
||||||
:param published: The creation date.
|
|
||||||
:returns: Creation date as datetime.datetime
|
|
||||||
'''
|
|
||||||
if published is not None:
|
|
||||||
if isinstance(published, string_types):
|
|
||||||
published = dateutil.parser.parse(published)
|
|
||||||
if not isinstance(published, datetime):
|
|
||||||
raise ValueError('Invalid datetime format')
|
|
||||||
if published.tzinfo is None:
|
|
||||||
raise ValueError('Datetime object has no timezone info')
|
|
||||||
self.__atom_published = published
|
|
||||||
self.__rss_pubDate = published
|
|
||||||
|
|
||||||
return self.__atom_published
|
|
||||||
|
|
||||||
def pubDate(self, pubDate=None):
|
|
||||||
'''Get or set the pubDate of the entry which indicates when the entry
|
|
||||||
was published. This method is just another name for the published(...)
|
|
||||||
method.
|
|
||||||
'''
|
|
||||||
return self.published(pubDate)
|
|
||||||
|
|
||||||
def pubdate(self, pubDate=None):
|
|
||||||
'''Get or set the pubDate of the entry which indicates when the entry
|
|
||||||
was published. This method is just another name for the published(...)
|
|
||||||
method.
|
|
||||||
|
|
||||||
pubdate(…) is deprecated and may be removed in feedgen ≥ 0.8. Use
|
|
||||||
pubDate(…) instead.
|
|
||||||
'''
|
|
||||||
warnings.warn('pubdate(…) is deprecated and may be removed in feedgen '
|
|
||||||
'≥ 0.8. Use pubDate(…) instead.')
|
|
||||||
return self.published(pubDate)
|
|
||||||
|
|
||||||
def rights(self, rights=None):
|
|
||||||
'''Get or set the rights value of the entry which conveys information
|
|
||||||
about rights, e.g. copyrights, held in and over the entry. This ATOM
|
|
||||||
value will also set rss:copyright.
|
|
||||||
|
|
||||||
:param rights: Rights information of the feed.
|
|
||||||
:returns: Rights information of the feed.
|
|
||||||
'''
|
|
||||||
if rights is not None:
|
|
||||||
self.__atom_rights = rights
|
|
||||||
return self.__atom_rights
|
|
||||||
|
|
||||||
def comments(self, comments=None):
|
|
||||||
'''Get or set the value of comments which is the URL of the comments
|
|
||||||
page for the item. This is a RSS only value.
|
|
||||||
|
|
||||||
:param comments: URL to the comments page.
|
|
||||||
:returns: URL to the comments page.
|
|
||||||
'''
|
|
||||||
if comments is not None:
|
|
||||||
self.__rss_comments = comments
|
|
||||||
return self.__rss_comments
|
|
||||||
|
|
||||||
def source(self, url=None, title=None):
|
|
||||||
'''Get or set the source for the current feed entry.
|
|
||||||
|
|
||||||
Note that ATOM feeds support a lot more sub elements than title and URL
|
|
||||||
(which is what RSS supports) but these are currently not supported.
|
|
||||||
Patches are welcome.
|
|
||||||
|
|
||||||
:param url: Link to the source.
|
|
||||||
:param title: Title of the linked resource
|
|
||||||
:returns: Source element as dictionaries.
|
|
||||||
'''
|
|
||||||
if url is not None and title is not None:
|
|
||||||
self.__rss_source = {'url': url, 'title': title}
|
|
||||||
self.__atom_source = {'link': url, 'title': title}
|
|
||||||
return self.__rss_source
|
|
||||||
|
|
||||||
def enclosure(self, url=None, length=None, type=None):
|
|
||||||
'''Get or set the value of enclosure which describes a media object
|
|
||||||
that is attached to the item. This is a RSS only value which is
|
|
||||||
represented by link(rel=enclosure) in ATOM. ATOM feeds can furthermore
|
|
||||||
contain several enclosures while RSS may contain only one. That is why
|
|
||||||
this method, if repeatedly called, will add more than one enclosures to
|
|
||||||
the feed. However, only the last one is used for RSS.
|
|
||||||
|
|
||||||
:param url: URL of the media object.
|
|
||||||
:param length: Size of the media in bytes.
|
|
||||||
:param type: Mimetype of the linked media.
|
|
||||||
:returns: Data of the enclosure element.
|
|
||||||
'''
|
|
||||||
if url is not None:
|
|
||||||
self.link(href=url, rel='enclosure', type=type, length=length)
|
|
||||||
return self.__rss_enclosure
|
|
||||||
|
|
||||||
def ttl(self, ttl=None):
|
|
||||||
'''Get or set the ttl value. It is an RSS only element. ttl stands for
|
|
||||||
time to live. It's a number of minutes that indicates how long a
|
|
||||||
channel can be cached before refreshing from the source.
|
|
||||||
|
|
||||||
:param ttl: Integer value representing the time to live.
|
|
||||||
:returns: Time to live of of the entry.
|
|
||||||
'''
|
|
||||||
if ttl is not None:
|
|
||||||
self.__rss_ttl = int(ttl)
|
|
||||||
return self.__rss_ttl
|
|
||||||
|
|
||||||
def load_extension(self, name, atom=True, rss=True):
|
|
||||||
'''Load a specific extension by name.
|
|
||||||
|
|
||||||
:param name: Name of the extension to load.
|
|
||||||
:param atom: If the extension should be used for ATOM feeds.
|
|
||||||
:param rss: If the extension should be used for RSS feeds.
|
|
||||||
'''
|
|
||||||
# Check loaded extensions
|
|
||||||
if not isinstance(self.__extensions, dict):
|
|
||||||
self.__extensions = {}
|
|
||||||
if name in self.__extensions.keys():
|
|
||||||
raise ImportError('Extension already loaded')
|
|
||||||
|
|
||||||
# Load extension
|
|
||||||
extname = name[0].upper() + name[1:] + 'EntryExtension'
|
|
||||||
try:
|
|
||||||
supmod = __import__('feedgen.ext.%s_entry' % name)
|
|
||||||
extmod = getattr(supmod.ext, name + '_entry')
|
|
||||||
except ImportError:
|
|
||||||
# Use FeedExtension module instead
|
|
||||||
supmod = __import__('feedgen.ext.%s' % name)
|
|
||||||
extmod = getattr(supmod.ext, name)
|
|
||||||
ext = getattr(extmod, extname)
|
|
||||||
self.register_extension(name, ext, atom, rss)
|
|
||||||
|
|
||||||
def register_extension(self, namespace, extension_class_entry=None,
|
|
||||||
atom=True, rss=True):
|
|
||||||
'''Register a specific extension by classes to a namespace.
|
|
||||||
|
|
||||||
:param namespace: namespace for the extension
|
|
||||||
:param extension_class_entry: Class of the entry extension to load.
|
|
||||||
:param atom: If the extension should be used for ATOM feeds.
|
|
||||||
:param rss: If the extension should be used for RSS feeds.
|
|
||||||
'''
|
|
||||||
# Check loaded extensions
|
|
||||||
# `load_extension` ignores the "Extension" suffix.
|
|
||||||
if not isinstance(self.__extensions, dict):
|
|
||||||
self.__extensions = {}
|
|
||||||
if namespace in self.__extensions.keys():
|
|
||||||
raise ImportError('Extension already loaded')
|
|
||||||
if not extension_class_entry:
|
|
||||||
raise ImportError('No extension class')
|
|
||||||
|
|
||||||
extinst = extension_class_entry()
|
|
||||||
setattr(self, namespace, extinst)
|
|
||||||
|
|
||||||
# `load_extension` registry
|
|
||||||
self.__extensions[namespace] = {
|
|
||||||
'inst': extinst,
|
|
||||||
'extension_class_entry': extension_class_entry,
|
|
||||||
'atom': atom,
|
|
||||||
'rss': rss
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
===========
|
|
||||||
feedgen.ext
|
|
||||||
===========
|
|
||||||
"""
|
|
|
@ -1,43 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.ext.base
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Basic FeedGenerator extension which does nothing but provides all necessary
|
|
||||||
methods.
|
|
||||||
|
|
||||||
:copyright: 2013, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
class BaseExtension(object):
|
|
||||||
'''Basic FeedGenerator extension.
|
|
||||||
'''
|
|
||||||
def extend_ns(self):
|
|
||||||
'''Returns a dict that will be used in the namespace map for the feed.
|
|
||||||
'''
|
|
||||||
return dict()
|
|
||||||
|
|
||||||
def extend_rss(self, feed):
|
|
||||||
'''Extend a RSS feed xml structure containing all previously set fields.
|
|
||||||
|
|
||||||
:param feed: The feed xml root element.
|
|
||||||
:returns: The feed root element.
|
|
||||||
'''
|
|
||||||
return feed
|
|
||||||
|
|
||||||
def extend_atom(self, feed):
|
|
||||||
'''Extend an ATOM feed xml structure containing all previously set
|
|
||||||
fields.
|
|
||||||
|
|
||||||
:param feed: The feed xml root element.
|
|
||||||
:returns: The feed root element.
|
|
||||||
'''
|
|
||||||
return feed
|
|
||||||
|
|
||||||
|
|
||||||
class BaseEntryExtension(BaseExtension):
|
|
||||||
'''Basic FeedEntry extension.
|
|
||||||
'''
|
|
|
@ -1,407 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.ext.dc
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Extends the FeedGenerator to add Dubline Core Elements to the feeds.
|
|
||||||
|
|
||||||
Descriptions partly taken from
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-coverage
|
|
||||||
|
|
||||||
:copyright: 2013-2017, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
|
|
||||||
from feedgen.ext.base import BaseExtension
|
|
||||||
from feedgen.util import xml_elem
|
|
||||||
|
|
||||||
|
|
||||||
class DcBaseExtension(BaseExtension):
|
|
||||||
'''Dublin Core Elements extension for podcasts.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# http://dublincore.org/documents/usageguide/elements.shtml
|
|
||||||
# http://dublincore.org/documents/dces/
|
|
||||||
# http://dublincore.org/documents/dcmi-terms/
|
|
||||||
self._dcelem_contributor = None
|
|
||||||
self._dcelem_coverage = None
|
|
||||||
self._dcelem_creator = None
|
|
||||||
self._dcelem_date = None
|
|
||||||
self._dcelem_description = None
|
|
||||||
self._dcelem_format = None
|
|
||||||
self._dcelem_identifier = None
|
|
||||||
self._dcelem_language = None
|
|
||||||
self._dcelem_publisher = None
|
|
||||||
self._dcelem_relation = None
|
|
||||||
self._dcelem_rights = None
|
|
||||||
self._dcelem_source = None
|
|
||||||
self._dcelem_subject = None
|
|
||||||
self._dcelem_title = None
|
|
||||||
self._dcelem_type = None
|
|
||||||
|
|
||||||
def extend_ns(self):
|
|
||||||
return {'dc': 'http://purl.org/dc/elements/1.1/'}
|
|
||||||
|
|
||||||
def _extend_xml(self, xml_element):
|
|
||||||
'''Extend xml_element with set DC fields.
|
|
||||||
|
|
||||||
:param xml_element: etree element
|
|
||||||
'''
|
|
||||||
DCELEMENTS_NS = 'http://purl.org/dc/elements/1.1/'
|
|
||||||
|
|
||||||
for elem in ['contributor', 'coverage', 'creator', 'date',
|
|
||||||
'description', 'language', 'publisher', 'relation',
|
|
||||||
'rights', 'source', 'subject', 'title', 'type', 'format',
|
|
||||||
'identifier']:
|
|
||||||
if hasattr(self, '_dcelem_%s' % elem):
|
|
||||||
for val in getattr(self, '_dcelem_%s' % elem) or []:
|
|
||||||
node = xml_elem('{%s}%s' % (DCELEMENTS_NS, elem),
|
|
||||||
xml_element)
|
|
||||||
node.text = val
|
|
||||||
|
|
||||||
def extend_atom(self, atom_feed):
|
|
||||||
'''Extend an Atom feed with the set DC fields.
|
|
||||||
|
|
||||||
:param atom_feed: The feed root element
|
|
||||||
:returns: The feed root element
|
|
||||||
'''
|
|
||||||
|
|
||||||
self._extend_xml(atom_feed)
|
|
||||||
|
|
||||||
return atom_feed
|
|
||||||
|
|
||||||
def extend_rss(self, rss_feed):
|
|
||||||
'''Extend a RSS feed with the set DC fields.
|
|
||||||
|
|
||||||
:param rss_feed: The feed root element
|
|
||||||
:returns: The feed root element.
|
|
||||||
'''
|
|
||||||
channel = rss_feed[0]
|
|
||||||
self._extend_xml(channel)
|
|
||||||
|
|
||||||
return rss_feed
|
|
||||||
|
|
||||||
def dc_contributor(self, contributor=None, replace=False):
|
|
||||||
'''Get or set the dc:contributor which is an entity responsible for
|
|
||||||
making contributions to the resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-contributor
|
|
||||||
|
|
||||||
:param contributor: Contributor or list of contributors.
|
|
||||||
:param replace: Replace alredy set contributors (deault: False).
|
|
||||||
:returns: List of contributors.
|
|
||||||
'''
|
|
||||||
if contributor is not None:
|
|
||||||
if not isinstance(contributor, list):
|
|
||||||
contributor = [contributor]
|
|
||||||
if replace or not self._dcelem_contributor:
|
|
||||||
self._dcelem_contributor = []
|
|
||||||
self._dcelem_contributor += contributor
|
|
||||||
return self._dcelem_contributor
|
|
||||||
|
|
||||||
def dc_coverage(self, coverage=None, replace=True):
|
|
||||||
'''Get or set the dc:coverage which indicated the spatial or temporal
|
|
||||||
topic of the resource, the spatial applicability of the resource, or
|
|
||||||
the jurisdiction under which the resource is relevant.
|
|
||||||
|
|
||||||
Spatial topic and spatial applicability may be a named place or a
|
|
||||||
location specified by its geographic coordinates. Temporal topic may be
|
|
||||||
a named period, date, or date range. A jurisdiction may be a named
|
|
||||||
administrative entity or a geographic place to which the resource
|
|
||||||
applies. Recommended best practice is to use a controlled vocabulary
|
|
||||||
such as the Thesaurus of Geographic Names [TGN]. Where appropriate,
|
|
||||||
named places or time periods can be used in preference to numeric
|
|
||||||
identifiers such as sets of coordinates or date ranges.
|
|
||||||
|
|
||||||
References:
|
|
||||||
[TGN] http://www.getty.edu/research/tools/vocabulary/tgn/index.html
|
|
||||||
|
|
||||||
:param coverage: Coverage of the feed.
|
|
||||||
:param replace: Replace already set coverage (default: True).
|
|
||||||
:returns: Coverage of the feed.
|
|
||||||
'''
|
|
||||||
if coverage is not None:
|
|
||||||
if not isinstance(coverage, list):
|
|
||||||
coverage = [coverage]
|
|
||||||
if replace or not self._dcelem_coverage:
|
|
||||||
self._dcelem_coverage = []
|
|
||||||
self._dcelem_coverage = coverage
|
|
||||||
return self._dcelem_coverage
|
|
||||||
|
|
||||||
def dc_creator(self, creator=None, replace=False):
|
|
||||||
'''Get or set the dc:creator which is an entity primarily responsible
|
|
||||||
for making the resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-creator
|
|
||||||
|
|
||||||
:param creator: Creator or list of creators.
|
|
||||||
:param replace: Replace alredy set creators (deault: False).
|
|
||||||
:returns: List of creators.
|
|
||||||
'''
|
|
||||||
if creator is not None:
|
|
||||||
if not isinstance(creator, list):
|
|
||||||
creator = [creator]
|
|
||||||
if replace or not self._dcelem_creator:
|
|
||||||
self._dcelem_creator = []
|
|
||||||
self._dcelem_creator += creator
|
|
||||||
return self._dcelem_creator
|
|
||||||
|
|
||||||
def dc_date(self, date=None, replace=True):
|
|
||||||
'''Get or set the dc:date which describes a point or period of time
|
|
||||||
associated with an event in the lifecycle of the resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-date
|
|
||||||
|
|
||||||
:param date: Date or list of dates.
|
|
||||||
:param replace: Replace alredy set dates (deault: True).
|
|
||||||
:returns: List of dates.
|
|
||||||
'''
|
|
||||||
if date is not None:
|
|
||||||
if not isinstance(date, list):
|
|
||||||
date = [date]
|
|
||||||
if replace or not self._dcelem_date:
|
|
||||||
self._dcelem_date = []
|
|
||||||
self._dcelem_date += date
|
|
||||||
return self._dcelem_date
|
|
||||||
|
|
||||||
def dc_description(self, description=None, replace=True):
|
|
||||||
'''Get or set the dc:description which is an account of the resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-description
|
|
||||||
|
|
||||||
:param description: Description or list of descriptions.
|
|
||||||
:param replace: Replace alredy set descriptions (deault: True).
|
|
||||||
:returns: List of descriptions.
|
|
||||||
'''
|
|
||||||
if description is not None:
|
|
||||||
if not isinstance(description, list):
|
|
||||||
description = [description]
|
|
||||||
if replace or not self._dcelem_description:
|
|
||||||
self._dcelem_description = []
|
|
||||||
self._dcelem_description += description
|
|
||||||
return self._dcelem_description
|
|
||||||
|
|
||||||
def dc_format(self, format=None, replace=True):
|
|
||||||
'''Get or set the dc:format which describes the file format, physical
|
|
||||||
medium, or dimensions of the resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-format
|
|
||||||
|
|
||||||
:param format: Format of the resource or list of formats.
|
|
||||||
:param replace: Replace alredy set format (deault: True).
|
|
||||||
:returns: Format of the resource.
|
|
||||||
'''
|
|
||||||
if format is not None:
|
|
||||||
if not isinstance(format, list):
|
|
||||||
format = [format]
|
|
||||||
if replace or not self._dcelem_format:
|
|
||||||
self._dcelem_format = []
|
|
||||||
self._dcelem_format += format
|
|
||||||
return self._dcelem_format
|
|
||||||
|
|
||||||
def dc_identifier(self, identifier=None, replace=True):
|
|
||||||
'''Get or set the dc:identifier which should be an unambiguous
|
|
||||||
reference to the resource within a given context.
|
|
||||||
|
|
||||||
For more inidentifierion see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-identifier
|
|
||||||
|
|
||||||
:param identifier: Identifier of the resource or list of identifiers.
|
|
||||||
:param replace: Replace alredy set identifier (deault: True).
|
|
||||||
:returns: Identifiers of the resource.
|
|
||||||
'''
|
|
||||||
if identifier is not None:
|
|
||||||
if not isinstance(identifier, list):
|
|
||||||
identifier = [identifier]
|
|
||||||
if replace or not self._dcelem_identifier:
|
|
||||||
self._dcelem_identifier = []
|
|
||||||
self._dcelem_identifier += identifier
|
|
||||||
return self._dcelem_identifier
|
|
||||||
|
|
||||||
def dc_language(self, language=None, replace=True):
|
|
||||||
'''Get or set the dc:language which describes a language of the
|
|
||||||
resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-language
|
|
||||||
|
|
||||||
:param language: Language or list of languages.
|
|
||||||
:param replace: Replace alredy set languages (deault: True).
|
|
||||||
:returns: List of languages.
|
|
||||||
'''
|
|
||||||
if language is not None:
|
|
||||||
if not isinstance(language, list):
|
|
||||||
language = [language]
|
|
||||||
if replace or not self._dcelem_language:
|
|
||||||
self._dcelem_language = []
|
|
||||||
self._dcelem_language += language
|
|
||||||
return self._dcelem_language
|
|
||||||
|
|
||||||
def dc_publisher(self, publisher=None, replace=False):
|
|
||||||
'''Get or set the dc:publisher which is an entity responsible for
|
|
||||||
making the resource available.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-publisher
|
|
||||||
|
|
||||||
:param publisher: Publisher or list of publishers.
|
|
||||||
:param replace: Replace alredy set publishers (deault: False).
|
|
||||||
:returns: List of publishers.
|
|
||||||
'''
|
|
||||||
if publisher is not None:
|
|
||||||
if not isinstance(publisher, list):
|
|
||||||
publisher = [publisher]
|
|
||||||
if replace or not self._dcelem_publisher:
|
|
||||||
self._dcelem_publisher = []
|
|
||||||
self._dcelem_publisher += publisher
|
|
||||||
return self._dcelem_publisher
|
|
||||||
|
|
||||||
def dc_relation(self, relation=None, replace=False):
|
|
||||||
'''Get or set the dc:relation which describes a related resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-relation
|
|
||||||
|
|
||||||
:param relation: Relation or list of relations.
|
|
||||||
:param replace: Replace alredy set relations (deault: False).
|
|
||||||
:returns: List of relations.
|
|
||||||
'''
|
|
||||||
if relation is not None:
|
|
||||||
if not isinstance(relation, list):
|
|
||||||
relation = [relation]
|
|
||||||
if replace or not self._dcelem_relation:
|
|
||||||
self._dcelem_relation = []
|
|
||||||
self._dcelem_relation += relation
|
|
||||||
return self._dcelem_relation
|
|
||||||
|
|
||||||
def dc_rights(self, rights=None, replace=False):
|
|
||||||
'''Get or set the dc:rights which may contain information about rights
|
|
||||||
held in and over the resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-rights
|
|
||||||
|
|
||||||
:param rights: Rights information or list of rights information.
|
|
||||||
:param replace: Replace alredy set rightss (deault: False).
|
|
||||||
:returns: List of rights information.
|
|
||||||
'''
|
|
||||||
if rights is not None:
|
|
||||||
if not isinstance(rights, list):
|
|
||||||
rights = [rights]
|
|
||||||
if replace or not self._dcelem_rights:
|
|
||||||
self._dcelem_rights = []
|
|
||||||
self._dcelem_rights += rights
|
|
||||||
return self._dcelem_rights
|
|
||||||
|
|
||||||
def dc_source(self, source=None, replace=False):
|
|
||||||
'''Get or set the dc:source which is a related resource from which the
|
|
||||||
described resource is derived.
|
|
||||||
|
|
||||||
The described resource may be derived from the related resource in
|
|
||||||
whole or in part. Recommended best practice is to identify the related
|
|
||||||
resource by means of a string conforming to a formal identification
|
|
||||||
system.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-source
|
|
||||||
|
|
||||||
:param source: Source or list of sources.
|
|
||||||
:param replace: Replace alredy set sources (deault: False).
|
|
||||||
:returns: List of sources.
|
|
||||||
'''
|
|
||||||
if source is not None:
|
|
||||||
if not isinstance(source, list):
|
|
||||||
source = [source]
|
|
||||||
if replace or not self._dcelem_source:
|
|
||||||
self._dcelem_source = []
|
|
||||||
self._dcelem_source += source
|
|
||||||
return self._dcelem_source
|
|
||||||
|
|
||||||
def dc_subject(self, subject=None, replace=False):
|
|
||||||
'''Get or set the dc:subject which describes the topic of the resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-subject
|
|
||||||
|
|
||||||
:param subject: Subject or list of subjects.
|
|
||||||
:param replace: Replace alredy set subjects (deault: False).
|
|
||||||
:returns: List of subjects.
|
|
||||||
'''
|
|
||||||
if subject is not None:
|
|
||||||
if not isinstance(subject, list):
|
|
||||||
subject = [subject]
|
|
||||||
if replace or not self._dcelem_subject:
|
|
||||||
self._dcelem_subject = []
|
|
||||||
self._dcelem_subject += subject
|
|
||||||
return self._dcelem_subject
|
|
||||||
|
|
||||||
def dc_title(self, title=None, replace=True):
|
|
||||||
'''Get or set the dc:title which is a name given to the resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-title
|
|
||||||
|
|
||||||
:param title: Title or list of titles.
|
|
||||||
:param replace: Replace alredy set titles (deault: False).
|
|
||||||
:returns: List of titles.
|
|
||||||
'''
|
|
||||||
if title is not None:
|
|
||||||
if not isinstance(title, list):
|
|
||||||
title = [title]
|
|
||||||
if replace or not self._dcelem_title:
|
|
||||||
self._dcelem_title = []
|
|
||||||
self._dcelem_title += title
|
|
||||||
return self._dcelem_title
|
|
||||||
|
|
||||||
def dc_type(self, type=None, replace=False):
|
|
||||||
'''Get or set the dc:type which describes the nature or genre of the
|
|
||||||
resource.
|
|
||||||
|
|
||||||
For more information see:
|
|
||||||
http://dublincore.org/documents/dcmi-terms/#elements-type
|
|
||||||
|
|
||||||
:param type: Type or list of types.
|
|
||||||
:param replace: Replace alredy set types (deault: False).
|
|
||||||
:returns: List of types.
|
|
||||||
'''
|
|
||||||
if type is not None:
|
|
||||||
if not isinstance(type, list):
|
|
||||||
type = [type]
|
|
||||||
if replace or not self._dcelem_type:
|
|
||||||
self._dcelem_type = []
|
|
||||||
self._dcelem_type += type
|
|
||||||
return self._dcelem_type
|
|
||||||
|
|
||||||
|
|
||||||
class DcExtension(DcBaseExtension):
|
|
||||||
'''Dublin Core Elements extension for podcasts.
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
class DcEntryExtension(DcBaseExtension):
|
|
||||||
'''Dublin Core Elements extension for podcasts.
|
|
||||||
'''
|
|
||||||
def extend_atom(self, entry):
|
|
||||||
'''Add dc elements to an atom item. Alters the item itself.
|
|
||||||
|
|
||||||
:param entry: An atom entry element.
|
|
||||||
:returns: The entry element.
|
|
||||||
'''
|
|
||||||
self._extend_xml(entry)
|
|
||||||
return entry
|
|
||||||
|
|
||||||
def extend_rss(self, item):
|
|
||||||
'''Add dc elements to a RSS item. Alters the item itself.
|
|
||||||
|
|
||||||
:param item: A RSS item element.
|
|
||||||
:returns: The item element.
|
|
||||||
'''
|
|
||||||
self._extend_xml(item)
|
|
||||||
return item
|
|
|
@ -1,21 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.ext.geo
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Extends the FeedGenerator to produce Simple GeoRSS feeds.
|
|
||||||
|
|
||||||
:copyright: 2017, Bob Breznak <bob.breznak@gmail.com>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
|
|
||||||
from feedgen.ext.base import BaseExtension
|
|
||||||
|
|
||||||
|
|
||||||
class GeoExtension(BaseExtension):
|
|
||||||
'''FeedGenerator extension for Simple GeoRSS.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def extend_ns(self):
|
|
||||||
return {'georss': 'http://www.georss.org/georss'}
|
|
|
@ -1,329 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.ext.geo_entry
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Extends the FeedGenerator to produce Simple GeoRSS feeds.
|
|
||||||
|
|
||||||
:copyright: 2017, Bob Breznak <bob.breznak@gmail.com>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
import numbers
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from feedgen.ext.base import BaseEntryExtension
|
|
||||||
from feedgen.util import xml_elem
|
|
||||||
|
|
||||||
|
|
||||||
class GeoRSSPolygonInteriorWarning(Warning):
|
|
||||||
"""
|
|
||||||
Simple placeholder for warning about ignored polygon interiors.
|
|
||||||
|
|
||||||
Stores the original geom on a ``geom`` attribute (if required warnings are
|
|
||||||
raised as errors).
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, geom, *args, **kwargs):
|
|
||||||
self.geom = geom
|
|
||||||
super(GeoRSSPolygonInteriorWarning, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return '{:d} interiors of polygon ignored'.format(
|
|
||||||
len(self.geom.__geo_interface__['coordinates']) - 1
|
|
||||||
) # ignore exterior in count
|
|
||||||
|
|
||||||
|
|
||||||
class GeoRSSGeometryError(ValueError):
|
|
||||||
"""
|
|
||||||
Subclass of ValueError for a GeoRSS geometry error
|
|
||||||
|
|
||||||
Only some geometries are supported in Simple GeoRSS, so if not raise an
|
|
||||||
error. Offending geometry is stored on the ``geom`` attribute.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, geom, *args, **kwargs):
|
|
||||||
self.geom = geom
|
|
||||||
super(GeoRSSGeometryError, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
msg = "Geometry of type '{}' not in Point, Linestring or Polygon"
|
|
||||||
return msg.format(
|
|
||||||
self.geom.__geo_interface__['type']
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class GeoEntryExtension(BaseEntryExtension):
|
|
||||||
'''FeedEntry extension for Simple GeoRSS.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
'''Simple GeoRSS tag'''
|
|
||||||
# geometries
|
|
||||||
self.__point = None
|
|
||||||
self.__line = None
|
|
||||||
self.__polygon = None
|
|
||||||
self.__box = None
|
|
||||||
|
|
||||||
# additional properties
|
|
||||||
self.__featuretypetag = None
|
|
||||||
self.__relationshiptag = None
|
|
||||||
self.__featurename = None
|
|
||||||
|
|
||||||
# elevation
|
|
||||||
self.__elev = None
|
|
||||||
self.__floor = None
|
|
||||||
|
|
||||||
# radius
|
|
||||||
self.__radius = None
|
|
||||||
|
|
||||||
def extend_file(self, entry):
|
|
||||||
'''Add additional fields to an RSS item.
|
|
||||||
|
|
||||||
:param feed: The RSS item XML element to use.
|
|
||||||
'''
|
|
||||||
|
|
||||||
GEO_NS = 'http://www.georss.org/georss'
|
|
||||||
|
|
||||||
if self.__point:
|
|
||||||
point = xml_elem('{%s}point' % GEO_NS, entry)
|
|
||||||
point.text = self.__point
|
|
||||||
|
|
||||||
if self.__line:
|
|
||||||
line = xml_elem('{%s}line' % GEO_NS, entry)
|
|
||||||
line.text = self.__line
|
|
||||||
|
|
||||||
if self.__polygon:
|
|
||||||
polygon = xml_elem('{%s}polygon' % GEO_NS, entry)
|
|
||||||
polygon.text = self.__polygon
|
|
||||||
|
|
||||||
if self.__box:
|
|
||||||
box = xml_elem('{%s}box' % GEO_NS, entry)
|
|
||||||
box.text = self.__box
|
|
||||||
|
|
||||||
if self.__featuretypetag:
|
|
||||||
featuretypetag = xml_elem('{%s}featuretypetag' % GEO_NS, entry)
|
|
||||||
featuretypetag.text = self.__featuretypetag
|
|
||||||
|
|
||||||
if self.__relationshiptag:
|
|
||||||
relationshiptag = xml_elem('{%s}relationshiptag' % GEO_NS, entry)
|
|
||||||
relationshiptag.text = self.__relationshiptag
|
|
||||||
|
|
||||||
if self.__featurename:
|
|
||||||
featurename = xml_elem('{%s}featurename' % GEO_NS, entry)
|
|
||||||
featurename.text = self.__featurename
|
|
||||||
|
|
||||||
if self.__elev:
|
|
||||||
elevation = xml_elem('{%s}elev' % GEO_NS, entry)
|
|
||||||
elevation.text = str(self.__elev)
|
|
||||||
|
|
||||||
if self.__floor:
|
|
||||||
floor = xml_elem('{%s}floor' % GEO_NS, entry)
|
|
||||||
floor.text = str(self.__floor)
|
|
||||||
|
|
||||||
if self.__radius:
|
|
||||||
radius = xml_elem('{%s}radius' % GEO_NS, entry)
|
|
||||||
radius.text = str(self.__radius)
|
|
||||||
|
|
||||||
return entry
|
|
||||||
|
|
||||||
def extend_rss(self, entry):
|
|
||||||
return self.extend_file(entry)
|
|
||||||
|
|
||||||
def extend_atom(self, entry):
|
|
||||||
return self.extend_file(entry)
|
|
||||||
|
|
||||||
def point(self, point=None):
|
|
||||||
'''Get or set the georss:point of the entry.
|
|
||||||
|
|
||||||
:param point: The GeoRSS formatted point (i.e. "42.36 -71.05")
|
|
||||||
:returns: The current georss:point of the entry.
|
|
||||||
'''
|
|
||||||
|
|
||||||
if point is not None:
|
|
||||||
self.__point = point
|
|
||||||
|
|
||||||
return self.__point
|
|
||||||
|
|
||||||
def line(self, line=None):
|
|
||||||
'''Get or set the georss:line of the entry
|
|
||||||
|
|
||||||
:param point: The GeoRSS formatted line (i.e. "45.256 -110.45 46.46
|
|
||||||
-109.48 43.84 -109.86")
|
|
||||||
:return: The current georss:line of the entry
|
|
||||||
'''
|
|
||||||
if line is not None:
|
|
||||||
self.__line = line
|
|
||||||
|
|
||||||
return self.__line
|
|
||||||
|
|
||||||
def polygon(self, polygon=None):
|
|
||||||
'''Get or set the georss:polygon of the entry
|
|
||||||
|
|
||||||
:param polygon: The GeoRSS formatted polygon (i.e. "45.256 -110.45
|
|
||||||
46.46 -109.48 43.84 -109.86 45.256 -110.45")
|
|
||||||
:return: The current georss:polygon of the entry
|
|
||||||
'''
|
|
||||||
if polygon is not None:
|
|
||||||
self.__polygon = polygon
|
|
||||||
|
|
||||||
return self.__polygon
|
|
||||||
|
|
||||||
def box(self, box=None):
|
|
||||||
'''
|
|
||||||
Get or set the georss:box of the entry
|
|
||||||
|
|
||||||
:param box: The GeoRSS formatted box (i.e. "42.943 -71.032 43.039
|
|
||||||
-69.856")
|
|
||||||
:return: The current georss:box of the entry
|
|
||||||
'''
|
|
||||||
if box is not None:
|
|
||||||
self.__box = box
|
|
||||||
|
|
||||||
return self.__box
|
|
||||||
|
|
||||||
def featuretypetag(self, featuretypetag=None):
|
|
||||||
'''
|
|
||||||
Get or set the georss:featuretypetag of the entry
|
|
||||||
|
|
||||||
:param featuretypetag: The GeoRSS feaaturertyptag (e.g. "city")
|
|
||||||
:return: The current georss:featurertypetag
|
|
||||||
'''
|
|
||||||
if featuretypetag is not None:
|
|
||||||
self.__featuretypetag = featuretypetag
|
|
||||||
|
|
||||||
return self.__featuretypetag
|
|
||||||
|
|
||||||
def relationshiptag(self, relationshiptag=None):
|
|
||||||
'''
|
|
||||||
Get or set the georss:relationshiptag of the entry
|
|
||||||
|
|
||||||
:param relationshiptag: The GeoRSS relationshiptag (e.g.
|
|
||||||
"is-centred-at")
|
|
||||||
:return: the current georss:relationshiptag
|
|
||||||
'''
|
|
||||||
if relationshiptag is not None:
|
|
||||||
self.__relationshiptag = relationshiptag
|
|
||||||
|
|
||||||
return self.__relationshiptag
|
|
||||||
|
|
||||||
def featurename(self, featurename=None):
|
|
||||||
'''
|
|
||||||
Get or set the georss:featurename of the entry
|
|
||||||
|
|
||||||
:param featuretypetag: The GeoRSS featurename (e.g. "Footscray")
|
|
||||||
:return: the current georss:featurename
|
|
||||||
'''
|
|
||||||
if featurename is not None:
|
|
||||||
self.__featurename = featurename
|
|
||||||
|
|
||||||
return self.__featurename
|
|
||||||
|
|
||||||
def elev(self, elev=None):
|
|
||||||
'''
|
|
||||||
Get or set the georss:elev of the entry
|
|
||||||
|
|
||||||
:param elev: The GeoRSS elevation (e.g. 100.3)
|
|
||||||
:type elev: numbers.Number
|
|
||||||
:return: the current georss:elev
|
|
||||||
'''
|
|
||||||
if elev is not None:
|
|
||||||
if not isinstance(elev, numbers.Number):
|
|
||||||
raise ValueError("elev tag must be numeric: {}".format(elev))
|
|
||||||
|
|
||||||
self.__elev = elev
|
|
||||||
|
|
||||||
return self.__elev
|
|
||||||
|
|
||||||
def floor(self, floor=None):
|
|
||||||
'''
|
|
||||||
Get or set the georss:floor of the entry
|
|
||||||
|
|
||||||
:param floor: The GeoRSS floor (e.g. 4)
|
|
||||||
:type floor: int
|
|
||||||
:return: the current georss:floor
|
|
||||||
'''
|
|
||||||
if floor is not None:
|
|
||||||
if not isinstance(floor, int):
|
|
||||||
raise ValueError("floor tag must be int: {}".format(floor))
|
|
||||||
|
|
||||||
self.__floor = floor
|
|
||||||
|
|
||||||
return self.__floor
|
|
||||||
|
|
||||||
def radius(self, radius=None):
|
|
||||||
'''
|
|
||||||
Get or set the georss:radius of the entry
|
|
||||||
|
|
||||||
:param radius: The GeoRSS radius (e.g. 100.3)
|
|
||||||
:type radius: numbers.Number
|
|
||||||
:return: the current georss:radius
|
|
||||||
'''
|
|
||||||
if radius is not None:
|
|
||||||
if not isinstance(radius, numbers.Number):
|
|
||||||
raise ValueError(
|
|
||||||
"radius tag must be numeric: {}".format(radius)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.__radius = radius
|
|
||||||
|
|
||||||
return self.__radius
|
|
||||||
|
|
||||||
def geom_from_geo_interface(self, geom):
|
|
||||||
'''
|
|
||||||
Generate a georss geometry from some Python object with a
|
|
||||||
``__geo_interface__`` property (see the `geo_interface specification by
|
|
||||||
Sean Gillies`_geointerface )
|
|
||||||
|
|
||||||
Note only a subset of GeoJSON (see `geojson.org`_geojson ) can be
|
|
||||||
easily converted to GeoRSS:
|
|
||||||
|
|
||||||
- Point
|
|
||||||
- LineString
|
|
||||||
- Polygon (if there are holes / donuts in the polygons a warning will
|
|
||||||
be generaated
|
|
||||||
|
|
||||||
Other GeoJson types will raise a ``ValueError``.
|
|
||||||
|
|
||||||
.. note:: The geometry is assumed to be x, y as longitude, latitude in
|
|
||||||
the WGS84 projection.
|
|
||||||
|
|
||||||
.. _geointerface: https://gist.github.com/sgillies/2217756
|
|
||||||
.. _geojson: https://geojson.org/
|
|
||||||
|
|
||||||
:param geom: Geometry object with a __geo_interface__ property
|
|
||||||
:return: the formatted GeoRSS geometry
|
|
||||||
'''
|
|
||||||
geojson = geom.__geo_interface__
|
|
||||||
|
|
||||||
if geojson['type'] not in ('Point', 'LineString', 'Polygon'):
|
|
||||||
raise GeoRSSGeometryError(geom)
|
|
||||||
|
|
||||||
if geojson['type'] == 'Point':
|
|
||||||
|
|
||||||
coords = '{:f} {:f}'.format(
|
|
||||||
geojson['coordinates'][1], # latitude is y
|
|
||||||
geojson['coordinates'][0]
|
|
||||||
)
|
|
||||||
return self.point(coords)
|
|
||||||
|
|
||||||
elif geojson['type'] == 'LineString':
|
|
||||||
|
|
||||||
coords = ' '.join(
|
|
||||||
'{:f} {:f}'.format(vertex[1], vertex[0])
|
|
||||||
for vertex in
|
|
||||||
geojson['coordinates']
|
|
||||||
)
|
|
||||||
return self.line(coords)
|
|
||||||
|
|
||||||
elif geojson['type'] == 'Polygon':
|
|
||||||
|
|
||||||
if len(geojson['coordinates']) > 1:
|
|
||||||
warnings.warn(GeoRSSPolygonInteriorWarning(geom))
|
|
||||||
|
|
||||||
coords = ' '.join(
|
|
||||||
'{:f} {:f}'.format(vertex[1], vertex[0])
|
|
||||||
for vertex in
|
|
||||||
geojson['coordinates'][0]
|
|
||||||
)
|
|
||||||
return self.polygon(coords)
|
|
|
@ -1,183 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.ext.media
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Extends the feedgen to produce media tags.
|
|
||||||
|
|
||||||
:copyright: 2013-2017, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
|
|
||||||
from feedgen.ext.base import BaseEntryExtension, BaseExtension
|
|
||||||
from feedgen.util import ensure_format, xml_elem
|
|
||||||
|
|
||||||
MEDIA_NS = 'http://search.yahoo.com/mrss/'
|
|
||||||
|
|
||||||
|
|
||||||
class MediaExtension(BaseExtension):
|
|
||||||
'''FeedGenerator extension for torrent feeds.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def extend_ns(self):
|
|
||||||
return {'media': MEDIA_NS}
|
|
||||||
|
|
||||||
|
|
||||||
class MediaEntryExtension(BaseEntryExtension):
|
|
||||||
'''FeedEntry extension for media tags.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.__media_content = []
|
|
||||||
self.__media_thumbnail = []
|
|
||||||
|
|
||||||
def extend_atom(self, entry):
|
|
||||||
'''Add additional fields to an RSS item.
|
|
||||||
|
|
||||||
:param feed: The RSS item XML element to use.
|
|
||||||
'''
|
|
||||||
|
|
||||||
groups = {None: entry}
|
|
||||||
for media_content in self.__media_content:
|
|
||||||
# Define current media:group
|
|
||||||
group = groups.get(media_content.get('group'))
|
|
||||||
if group is None:
|
|
||||||
group = xml_elem('{%s}group' % MEDIA_NS, entry)
|
|
||||||
groups[media_content.get('group')] = group
|
|
||||||
# Add content
|
|
||||||
content = xml_elem('{%s}content' % MEDIA_NS, group)
|
|
||||||
for attr in ('url', 'fileSize', 'type', 'medium', 'isDefault',
|
|
||||||
'expression', 'bitrate', 'framerate', 'samplingrate',
|
|
||||||
'channels', 'duration', 'height', 'width', 'lang'):
|
|
||||||
if media_content.get(attr):
|
|
||||||
content.set(attr, media_content[attr])
|
|
||||||
|
|
||||||
for media_thumbnail in self.__media_thumbnail:
|
|
||||||
# Define current media:group
|
|
||||||
group = groups.get(media_thumbnail.get('group'))
|
|
||||||
if group is None:
|
|
||||||
group = xml_elem('{%s}group' % MEDIA_NS, entry)
|
|
||||||
groups[media_thumbnail.get('group')] = group
|
|
||||||
# Add thumbnails
|
|
||||||
thumbnail = xml_elem('{%s}thumbnail' % MEDIA_NS, group)
|
|
||||||
for attr in ('url', 'height', 'width', 'time'):
|
|
||||||
if media_thumbnail.get(attr):
|
|
||||||
thumbnail.set(attr, media_thumbnail[attr])
|
|
||||||
|
|
||||||
return entry
|
|
||||||
|
|
||||||
def extend_rss(self, item):
|
|
||||||
return self.extend_atom(item)
|
|
||||||
|
|
||||||
def content(self, content=None, replace=False, group='default', **kwargs):
|
|
||||||
'''Get or set media:content data.
|
|
||||||
|
|
||||||
This method can be called with:
|
|
||||||
- the fields of a media:content as keyword arguments
|
|
||||||
- the fields of a media:content as a dictionary
|
|
||||||
- a list of dictionaries containing the media:content fields
|
|
||||||
|
|
||||||
<media:content> is a sub-element of either <item> or <media:group>.
|
|
||||||
Media objects that are not the same content should not be included in
|
|
||||||
the same <media:group> element. The sequence of these items implies
|
|
||||||
the order of presentation. While many of the attributes appear to be
|
|
||||||
audio/video specific, this element can be used to publish any type
|
|
||||||
of media. It contains 14 attributes, most of which are optional.
|
|
||||||
|
|
||||||
media:content has the following fields:
|
|
||||||
- *url* should specify the direct URL to the media object.
|
|
||||||
- *fileSize* number of bytes of the media object.
|
|
||||||
- *type* standard MIME type of the object.
|
|
||||||
- *medium* type of object (image | audio | video | document |
|
|
||||||
executable).
|
|
||||||
- *isDefault* determines if this is the default object.
|
|
||||||
- *expression* determines if the object is a sample or the full version
|
|
||||||
of the object, or even if it is a continuous stream (sample | full |
|
|
||||||
nonstop).
|
|
||||||
- *bitrate* kilobits per second rate of media.
|
|
||||||
- *framerate* number of frames per second for the media object.
|
|
||||||
- *samplingrate* number of samples per second taken to create the media
|
|
||||||
object. It is expressed in thousands of samples per second (kHz).
|
|
||||||
- *channels* number of audio channels in the media object.
|
|
||||||
- *duration* number of seconds the media object plays.
|
|
||||||
- *height* height of the media object.
|
|
||||||
- *width* width of the media object.
|
|
||||||
- *lang* is the primary language encapsulated in the media object.
|
|
||||||
|
|
||||||
:param content: Dictionary or list of dictionaries with content data.
|
|
||||||
:param replace: Add or replace old data.
|
|
||||||
:param group: Media group to put this content in.
|
|
||||||
|
|
||||||
:returns: The media content tag.
|
|
||||||
'''
|
|
||||||
# Handle kwargs
|
|
||||||
if content is None and kwargs:
|
|
||||||
content = kwargs
|
|
||||||
# Handle new data
|
|
||||||
if content is not None:
|
|
||||||
# Reset data if we want to replace them
|
|
||||||
if replace or self.__media_content is None:
|
|
||||||
self.__media_content = []
|
|
||||||
# Ensure list
|
|
||||||
if not isinstance(content, list):
|
|
||||||
content = [content]
|
|
||||||
# define media group
|
|
||||||
for c in content:
|
|
||||||
c['group'] = c.get('group', group)
|
|
||||||
self.__media_content += ensure_format(
|
|
||||||
content,
|
|
||||||
set(['url', 'fileSize', 'type', 'medium', 'isDefault',
|
|
||||||
'expression', 'bitrate', 'framerate', 'samplingrate',
|
|
||||||
'channels', 'duration', 'height', 'width', 'lang',
|
|
||||||
'group']),
|
|
||||||
set(['url', 'group']))
|
|
||||||
return self.__media_content
|
|
||||||
|
|
||||||
def thumbnail(self, thumbnail=None, replace=False, group='default',
|
|
||||||
**kwargs):
|
|
||||||
'''Get or set media:thumbnail data.
|
|
||||||
|
|
||||||
This method can be called with:
|
|
||||||
- the fields of a media:content as keyword arguments
|
|
||||||
- the fields of a media:content as a dictionary
|
|
||||||
- a list of dictionaries containing the media:content fields
|
|
||||||
|
|
||||||
Allows particular images to be used as representative images for
|
|
||||||
the media object. If multiple thumbnails are included, and time
|
|
||||||
coding is not at play, it is assumed that the images are in order
|
|
||||||
of importance. It has one required attribute and three optional
|
|
||||||
attributes.
|
|
||||||
|
|
||||||
media:thumbnail has the following fields:
|
|
||||||
- *url* should specify the direct URL to the media object.
|
|
||||||
- *height* height of the media object.
|
|
||||||
- *width* width of the media object.
|
|
||||||
- *time* specifies the time offset in relation to the media object.
|
|
||||||
|
|
||||||
:param thumbnail: Dictionary or list of dictionaries with thumbnail
|
|
||||||
data.
|
|
||||||
:param replace: Add or replace old data.
|
|
||||||
:param group: Media group to put this content in.
|
|
||||||
|
|
||||||
:returns: The media thumbnail tag.
|
|
||||||
'''
|
|
||||||
# Handle kwargs
|
|
||||||
if thumbnail is None and kwargs:
|
|
||||||
thumbnail = kwargs
|
|
||||||
# Handle new data
|
|
||||||
if thumbnail is not None:
|
|
||||||
# Reset data if we want to replace them
|
|
||||||
if replace or self.__media_thumbnail is None:
|
|
||||||
self.__media_thumbnail = []
|
|
||||||
# Ensure list
|
|
||||||
if not isinstance(thumbnail, list):
|
|
||||||
thumbnail = [thumbnail]
|
|
||||||
# Define media group
|
|
||||||
for t in thumbnail:
|
|
||||||
t['group'] = t.get('group', group)
|
|
||||||
self.__media_thumbnail += ensure_format(
|
|
||||||
thumbnail,
|
|
||||||
set(['url', 'height', 'width', 'time', 'group']),
|
|
||||||
set(['url', 'group']))
|
|
||||||
return self.__media_thumbnail
|
|
|
@ -1,355 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.ext.podcast
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Extends the FeedGenerator to produce podcasts.
|
|
||||||
|
|
||||||
:copyright: 2013, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
|
|
||||||
from feedgen.compat import string_types
|
|
||||||
from feedgen.ext.base import BaseExtension
|
|
||||||
from feedgen.util import ensure_format, xml_elem
|
|
||||||
|
|
||||||
|
|
||||||
class PodcastExtension(BaseExtension):
|
|
||||||
'''FeedGenerator extension for podcasts.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# ITunes tags
|
|
||||||
# http://www.apple.com/itunes/podcasts/specs.html#rss
|
|
||||||
self.__itunes_author = None
|
|
||||||
self.__itunes_block = None
|
|
||||||
self.__itunes_category = None
|
|
||||||
self.__itunes_image = None
|
|
||||||
self.__itunes_explicit = None
|
|
||||||
self.__itunes_complete = None
|
|
||||||
self.__itunes_new_feed_url = None
|
|
||||||
self.__itunes_owner = None
|
|
||||||
self.__itunes_subtitle = None
|
|
||||||
self.__itunes_summary = None
|
|
||||||
|
|
||||||
def extend_ns(self):
|
|
||||||
return {'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'}
|
|
||||||
|
|
||||||
def extend_rss(self, rss_feed):
|
|
||||||
'''Extend an RSS feed root with set itunes fields.
|
|
||||||
|
|
||||||
:returns: The feed root element.
|
|
||||||
'''
|
|
||||||
ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
|
|
||||||
channel = rss_feed[0]
|
|
||||||
|
|
||||||
if self.__itunes_author:
|
|
||||||
author = xml_elem('{%s}author' % ITUNES_NS, channel)
|
|
||||||
author.text = self.__itunes_author
|
|
||||||
|
|
||||||
if self.__itunes_block is not None:
|
|
||||||
block = xml_elem('{%s}block' % ITUNES_NS, channel)
|
|
||||||
block.text = 'yes' if self.__itunes_block else 'no'
|
|
||||||
|
|
||||||
for c in self.__itunes_category or []:
|
|
||||||
if not c.get('cat'):
|
|
||||||
continue
|
|
||||||
category = channel.find(
|
|
||||||
'{%s}category[@text="%s"]' % (ITUNES_NS, c.get('cat')))
|
|
||||||
if category is None:
|
|
||||||
category = xml_elem('{%s}category' % ITUNES_NS, channel)
|
|
||||||
category.attrib['text'] = c.get('cat')
|
|
||||||
|
|
||||||
if c.get('sub'):
|
|
||||||
subcategory = xml_elem('{%s}category' % ITUNES_NS, category)
|
|
||||||
subcategory.attrib['text'] = c.get('sub')
|
|
||||||
|
|
||||||
if self.__itunes_image:
|
|
||||||
image = xml_elem('{%s}image' % ITUNES_NS, channel)
|
|
||||||
image.attrib['href'] = self.__itunes_image
|
|
||||||
|
|
||||||
if self.__itunes_explicit in ('yes', 'no', 'clean'):
|
|
||||||
explicit = xml_elem('{%s}explicit' % ITUNES_NS, channel)
|
|
||||||
explicit.text = self.__itunes_explicit
|
|
||||||
|
|
||||||
if self.__itunes_complete in ('yes', 'no'):
|
|
||||||
complete = xml_elem('{%s}complete' % ITUNES_NS, channel)
|
|
||||||
complete.text = self.__itunes_complete
|
|
||||||
|
|
||||||
if self.__itunes_new_feed_url:
|
|
||||||
new_feed_url = xml_elem('{%s}new-feed-url' % ITUNES_NS, channel)
|
|
||||||
new_feed_url.text = self.__itunes_new_feed_url
|
|
||||||
|
|
||||||
if self.__itunes_owner:
|
|
||||||
owner = xml_elem('{%s}owner' % ITUNES_NS, channel)
|
|
||||||
owner_name = xml_elem('{%s}name' % ITUNES_NS, owner)
|
|
||||||
owner_name.text = self.__itunes_owner.get('name')
|
|
||||||
owner_email = xml_elem('{%s}email' % ITUNES_NS, owner)
|
|
||||||
owner_email.text = self.__itunes_owner.get('email')
|
|
||||||
|
|
||||||
if self.__itunes_subtitle:
|
|
||||||
subtitle = xml_elem('{%s}subtitle' % ITUNES_NS, channel)
|
|
||||||
subtitle.text = self.__itunes_subtitle
|
|
||||||
|
|
||||||
if self.__itunes_summary:
|
|
||||||
summary = xml_elem('{%s}summary' % ITUNES_NS, channel)
|
|
||||||
summary.text = self.__itunes_summary
|
|
||||||
|
|
||||||
return rss_feed
|
|
||||||
|
|
||||||
def itunes_author(self, itunes_author=None):
|
|
||||||
'''Get or set the itunes:author. The content of this tag is shown in
|
|
||||||
the Artist column in iTunes. If the tag is not present, iTunes uses the
|
|
||||||
contents of the <author> tag. If <itunes:author> is not present at the
|
|
||||||
feed level, iTunes will use the contents of <managingEditor>.
|
|
||||||
|
|
||||||
:param itunes_author: The author of the podcast.
|
|
||||||
:returns: The author of the podcast.
|
|
||||||
'''
|
|
||||||
if itunes_author is not None:
|
|
||||||
self.__itunes_author = itunes_author
|
|
||||||
return self.__itunes_author
|
|
||||||
|
|
||||||
def itunes_block(self, itunes_block=None):
|
|
||||||
'''Get or set the ITunes block attribute. Use this to prevent the
|
|
||||||
entire podcast from appearing in the iTunes podcast directory.
|
|
||||||
|
|
||||||
:param itunes_block: Block the podcast.
|
|
||||||
:returns: If the podcast is blocked.
|
|
||||||
'''
|
|
||||||
if itunes_block is not None:
|
|
||||||
self.__itunes_block = itunes_block
|
|
||||||
return self.__itunes_block
|
|
||||||
|
|
||||||
def itunes_category(self, itunes_category=None, replace=False, **kwargs):
|
|
||||||
'''Get or set the ITunes category which appears in the category column
|
|
||||||
and in iTunes Store Browser.
|
|
||||||
|
|
||||||
The (sub-)category has to be one from the values defined at
|
|
||||||
http://www.apple.com/itunes/podcasts/specs.html#categories
|
|
||||||
|
|
||||||
This method can be called with:
|
|
||||||
|
|
||||||
- the fields of an itunes_category as keyword arguments
|
|
||||||
- the fields of an itunes_category as a dictionary
|
|
||||||
- a list of dictionaries containing the itunes_category fields
|
|
||||||
|
|
||||||
An itunes_category has the following fields:
|
|
||||||
|
|
||||||
- *cat* name for a category.
|
|
||||||
- *sub* name for a subcategory, child of category
|
|
||||||
|
|
||||||
If a podcast has more than one subcategory from the same category, the
|
|
||||||
category is called more than once.
|
|
||||||
|
|
||||||
Likei the parameter::
|
|
||||||
|
|
||||||
[{"cat":"Arts","sub":"Design"},{"cat":"Arts","sub":"Food"}]
|
|
||||||
|
|
||||||
…would become::
|
|
||||||
|
|
||||||
<itunes:category text="Arts">
|
|
||||||
<itunes:category text="Design"/>
|
|
||||||
<itunes:category text="Food"/>
|
|
||||||
</itunes:category>
|
|
||||||
|
|
||||||
|
|
||||||
:param itunes_category: Dictionary or list of dictionaries with
|
|
||||||
itunes_category data.
|
|
||||||
:param replace: Add or replace old data.
|
|
||||||
:returns: List of itunes_categories as dictionaries.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Important note about deprecated parameter syntax:** Old version of
|
|
||||||
the feedgen did only support one category plus one subcategory which
|
|
||||||
would be passed to this ducntion as first two parameters. For
|
|
||||||
compatibility reasons, this still works but should not be used any may
|
|
||||||
be removed at any time.
|
|
||||||
'''
|
|
||||||
# Ensure old API still works for now. Note that the API is deprecated
|
|
||||||
# and this fallback may be removed at any time.
|
|
||||||
if isinstance(itunes_category, string_types):
|
|
||||||
itunes_category = {'cat': itunes_category}
|
|
||||||
if replace:
|
|
||||||
itunes_category['sub'] = replace
|
|
||||||
replace = True
|
|
||||||
if itunes_category is None and kwargs:
|
|
||||||
itunes_category = kwargs
|
|
||||||
if itunes_category is not None:
|
|
||||||
if replace or self.__itunes_category is None:
|
|
||||||
self.__itunes_category = []
|
|
||||||
self.__itunes_category += ensure_format(itunes_category,
|
|
||||||
set(['cat', 'sub']),
|
|
||||||
set(['cat']))
|
|
||||||
return self.__itunes_category
|
|
||||||
|
|
||||||
def itunes_image(self, itunes_image=None):
|
|
||||||
'''Get or set the image for the podcast. This tag specifies the artwork
|
|
||||||
for your podcast. Put the URL to the image in the href attribute.
|
|
||||||
iTunes prefers square .jpg images that are at least 1400x1400 pixels,
|
|
||||||
which is different from what is specified for the standard RSS image
|
|
||||||
tag. In order for a podcast to be eligible for an iTunes Store feature,
|
|
||||||
the accompanying image must be at least 1400x1400 pixels.
|
|
||||||
|
|
||||||
iTunes supports images in JPEG and PNG formats with an RGB color space
|
|
||||||
(CMYK is not supported). The URL must end in ".jpg" or ".png". If the
|
|
||||||
<itunes:image> tag is not present, iTunes will use the contents of the
|
|
||||||
RSS image tag.
|
|
||||||
|
|
||||||
If you change your podcast’s image, also change the file’s name. iTunes
|
|
||||||
may not change the image if it checks your feed and the image URL is
|
|
||||||
the same. The server hosting your cover art image must allow HTTP head
|
|
||||||
requests for iTS to be able to automatically update your cover art.
|
|
||||||
|
|
||||||
:param itunes_image: Image of the podcast.
|
|
||||||
:returns: Image of the podcast.
|
|
||||||
'''
|
|
||||||
if itunes_image is not None:
|
|
||||||
if itunes_image.endswith('.jpg') or itunes_image.endswith('.png'):
|
|
||||||
self.__itunes_image = itunes_image
|
|
||||||
else:
|
|
||||||
ValueError('Image file must be png or jpg')
|
|
||||||
return self.__itunes_image
|
|
||||||
|
|
||||||
def itunes_explicit(self, itunes_explicit=None):
|
|
||||||
'''Get or the the itunes:explicit value of the podcast. This tag should
|
|
||||||
be used to indicate whether your podcast contains explicit material.
|
|
||||||
The three values for this tag are "yes", "no", and "clean".
|
|
||||||
|
|
||||||
If you populate this tag with "yes", an "explicit" parental advisory
|
|
||||||
graphic will appear next to your podcast artwork on the iTunes Store
|
|
||||||
and in the Name column in iTunes. If the value is "clean", the parental
|
|
||||||
advisory type is considered Clean, meaning that no explicit language or
|
|
||||||
adult content is included anywhere in the episodes, and a "clean"
|
|
||||||
graphic will appear. If the explicit tag is present and has any other
|
|
||||||
value (e.g., "no"), you see no indicator — blank is the default
|
|
||||||
advisory type.
|
|
||||||
|
|
||||||
:param itunes_explicit: If the podcast contains explicit material.
|
|
||||||
:returns: If the podcast contains explicit material.
|
|
||||||
'''
|
|
||||||
if itunes_explicit is not None:
|
|
||||||
if itunes_explicit not in ('', 'yes', 'no', 'clean'):
|
|
||||||
raise ValueError('Invalid value for explicit tag')
|
|
||||||
self.__itunes_explicit = itunes_explicit
|
|
||||||
return self.__itunes_explicit
|
|
||||||
|
|
||||||
def itunes_complete(self, itunes_complete=None):
|
|
||||||
'''Get or set the itunes:complete value of the podcast. This tag can be
|
|
||||||
used to indicate the completion of a podcast.
|
|
||||||
|
|
||||||
If you populate this tag with "yes", you are indicating that no more
|
|
||||||
episodes will be added to the podcast. If the <itunes:complete> tag is
|
|
||||||
present and has any other value (e.g. “no”), it will have no effect on
|
|
||||||
the podcast.
|
|
||||||
|
|
||||||
:param itunes_complete: If the podcast is complete.
|
|
||||||
:returns: If the podcast is complete.
|
|
||||||
'''
|
|
||||||
if itunes_complete is not None:
|
|
||||||
if itunes_complete not in ('yes', 'no', '', True, False):
|
|
||||||
raise ValueError('Invalid value for complete tag')
|
|
||||||
if itunes_complete is True:
|
|
||||||
itunes_complete = 'yes'
|
|
||||||
if itunes_complete is False:
|
|
||||||
itunes_complete = 'no'
|
|
||||||
self.__itunes_complete = itunes_complete
|
|
||||||
return self.__itunes_complete
|
|
||||||
|
|
||||||
def itunes_new_feed_url(self, itunes_new_feed_url=None):
|
|
||||||
'''Get or set the new-feed-url property of the podcast. This tag allows
|
|
||||||
you to change the URL where the podcast feed is located
|
|
||||||
|
|
||||||
After adding the tag to your old feed, you should maintain the old feed
|
|
||||||
for 48 hours before retiring it. At that point, iTunes will have
|
|
||||||
updated the directory with the new feed URL.
|
|
||||||
|
|
||||||
:param itunes_new_feed_url: New feed URL.
|
|
||||||
:returns: New feed URL.
|
|
||||||
'''
|
|
||||||
if itunes_new_feed_url is not None:
|
|
||||||
self.__itunes_new_feed_url = itunes_new_feed_url
|
|
||||||
return self.__itunes_new_feed_url
|
|
||||||
|
|
||||||
def itunes_owner(self, name=None, email=None):
|
|
||||||
'''Get or set the itunes:owner of the podcast. This tag contains
|
|
||||||
information that will be used to contact the owner of the podcast for
|
|
||||||
communication specifically about the podcast. It will not be publicly
|
|
||||||
displayed.
|
|
||||||
|
|
||||||
:param itunes_owner: The owner of the feed.
|
|
||||||
:returns: Data of the owner of the feed.
|
|
||||||
'''
|
|
||||||
if name is not None:
|
|
||||||
if name and email:
|
|
||||||
self.__itunes_owner = {'name': name, 'email': email}
|
|
||||||
elif not name and not email:
|
|
||||||
self.__itunes_owner = None
|
|
||||||
else:
|
|
||||||
raise ValueError('Both name and email have to be set.')
|
|
||||||
return self.__itunes_owner
|
|
||||||
|
|
||||||
def itunes_subtitle(self, itunes_subtitle=None):
|
|
||||||
'''Get or set the itunes:subtitle value for the podcast. The contents of
|
|
||||||
this tag are shown in the Description column in iTunes. The subtitle
|
|
||||||
displays best if it is only a few words long.
|
|
||||||
|
|
||||||
:param itunes_subtitle: Subtitle of the podcast.
|
|
||||||
:returns: Subtitle of the podcast.
|
|
||||||
'''
|
|
||||||
if itunes_subtitle is not None:
|
|
||||||
self.__itunes_subtitle = itunes_subtitle
|
|
||||||
return self.__itunes_subtitle
|
|
||||||
|
|
||||||
def itunes_summary(self, itunes_summary=None):
|
|
||||||
'''Get or set the itunes:summary value for the podcast. The contents of
|
|
||||||
this tag are shown in a separate window that appears when the "circled
|
|
||||||
i" in the Description column is clicked. It also appears on the iTunes
|
|
||||||
page for your podcast. This field can be up to 4000 characters. If
|
|
||||||
`<itunes:summary>` is not included, the contents of the <description>
|
|
||||||
tag are used.
|
|
||||||
|
|
||||||
:param itunes_summary: Summary of the podcast.
|
|
||||||
:returns: Summary of the podcast.
|
|
||||||
'''
|
|
||||||
if itunes_summary is not None:
|
|
||||||
self.__itunes_summary = itunes_summary
|
|
||||||
return self.__itunes_summary
|
|
||||||
|
|
||||||
_itunes_categories = {
|
|
||||||
'Arts': [
|
|
||||||
'Design', 'Fashion & Beauty', 'Food', 'Literature',
|
|
||||||
'Performing Arts', 'Visual Arts'],
|
|
||||||
'Business': [
|
|
||||||
'Business News', 'Careers', 'Investing',
|
|
||||||
'Management & Marketing', 'Shopping'],
|
|
||||||
'Comedy': [],
|
|
||||||
'Education': [
|
|
||||||
'Education', 'Education Technology', 'Higher Education',
|
|
||||||
'K-12', 'Language Courses', 'Training'],
|
|
||||||
'Games & Hobbies': [
|
|
||||||
'Automotive', 'Aviation', 'Hobbies', 'Other Games',
|
|
||||||
'Video Games'],
|
|
||||||
'Government & Organizations': [
|
|
||||||
'Local', 'National', 'Non-Profit', 'Regional'],
|
|
||||||
'Health': [
|
|
||||||
'Alternative Health', 'Fitness & Nutrition', 'Self-Help',
|
|
||||||
'Sexuality'],
|
|
||||||
'Kids & Family': [],
|
|
||||||
'Music': [],
|
|
||||||
'News & Politics': [],
|
|
||||||
'Religion & Spirituality': [
|
|
||||||
'Buddhism', 'Christianity', 'Hinduism', 'Islam', 'Judaism',
|
|
||||||
'Other', 'Spirituality'],
|
|
||||||
'Science & Medicine': [
|
|
||||||
'Medicine', 'Natural Sciences', 'Social Sciences'],
|
|
||||||
'Society & Culture': [
|
|
||||||
'History', 'Personal Journals', 'Philosophy',
|
|
||||||
'Places & Travel'],
|
|
||||||
'Sports & Recreation': [
|
|
||||||
'Amateur', 'College & High School', 'Outdoor', 'Professional'],
|
|
||||||
'Technology': [
|
|
||||||
'Gadgets', 'Tech News', 'Podcasting', 'Software How-To'],
|
|
||||||
'TV & Film': []}
|
|
|
@ -1,244 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.ext.podcast_entry
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Extends the feedgen to produce podcasts.
|
|
||||||
|
|
||||||
:copyright: 2013-2016, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
|
|
||||||
from feedgen.ext.base import BaseEntryExtension
|
|
||||||
from feedgen.util import xml_elem
|
|
||||||
|
|
||||||
|
|
||||||
class PodcastEntryExtension(BaseEntryExtension):
|
|
||||||
'''FeedEntry extension for podcasts.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# ITunes tags
|
|
||||||
# http://www.apple.com/itunes/podcasts/specs.html#rss
|
|
||||||
self.__itunes_author = None
|
|
||||||
self.__itunes_block = None
|
|
||||||
self.__itunes_image = None
|
|
||||||
self.__itunes_duration = None
|
|
||||||
self.__itunes_explicit = None
|
|
||||||
self.__itunes_is_closed_captioned = None
|
|
||||||
self.__itunes_order = None
|
|
||||||
self.__itunes_subtitle = None
|
|
||||||
self.__itunes_summary = None
|
|
||||||
|
|
||||||
def extend_rss(self, entry):
|
|
||||||
'''Add additional fields to an RSS item.
|
|
||||||
|
|
||||||
:param feed: The RSS item XML element to use.
|
|
||||||
'''
|
|
||||||
ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
|
|
||||||
|
|
||||||
if self.__itunes_author:
|
|
||||||
author = xml_elem('{%s}author' % ITUNES_NS, entry)
|
|
||||||
author.text = self.__itunes_author
|
|
||||||
|
|
||||||
if self.__itunes_block is not None:
|
|
||||||
block = xml_elem('{%s}block' % ITUNES_NS, entry)
|
|
||||||
block.text = 'yes' if self.__itunes_block else 'no'
|
|
||||||
|
|
||||||
if self.__itunes_image:
|
|
||||||
image = xml_elem('{%s}image' % ITUNES_NS, entry)
|
|
||||||
image.attrib['href'] = self.__itunes_image
|
|
||||||
|
|
||||||
if self.__itunes_duration:
|
|
||||||
duration = xml_elem('{%s}duration' % ITUNES_NS, entry)
|
|
||||||
duration.text = self.__itunes_duration
|
|
||||||
|
|
||||||
if self.__itunes_explicit in ('yes', 'no', 'clean'):
|
|
||||||
explicit = xml_elem('{%s}explicit' % ITUNES_NS, entry)
|
|
||||||
explicit.text = self.__itunes_explicit
|
|
||||||
|
|
||||||
if self.__itunes_is_closed_captioned is not None:
|
|
||||||
is_closed_captioned = xml_elem(
|
|
||||||
'{%s}isClosedCaptioned' % ITUNES_NS, entry)
|
|
||||||
if self.__itunes_is_closed_captioned:
|
|
||||||
is_closed_captioned.text = 'yes'
|
|
||||||
else:
|
|
||||||
is_closed_captioned.text = 'no'
|
|
||||||
|
|
||||||
if self.__itunes_order is not None and self.__itunes_order >= 0:
|
|
||||||
order = xml_elem('{%s}order' % ITUNES_NS, entry)
|
|
||||||
order.text = str(self.__itunes_order)
|
|
||||||
|
|
||||||
if self.__itunes_subtitle:
|
|
||||||
subtitle = xml_elem('{%s}subtitle' % ITUNES_NS, entry)
|
|
||||||
subtitle.text = self.__itunes_subtitle
|
|
||||||
|
|
||||||
if self.__itunes_summary:
|
|
||||||
summary = xml_elem('{%s}summary' % ITUNES_NS, entry)
|
|
||||||
summary.text = self.__itunes_summary
|
|
||||||
return entry
|
|
||||||
|
|
||||||
def itunes_author(self, itunes_author=None):
|
|
||||||
'''Get or set the itunes:author of the podcast episode. The content of
|
|
||||||
this tag is shown in the Artist column in iTunes. If the tag is not
|
|
||||||
present, iTunes uses the contents of the <author> tag. If
|
|
||||||
<itunes:author> is not present at the feed level, iTunes will use the
|
|
||||||
contents of <managingEditor>.
|
|
||||||
|
|
||||||
:param itunes_author: The author of the podcast.
|
|
||||||
:returns: The author of the podcast.
|
|
||||||
'''
|
|
||||||
if itunes_author is not None:
|
|
||||||
self.__itunes_author = itunes_author
|
|
||||||
return self.__itunes_author
|
|
||||||
|
|
||||||
def itunes_block(self, itunes_block=None):
|
|
||||||
'''Get or set the ITunes block attribute. Use this to prevent episodes
|
|
||||||
from appearing in the iTunes podcast directory.
|
|
||||||
|
|
||||||
:param itunes_block: Block podcast episodes.
|
|
||||||
:returns: If the podcast episode is blocked.
|
|
||||||
'''
|
|
||||||
if itunes_block is not None:
|
|
||||||
self.__itunes_block = itunes_block
|
|
||||||
return self.__itunes_block
|
|
||||||
|
|
||||||
def itunes_image(self, itunes_image=None):
|
|
||||||
'''Get or set the image for the podcast episode. This tag specifies the
|
|
||||||
artwork for your podcast. Put the URL to the image in the href
|
|
||||||
attribute. iTunes prefers square .jpg images that are at least
|
|
||||||
1400x1400 pixels, which is different from what is specified for the
|
|
||||||
standard RSS image tag. In order for a podcast to be eligible for an
|
|
||||||
iTunes Store feature, the accompanying image must be at least 1400x1400
|
|
||||||
pixels.
|
|
||||||
|
|
||||||
iTunes supports images in JPEG and PNG formats with an RGB color space
|
|
||||||
(CMYK is not supported). The URL must end in ".jpg" or ".png". If the
|
|
||||||
<itunes:image> tag is not present, iTunes will use the contents of the
|
|
||||||
RSS image tag.
|
|
||||||
|
|
||||||
If you change your podcast’s image, also change the file’s name. iTunes
|
|
||||||
may not change the image if it checks your feed and the image URL is
|
|
||||||
the same. The server hosting your cover art image must allow HTTP head
|
|
||||||
requests for iTS to be able to automatically update your cover art.
|
|
||||||
|
|
||||||
:param itunes_image: Image of the podcast.
|
|
||||||
:returns: Image of the podcast.
|
|
||||||
'''
|
|
||||||
if itunes_image is not None:
|
|
||||||
if itunes_image.endswith('.jpg') or itunes_image.endswith('.png'):
|
|
||||||
self.__itunes_image = itunes_image
|
|
||||||
else:
|
|
||||||
raise ValueError('Image file must be png or jpg')
|
|
||||||
return self.__itunes_image
|
|
||||||
|
|
||||||
def itunes_duration(self, itunes_duration=None):
|
|
||||||
'''Get or set the duration of the podcast episode. The content of this
|
|
||||||
tag is shown in the Time column in iTunes.
|
|
||||||
|
|
||||||
The tag can be formatted HH:MM:SS, H:MM:SS, MM:SS, or M:SS (H = hours,
|
|
||||||
M = minutes, S = seconds). If an integer is provided (no colon
|
|
||||||
present), the value is assumed to be in seconds. If one colon is
|
|
||||||
present, the number to the left is assumed to be minutes, and the
|
|
||||||
number to the right is assumed to be seconds. If more than two colons
|
|
||||||
are present, the numbers farthest to the right are ignored.
|
|
||||||
|
|
||||||
:param itunes_duration: Duration of the podcast episode.
|
|
||||||
:returns: Duration of the podcast episode.
|
|
||||||
'''
|
|
||||||
if itunes_duration is not None:
|
|
||||||
itunes_duration = str(itunes_duration)
|
|
||||||
if len(itunes_duration.split(':')) > 3 or \
|
|
||||||
itunes_duration.lstrip('0123456789:') != '':
|
|
||||||
raise ValueError('Invalid duration format')
|
|
||||||
self.__itunes_duration = itunes_duration
|
|
||||||
return self.__itunes_duration
|
|
||||||
|
|
||||||
def itunes_explicit(self, itunes_explicit=None):
|
|
||||||
'''Get or the the itunes:explicit value of the podcast episode. This
|
|
||||||
tag should be used to indicate whether your podcast episode contains
|
|
||||||
explicit material. The three values for this tag are "yes", "no", and
|
|
||||||
"clean".
|
|
||||||
|
|
||||||
If you populate this tag with "yes", an "explicit" parental advisory
|
|
||||||
graphic will appear next to your podcast artwork on the iTunes Store
|
|
||||||
and in the Name column in iTunes. If the value is "clean", the parental
|
|
||||||
advisory type is considered Clean, meaning that no explicit language or
|
|
||||||
adult content is included anywhere in the episodes, and a "clean"
|
|
||||||
graphic will appear. If the explicit tag is present and has any other
|
|
||||||
value (e.g., "no"), you see no indicator — blank is the default
|
|
||||||
advisory type.
|
|
||||||
|
|
||||||
:param itunes_explicit: If the podcast episode contains explicit
|
|
||||||
material.
|
|
||||||
:returns: If the podcast episode contains explicit material.
|
|
||||||
'''
|
|
||||||
if itunes_explicit is not None:
|
|
||||||
if itunes_explicit not in ('', 'yes', 'no', 'clean'):
|
|
||||||
raise ValueError('Invalid value for explicit tag')
|
|
||||||
self.__itunes_explicit = itunes_explicit
|
|
||||||
return self.__itunes_explicit
|
|
||||||
|
|
||||||
def itunes_is_closed_captioned(self, itunes_is_closed_captioned=None):
|
|
||||||
'''Get or set the is_closed_captioned value of the podcast episode.
|
|
||||||
This tag should be used if your podcast includes a video episode with
|
|
||||||
embedded closed captioning support. The two values for this tag are
|
|
||||||
"yes" and "no”.
|
|
||||||
|
|
||||||
:param is_closed_captioned: If the episode has closed captioning
|
|
||||||
support.
|
|
||||||
:returns: If the episode has closed captioning support.
|
|
||||||
'''
|
|
||||||
if itunes_is_closed_captioned is not None:
|
|
||||||
self.__itunes_is_closed_captioned = \
|
|
||||||
itunes_is_closed_captioned in ('yes', True)
|
|
||||||
return self.__itunes_is_closed_captioned
|
|
||||||
|
|
||||||
def itunes_order(self, itunes_order=None):
|
|
||||||
'''Get or set the itunes:order value of the podcast episode. This tag
|
|
||||||
can be used to override the default ordering of episodes on the store.
|
|
||||||
|
|
||||||
This tag is used at an <item> level by populating with the number value
|
|
||||||
in which you would like the episode to appear on the store. For
|
|
||||||
example, if you would like an <item> to appear as the first episode in
|
|
||||||
the podcast, you would populate the <itunes:order> tag with “1”. If
|
|
||||||
conflicting order values are present in multiple episodes, the store
|
|
||||||
will use default ordering (pubDate).
|
|
||||||
|
|
||||||
To remove the order from the episode set the order to a value below
|
|
||||||
zero.
|
|
||||||
|
|
||||||
:param itunes_order: The order of the episode.
|
|
||||||
:returns: The order of the episode.
|
|
||||||
'''
|
|
||||||
if itunes_order is not None:
|
|
||||||
self.__itunes_order = int(itunes_order)
|
|
||||||
return self.__itunes_order
|
|
||||||
|
|
||||||
def itunes_subtitle(self, itunes_subtitle=None):
|
|
||||||
'''Get or set the itunes:subtitle value for the podcast episode. The
|
|
||||||
contents of this tag are shown in the Description column in iTunes. The
|
|
||||||
subtitle displays best if it is only a few words long.
|
|
||||||
|
|
||||||
:param itunes_subtitle: Subtitle of the podcast episode.
|
|
||||||
:returns: Subtitle of the podcast episode.
|
|
||||||
'''
|
|
||||||
if itunes_subtitle is not None:
|
|
||||||
self.__itunes_subtitle = itunes_subtitle
|
|
||||||
return self.__itunes_subtitle
|
|
||||||
|
|
||||||
def itunes_summary(self, itunes_summary=None):
|
|
||||||
'''Get or set the itunes:summary value for the podcast episode. The
|
|
||||||
contents of this tag are shown in a separate window that appears when
|
|
||||||
the "circled i" in the Description column is clicked. It also appears
|
|
||||||
on the iTunes page for your podcast. This field can be up to 4000
|
|
||||||
characters. If <itunes:summary> is not included, the contents of the
|
|
||||||
<description> tag are used.
|
|
||||||
|
|
||||||
:param itunes_summary: Summary of the podcast episode.
|
|
||||||
:returns: Summary of the podcast episode.
|
|
||||||
'''
|
|
||||||
if itunes_summary is not None:
|
|
||||||
self.__itunes_summary = itunes_summary
|
|
||||||
return self.__itunes_summary
|
|
|
@ -1,60 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright 2015 Kenichi Sato <ksato9700@gmail.com>
|
|
||||||
#
|
|
||||||
|
|
||||||
'''
|
|
||||||
Extends FeedGenerator to support Syndication module
|
|
||||||
|
|
||||||
See below for details
|
|
||||||
http://web.resource.org/rss/1.0/modules/syndication/
|
|
||||||
'''
|
|
||||||
|
|
||||||
from feedgen.ext.base import BaseExtension
|
|
||||||
from feedgen.util import xml_elem
|
|
||||||
|
|
||||||
SYNDICATION_NS = 'http://purl.org/rss/1.0/modules/syndication/'
|
|
||||||
PERIOD_TYPE = ('hourly', 'daily', 'weekly', 'monthly', 'yearly')
|
|
||||||
|
|
||||||
|
|
||||||
def _set_value(channel, name, value):
|
|
||||||
if value:
|
|
||||||
newelem = xml_elem('{%s}' % SYNDICATION_NS + name, channel)
|
|
||||||
newelem.text = value
|
|
||||||
|
|
||||||
|
|
||||||
class SyndicationExtension(BaseExtension):
|
|
||||||
def __init__(self):
|
|
||||||
self._update_period = None
|
|
||||||
self._update_freq = None
|
|
||||||
self._update_base = None
|
|
||||||
|
|
||||||
def extend_ns(self):
|
|
||||||
return {'sy': SYNDICATION_NS}
|
|
||||||
|
|
||||||
def extend_rss(self, rss_feed):
|
|
||||||
channel = rss_feed[0]
|
|
||||||
_set_value(channel, 'UpdatePeriod', self._update_period)
|
|
||||||
_set_value(channel, 'UpdateFrequency', str(self._update_freq))
|
|
||||||
_set_value(channel, 'UpdateBase', self._update_base)
|
|
||||||
|
|
||||||
def update_period(self, value):
|
|
||||||
if value not in PERIOD_TYPE:
|
|
||||||
raise ValueError('Invalid update period value')
|
|
||||||
self._update_period = value
|
|
||||||
return self._update_period
|
|
||||||
|
|
||||||
def update_frequency(self, value):
|
|
||||||
if type(value) is not int or value <= 0:
|
|
||||||
raise ValueError('Invalid update frequency value')
|
|
||||||
self._update_freq = value
|
|
||||||
return self._update_freq
|
|
||||||
|
|
||||||
def update_base(self, value):
|
|
||||||
# the value should be in W3CDTF format
|
|
||||||
self._update_base = value
|
|
||||||
return self._update_base
|
|
||||||
|
|
||||||
|
|
||||||
class SyndicationEntryExtension(BaseExtension):
|
|
||||||
pass
|
|
|
@ -1,126 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.ext.torrent
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Extends the FeedGenerator to produce torrent feeds.
|
|
||||||
|
|
||||||
:copyright: 2016, Raspbeguy <raspbeguy@hashtagueule.fr>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
|
|
||||||
from feedgen.ext.base import BaseEntryExtension, BaseExtension
|
|
||||||
from feedgen.util import xml_elem
|
|
||||||
|
|
||||||
TORRENT_NS = 'http://xmlns.ezrss.it/0.1/dtd/'
|
|
||||||
|
|
||||||
|
|
||||||
class TorrentExtension(BaseExtension):
|
|
||||||
'''FeedGenerator extension for torrent feeds.
|
|
||||||
'''
|
|
||||||
def extend_ns(self):
|
|
||||||
return {'torrent': TORRENT_NS}
|
|
||||||
|
|
||||||
|
|
||||||
class TorrentEntryExtension(BaseEntryExtension):
|
|
||||||
'''FeedEntry extension for torrent feeds
|
|
||||||
'''
|
|
||||||
def __init__(self):
|
|
||||||
self.__torrent_filename = None
|
|
||||||
self.__torrent_infohash = None
|
|
||||||
self.__torrent_contentlength = None
|
|
||||||
self.__torrent_seeds = None
|
|
||||||
self.__torrent_peers = None
|
|
||||||
self.__torrent_verified = None
|
|
||||||
|
|
||||||
def extend_rss(self, entry):
|
|
||||||
'''Add additional fields to an RSS item.
|
|
||||||
|
|
||||||
:param feed: The RSS item XML element to use.
|
|
||||||
'''
|
|
||||||
if self.__torrent_filename:
|
|
||||||
filename = xml_elem('{%s}filename' % TORRENT_NS, entry)
|
|
||||||
filename.text = self.__torrent_filename
|
|
||||||
|
|
||||||
if self.__torrent_contentlength:
|
|
||||||
contentlength = xml_elem('{%s}contentlength' % TORRENT_NS, entry)
|
|
||||||
contentlength.text = self.__torrent_contentlength
|
|
||||||
|
|
||||||
if self.__torrent_infohash:
|
|
||||||
infohash = xml_elem('{%s}infohash' % TORRENT_NS, entry)
|
|
||||||
infohash.text = self.__torrent_infohash
|
|
||||||
magnet = xml_elem('{%s}magneturi' % TORRENT_NS, entry)
|
|
||||||
magnet.text = 'magnet:?xt=urn:btih:' + self.__torrent_infohash
|
|
||||||
|
|
||||||
if self.__torrent_seeds:
|
|
||||||
seeds = xml_elem('{%s}seed' % TORRENT_NS, entry)
|
|
||||||
seeds.text = self.__torrent_seeds
|
|
||||||
|
|
||||||
if self.__torrent_peers:
|
|
||||||
peers = xml_elem('{%s}peers' % TORRENT_NS, entry)
|
|
||||||
peers.text = self.__torrent_peers
|
|
||||||
|
|
||||||
if self.__torrent_verified:
|
|
||||||
verified = xml_elem('{%s}verified' % TORRENT_NS, entry)
|
|
||||||
verified.text = self.__torrent_verified
|
|
||||||
|
|
||||||
def filename(self, torrent_filename=None):
|
|
||||||
'''Get or set the name of the torrent file.
|
|
||||||
|
|
||||||
:param torrent_filename: The name of the torrent file.
|
|
||||||
:returns: The name of the torrent file.
|
|
||||||
'''
|
|
||||||
if torrent_filename is not None:
|
|
||||||
self.__torrent_filename = torrent_filename
|
|
||||||
return self.__torrent_filename
|
|
||||||
|
|
||||||
def infohash(self, torrent_infohash=None):
|
|
||||||
'''Get or set the hash of the target file.
|
|
||||||
|
|
||||||
:param torrent_infohash: The target file hash.
|
|
||||||
:returns: The target hash file.
|
|
||||||
'''
|
|
||||||
if torrent_infohash is not None:
|
|
||||||
self.__torrent_infohash = torrent_infohash
|
|
||||||
return self.__torrent_infohash
|
|
||||||
|
|
||||||
def contentlength(self, torrent_contentlength=None):
|
|
||||||
'''Get or set the size of the target file.
|
|
||||||
|
|
||||||
:param torrent_contentlength: The target file size.
|
|
||||||
:returns: The target file size.
|
|
||||||
'''
|
|
||||||
if torrent_contentlength is not None:
|
|
||||||
self.__torrent_contentlength = torrent_contentlength
|
|
||||||
return self.__torrent_contentlength
|
|
||||||
|
|
||||||
def seeds(self, torrent_seeds=None):
|
|
||||||
'''Get or set the number of seeds.
|
|
||||||
|
|
||||||
:param torrent_seeds: The seeds number.
|
|
||||||
:returns: The seeds number.
|
|
||||||
'''
|
|
||||||
if torrent_seeds is not None:
|
|
||||||
self.__torrent_seeds = torrent_seeds
|
|
||||||
return self.__torrent_seeds
|
|
||||||
|
|
||||||
def peers(self, torrent_peers=None):
|
|
||||||
'''Get or set the number od peers
|
|
||||||
|
|
||||||
:param torrent_infohash: The peers number.
|
|
||||||
:returns: The peers number.
|
|
||||||
'''
|
|
||||||
if torrent_peers is not None:
|
|
||||||
self.__torrent_peers = torrent_peers
|
|
||||||
return self.__torrent_peers
|
|
||||||
|
|
||||||
def verified(self, torrent_verified=None):
|
|
||||||
'''Get or set the number of verified peers.
|
|
||||||
|
|
||||||
:param torrent_infohash: The verified peers number.
|
|
||||||
:returns: The verified peers number.
|
|
||||||
'''
|
|
||||||
if torrent_verified is not None:
|
|
||||||
self.__torrent_verified = torrent_verified
|
|
||||||
return self.__torrent_verified
|
|
1169
feedgen/feed.py
|
@ -1,96 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.util
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This file contains helper functions for the feed generator module.
|
|
||||||
|
|
||||||
:copyright: 2013, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
'''
|
|
||||||
import locale
|
|
||||||
import sys
|
|
||||||
import lxml # nosec - we configure a safe parser below
|
|
||||||
|
|
||||||
# Configure a safe parser which does not allow XML entity expansion
|
|
||||||
parser = lxml.etree.XMLParser(
|
|
||||||
attribute_defaults=False,
|
|
||||||
dtd_validation=False,
|
|
||||||
load_dtd=False,
|
|
||||||
no_network=True,
|
|
||||||
recover=False,
|
|
||||||
remove_pis=True,
|
|
||||||
resolve_entities=False,
|
|
||||||
huge_tree=False)
|
|
||||||
|
|
||||||
|
|
||||||
def xml_fromstring(xmlstring):
|
|
||||||
return lxml.etree.fromstring(xmlstring, parser) # nosec - safe parser
|
|
||||||
|
|
||||||
|
|
||||||
def xml_elem(name, parent=None, **kwargs):
|
|
||||||
if parent is not None:
|
|
||||||
return lxml.etree.SubElement(parent, name, **kwargs)
|
|
||||||
return lxml.etree.Element(name, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_format(val, allowed, required, allowed_values=None, defaults=None):
|
|
||||||
'''Takes a dictionary or a list of dictionaries and check if all keys are in
|
|
||||||
the set of allowed keys, if all required keys are present and if the values
|
|
||||||
of a specific key are ok.
|
|
||||||
|
|
||||||
:param val: Dictionaries to check.
|
|
||||||
:param allowed: Set of allowed keys.
|
|
||||||
:param required: Set of required keys.
|
|
||||||
:param allowed_values: Dictionary with keys and sets of their allowed
|
|
||||||
values.
|
|
||||||
:param defaults: Dictionary with default values.
|
|
||||||
:returns: List of checked dictionaries.
|
|
||||||
'''
|
|
||||||
if not val:
|
|
||||||
return []
|
|
||||||
if allowed_values is None:
|
|
||||||
allowed_values = {}
|
|
||||||
if defaults is None:
|
|
||||||
defaults = {}
|
|
||||||
# Make shure that we have a list of dicts. Even if there is only one.
|
|
||||||
if not isinstance(val, list):
|
|
||||||
val = [val]
|
|
||||||
for elem in val:
|
|
||||||
if not isinstance(elem, dict):
|
|
||||||
raise ValueError('Invalid data (value is no dictionary)')
|
|
||||||
# Set default values
|
|
||||||
|
|
||||||
version = sys.version_info[0]
|
|
||||||
|
|
||||||
if version == 2:
|
|
||||||
items = defaults.iteritems()
|
|
||||||
else:
|
|
||||||
items = defaults.items()
|
|
||||||
|
|
||||||
for k, v in items:
|
|
||||||
elem[k] = elem.get(k, v)
|
|
||||||
if not set(elem.keys()) <= allowed:
|
|
||||||
raise ValueError('Data contains invalid keys')
|
|
||||||
if not set(elem.keys()) >= required:
|
|
||||||
raise ValueError('Data contains not all required keys')
|
|
||||||
|
|
||||||
if version == 2:
|
|
||||||
values = allowed_values.iteritems()
|
|
||||||
else:
|
|
||||||
values = allowed_values.items()
|
|
||||||
|
|
||||||
for k, v in values:
|
|
||||||
if elem.get(k) and not elem[k] in v:
|
|
||||||
raise ValueError('Invalid value for %s' % k)
|
|
||||||
return val
|
|
||||||
|
|
||||||
|
|
||||||
def formatRFC2822(date):
|
|
||||||
'''Make sure the locale setting do not interfere with the time format.
|
|
||||||
'''
|
|
||||||
old = locale.setlocale(locale.LC_ALL)
|
|
||||||
locale.setlocale(locale.LC_ALL, 'C')
|
|
||||||
date = date.strftime('%a, %d %b %Y %H:%M:%S %z')
|
|
||||||
locale.setlocale(locale.LC_ALL, old)
|
|
||||||
return date
|
|
|
@ -1,25 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
|
||||||
feedgen.version
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
:copyright: 2013-2018, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
|
|
||||||
:license: FreeBSD and LGPL, see license.* for more details.
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
'Version of python-feedgen represented as tuple'
|
|
||||||
version = (0, 9, 0)
|
|
||||||
|
|
||||||
|
|
||||||
'Version of python-feedgen represented as string'
|
|
||||||
version_str = '.'.join([str(x) for x in version])
|
|
||||||
|
|
||||||
version_major = version[:1]
|
|
||||||
version_minor = version[:2]
|
|
||||||
version_full = version
|
|
||||||
|
|
||||||
version_major_str = '.'.join([str(x) for x in version_major])
|
|
||||||
version_minor_str = '.'.join([str(x) for x in version_minor])
|
|
||||||
version_full_str = '.'.join([str(x) for x in version_full])
|
|
518
genindex.html
Normal file
|
@ -0,0 +1,518 @@
|
||||||
|
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>Index — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="#" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>Index</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h1 id="index">Index</h1>
|
||||||
|
|
||||||
|
<div class="genindex-jumpbox">
|
||||||
|
<a href="#A"><strong>A</strong></a>
|
||||||
|
| <a href="#B"><strong>B</strong></a>
|
||||||
|
| <a href="#C"><strong>C</strong></a>
|
||||||
|
| <a href="#D"><strong>D</strong></a>
|
||||||
|
| <a href="#E"><strong>E</strong></a>
|
||||||
|
| <a href="#F"><strong>F</strong></a>
|
||||||
|
| <a href="#G"><strong>G</strong></a>
|
||||||
|
| <a href="#I"><strong>I</strong></a>
|
||||||
|
| <a href="#L"><strong>L</strong></a>
|
||||||
|
| <a href="#M"><strong>M</strong></a>
|
||||||
|
| <a href="#P"><strong>P</strong></a>
|
||||||
|
| <a href="#R"><strong>R</strong></a>
|
||||||
|
| <a href="#S"><strong>S</strong></a>
|
||||||
|
| <a href="#T"><strong>T</strong></a>
|
||||||
|
| <a href="#U"><strong>U</strong></a>
|
||||||
|
| <a href="#V"><strong>V</strong></a>
|
||||||
|
| <a href="#W"><strong>W</strong></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<h2 id="A">A</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.add_entry">add_entry() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.add_item">add_item() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.atom_entry">atom_entry() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.atom_file">atom_file() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.atom_str">atom_str() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.author">author() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.author">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="B">B</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.base.html#feedgen.ext.base.BaseEntryExtension">BaseEntryExtension (class in feedgen.ext.base)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.base.html#feedgen.ext.base.BaseExtension">BaseExtension (class in feedgen.ext.base)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="C">C</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.category">category() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.category">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.cloud">cloud() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.comments">comments() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.content">content() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentEntryExtension.contentlength">contentlength() (feedgen.ext.torrent.TorrentEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.contributor">contributor() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.contributor">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.copyright">copyright() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="D">D</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_contributor">dc_contributor() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_coverage">dc_coverage() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_creator">dc_creator() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_date">dc_date() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_description">dc_description() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_format">dc_format() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_identifier">dc_identifier() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_language">dc_language() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_publisher">dc_publisher() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_relation">dc_relation() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_rights">dc_rights() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_source">dc_source() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_subject">dc_subject() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_title">dc_title() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.dc_type">dc_type() (feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension">DcBaseExtension (class in feedgen.ext.dc)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcEntryExtension">DcEntryExtension (class in feedgen.ext.dc)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcExtension">DcExtension (class in feedgen.ext.dc)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.description">description() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.description">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.docs">docs() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="E">E</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.enclosure">enclosure() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.util.html#feedgen.util.ensure_format">ensure_format() (in module feedgen.util)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.entry">entry() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.base.html#feedgen.ext.base.BaseExtension.extend_atom">extend_atom() (feedgen.ext.base.BaseExtension method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.extend_atom">(feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcEntryExtension.extend_atom">(feedgen.ext.dc.DcEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="ext/api.ext.base.html#feedgen.ext.base.BaseExtension.extend_ns">extend_ns() (feedgen.ext.base.BaseExtension method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.extend_ns">(feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.extend_ns">(feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentExtension.extend_ns">(feedgen.ext.torrent.TorrentExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.base.html#feedgen.ext.base.BaseExtension.extend_rss">extend_rss() (feedgen.ext.base.BaseExtension method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcBaseExtension.extend_rss">(feedgen.ext.dc.DcBaseExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#feedgen.ext.dc.DcEntryExtension.extend_rss">(feedgen.ext.dc.DcEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.extend_rss">(feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.extend_rss">(feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentEntryExtension.extend_rss">(feedgen.ext.torrent.TorrentEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="F">F</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry">FeedEntry (class in feedgen.entry)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.html#module-feedgen">feedgen (module)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#module-feedgen.entry">feedgen.entry (module)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.base.html#module-feedgen.ext.base">feedgen.ext.base (module)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.dc.html#module-feedgen.ext.dc">feedgen.ext.dc (module)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#module-feedgen.ext.podcast">feedgen.ext.podcast (module)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#module-feedgen.ext.podcast_entry">feedgen.ext.podcast_entry (module)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#module-feedgen.ext.torrent">feedgen.ext.torrent (module)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#module-feedgen.feed">feedgen.feed (module)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.util.html#module-feedgen.util">feedgen.util (module)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator">FeedGenerator (class in feedgen.feed)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentEntryExtension.filename">filename() (feedgen.ext.torrent.TorrentEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.util.html#feedgen.util.formatRFC2822">formatRFC2822() (in module feedgen.util)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="G">G</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.generator">generator() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.guid">guid() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="I">I</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.icon">icon() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.id">id() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.id">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.image">image() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentEntryExtension.infohash">infohash() (feedgen.ext.torrent.TorrentEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.item">item() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_author">itunes_author() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_author">(feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_block">itunes_block() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_block">(feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_category">itunes_category() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_complete">itunes_complete() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_duration">itunes_duration() (feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_explicit">itunes_explicit() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_explicit">(feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_image">itunes_image() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_image">(feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_is_closed_captioned">itunes_is_closed_captioned() (feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_new_feed_url">itunes_new_feed_url() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_order">itunes_order() (feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_owner">itunes_owner() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_subtitle">itunes_subtitle() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_subtitle">(feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension.itunes_summary">itunes_summary() (feedgen.ext.podcast.PodcastExtension method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension.itunes_summary">(feedgen.ext.podcast_entry.PodcastEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="L">L</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.language">language() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.lastBuildDate">lastBuildDate() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.link">link() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.link">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.load_extension">load_extension() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.load_extension">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.logo">logo() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="M">M</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.managingEditor">managingEditor() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="P">P</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentEntryExtension.peers">peers() (feedgen.ext.torrent.TorrentEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast_entry.html#feedgen.ext.podcast_entry.PodcastEntryExtension">PodcastEntryExtension (class in feedgen.ext.podcast_entry)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.podcast.html#feedgen.ext.podcast.PodcastExtension">PodcastExtension (class in feedgen.ext.podcast)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.pubDate">pubDate() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.pubdate">pubdate() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.pubDate">pubDate() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.published">published() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="R">R</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.rating">rating() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.register_extension">register_extension() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.register_extension">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.remove_entry">remove_entry() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.remove_item">remove_item() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.rights">rights() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.rights">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.rss_entry">rss_entry() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.rss_file">rss_file() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.rss_str">rss_str() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="S">S</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentEntryExtension.seeds">seeds() (feedgen.ext.torrent.TorrentEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.skipDays">skipDays() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.skipHours">skipHours() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.source">source() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.subtitle">subtitle() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.summary">summary() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="T">T</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.textInput">textInput() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.title">title() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.title">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentEntryExtension">TorrentEntryExtension (class in feedgen.ext.torrent)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentExtension">TorrentExtension (class in feedgen.ext.torrent)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.ttl">ttl() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.ttl">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="U">U</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.entry.html#feedgen.entry.FeedEntry.updated">updated() (feedgen.entry.FeedEntry method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.updated">(feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="V">V</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="ext/api.ext.torrent.html#feedgen.ext.torrent.TorrentEntryExtension.verified">verified() (feedgen.ext.torrent.TorrentEntryExtension method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="W">W</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="api.feed.html#feedgen.feed.FeedGenerator.webMaster">webMaster() (feedgen.feed.FeedGenerator method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
246
index.html
Normal file
|
@ -0,0 +1,246 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>Feedgenerator — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="API Documentation" href="api.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="#">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>Feedgenerator</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a class="uplink" href="#">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.html">API Documentation</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="contents topic" id="table-of-contents">
|
||||||
|
<p class="topic-title first">Table of Contents</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><a class="reference internal" href="#feedgenerator" id="id1">Feedgenerator</a><ul>
|
||||||
|
<li><a class="reference internal" href="#installation" id="id2">Installation</a></li>
|
||||||
|
<li><a class="reference internal" href="#create-a-feed" id="id3">Create a Feed</a></li>
|
||||||
|
<li><a class="reference internal" href="#generate-the-feed" id="id4">Generate the Feed</a></li>
|
||||||
|
<li><a class="reference internal" href="#add-feed-entries" id="id5">Add Feed Entries</a></li>
|
||||||
|
<li><a class="reference internal" href="#extensions" id="id6">Extensions</a></li>
|
||||||
|
<li><a class="reference internal" href="#testing-the-generator" id="id7">Testing the Generator</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a class="reference internal" href="#module-documentation" id="id8">Module documentation</a></li>
|
||||||
|
<li><a class="reference internal" href="#indices-and-tables" id="id9">Indices and tables</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="feedgenerator">
|
||||||
|
<h1><a class="toc-backref" href="#id1">Feedgenerator</a><a class="headerlink" href="#feedgenerator" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<a class="reference external image-reference" href="https://travis-ci.org/lkiesow/python-feedgen"><img alt="Build Status" src="https://travis-ci.org/lkiesow/python-feedgen.svg?branch=master" /></a>
|
||||||
|
<a class="reference external image-reference" href="https://coveralls.io/github/lkiesow/python-feedgen?branch=master"><img alt="Test Coverage Status" src="https://coveralls.io/repos/github/lkiesow/python-feedgen/badge.svg?branch=master" /></a>
|
||||||
|
<p>This module can be used to generate web feeds in both ATOM and RSS format. It
|
||||||
|
has support for extensions. Included is for example an extension to produce
|
||||||
|
Podcasts.</p>
|
||||||
|
<p>It is licensed under the terms of both, the FreeBSD license and the LGPLv3+.
|
||||||
|
Choose the one which is more convenient for you. For more details have a look
|
||||||
|
at license.bsd and license.lgpl.</p>
|
||||||
|
<p>More details about the project:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>Repository: <a class="reference external" href="https://github.com/lkiesow/python-feedgen">https://github.com/lkiesow/python-feedgen</a></li>
|
||||||
|
<li>Documentation: <a class="reference external" href="https://lkiesow.github.io/python-feedgen/">https://lkiesow.github.io/python-feedgen/</a></li>
|
||||||
|
<li>Python Package Index: <a class="reference external" href="https://pypi.python.org/pypi/feedgen/">https://pypi.python.org/pypi/feedgen/</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="section" id="installation">
|
||||||
|
<h2><a class="toc-backref" href="#id2">Installation</a><a class="headerlink" href="#installation" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p><strong>Prebuild packages</strong></p>
|
||||||
|
<p>If your distribution includes this project as package, like Fedora Linux does,
|
||||||
|
you can simply use your package manager to install the package. For example:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dnf install python3-feedgen
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p><strong>Using pip</strong></p>
|
||||||
|
<p>You can also use pip to install the feedgen module. Simply run:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ pip install feedgen
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="create-a-feed">
|
||||||
|
<h2><a class="toc-backref" href="#id3">Create a Feed</a><a class="headerlink" href="#create-a-feed" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>To create a feed simply instantiate the FeedGenerator class and insert some
|
||||||
|
data:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">feedgen.feed</span> <span class="k">import</span> <span class="n">FeedGenerator</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span> <span class="o">=</span> <span class="n">FeedGenerator</span><span class="p">()</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">id</span><span class="p">(</span><span class="s1">'http://lernfunk.de/media/654321'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'Some Testfeed'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">author</span><span class="p">(</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span><span class="s1">'John Doe'</span><span class="p">,</span><span class="s1">'email'</span><span class="p">:</span><span class="s1">'john@example.de'</span><span class="p">}</span> <span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">link</span><span class="p">(</span> <span class="n">href</span><span class="o">=</span><span class="s1">'http://example.com'</span><span class="p">,</span> <span class="n">rel</span><span class="o">=</span><span class="s1">'alternate'</span> <span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">logo</span><span class="p">(</span><span class="s1">'http://ex.com/logo.jpg'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">subtitle</span><span class="p">(</span><span class="s1">'This is a cool feed!'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">link</span><span class="p">(</span> <span class="n">href</span><span class="o">=</span><span class="s1">'http://larskiesow.de/test.atom'</span><span class="p">,</span> <span class="n">rel</span><span class="o">=</span><span class="s1">'self'</span> <span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">language</span><span class="p">(</span><span class="s1">'en'</span><span class="p">)</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>Note that for the methods which set fields that can occur more than once in a
|
||||||
|
feed you can use all of the following ways to provide data:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>Provide the data for that element as keyword arguments</li>
|
||||||
|
<li>Provide the data for that element as dictionary</li>
|
||||||
|
<li>Provide a list of dictionaries with the data for several elements</li>
|
||||||
|
</ul>
|
||||||
|
<p>Example:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">contributor</span><span class="p">(</span> <span class="n">name</span><span class="o">=</span><span class="s1">'John Doe'</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s1">'jdoe@example.com'</span> <span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">contributor</span><span class="p">({</span><span class="s1">'name'</span><span class="p">:</span><span class="s1">'John Doe'</span><span class="p">,</span> <span class="s1">'email'</span><span class="p">:</span><span class="s1">'jdoe@example.com'</span><span class="p">})</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">contributor</span><span class="p">([{</span><span class="s1">'name'</span><span class="p">:</span><span class="s1">'John Doe'</span><span class="p">,</span> <span class="s1">'email'</span><span class="p">:</span><span class="s1">'jdoe@example.com'</span><span class="p">},</span> <span class="o">...</span><span class="p">])</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="generate-the-feed">
|
||||||
|
<h2><a class="toc-backref" href="#id4">Generate the Feed</a><a class="headerlink" href="#generate-the-feed" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>After that you can generate both RSS or ATOM by calling the respective method:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">atomfeed</span> <span class="o">=</span> <span class="n">fg</span><span class="o">.</span><span class="n">atom_str</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># Get the ATOM feed as string</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">rssfeed</span> <span class="o">=</span> <span class="n">fg</span><span class="o">.</span><span class="n">rss_str</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># Get the RSS feed as string</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">atom_file</span><span class="p">(</span><span class="s1">'atom.xml'</span><span class="p">)</span> <span class="c1"># Write the ATOM feed to a file</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">rss_file</span><span class="p">(</span><span class="s1">'rss.xml'</span><span class="p">)</span> <span class="c1"># Write the RSS feed to a file</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="add-feed-entries">
|
||||||
|
<h2><a class="toc-backref" href="#id5">Add Feed Entries</a><a class="headerlink" href="#add-feed-entries" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>To add entries (items) to a feed you need to create new FeedEntry objects and
|
||||||
|
append them to the list of entries in the FeedGenerator. The most convenient
|
||||||
|
way to go is to use the FeedGenerator itself for the instantiation of the
|
||||||
|
FeedEntry object:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">fe</span> <span class="o">=</span> <span class="n">fg</span><span class="o">.</span><span class="n">add_entry</span><span class="p">()</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span><span class="o">.</span><span class="n">id</span><span class="p">(</span><span class="s1">'http://lernfunk.de/media/654321/1'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'The First Episode'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span><span class="o">.</span><span class="n">link</span><span class="p">(</span><span class="n">href</span><span class="o">=</span><span class="s2">"http://lernfunk.de/feed"</span><span class="p">)</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>The FeedGenerators method <cite>add_entry(…)</cite> without argument provides will
|
||||||
|
automatically generate a new FeedEntry object, append it to the feeds internal
|
||||||
|
list of entries and return it, so that additional data can be added.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="extensions">
|
||||||
|
<h2><a class="toc-backref" href="#id6">Extensions</a><a class="headerlink" href="#extensions" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>The FeedGenerator supports extension to include additional data into the XML
|
||||||
|
structure of the feeds. Extensions can be loaded like this:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">load_extension</span><span class="p">(</span><span class="s1">'someext'</span><span class="p">,</span> <span class="n">atom</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">rss</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>This will try to load the extension “someext” from the file <cite>ext/someext.py</cite>.
|
||||||
|
It is required that <cite>someext.py</cite> contains a class named “SomextExtension” which
|
||||||
|
is required to have at least the two methods <cite>extend_rss(…)</cite> and
|
||||||
|
<cite>extend_atom(…)</cite>. Although not required, it is strongly suggested to use
|
||||||
|
<cite>BaseExtension</cite> from <cite>ext/base.py</cite> as superclass.</p>
|
||||||
|
<p><cite>load_extension(‘someext’, …)</cite> will also try to load a class named
|
||||||
|
“SomextEntryExtension” for every entry of the feed. This class can be located
|
||||||
|
either in the same file as SomextExtension or in <cite>ext/someext_entry.py</cite> which
|
||||||
|
is suggested especially for large extensions.</p>
|
||||||
|
<p>The parameters <cite>atom</cite> and <cite>rss</cite> control if the extension is used for ATOM and
|
||||||
|
RSS feeds, respectively. The default value for both parameters is <cite>true</cite>
|
||||||
|
meaning the extension is used for both kinds of feeds.</p>
|
||||||
|
<p><strong>Example: Producing a Podcast</strong></p>
|
||||||
|
<p>One extension already provided is the podcast extension. A podcast is an RSS
|
||||||
|
feed with some additional elements for ITunes.</p>
|
||||||
|
<p>To produce a podcast simply load the <cite>podcast</cite> extension:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">feedgen.feed</span> <span class="k">import</span> <span class="n">FeedGenerator</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span> <span class="o">=</span> <span class="n">FeedGenerator</span><span class="p">()</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">load_extension</span><span class="p">(</span><span class="s1">'podcast'</span><span class="p">)</span>
|
||||||
|
<span class="gp">...</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">podcast</span><span class="o">.</span><span class="n">itunes_category</span><span class="p">(</span><span class="s1">'Technology'</span><span class="p">,</span> <span class="s1">'Podcasting'</span><span class="p">)</span>
|
||||||
|
<span class="gp">...</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span> <span class="o">=</span> <span class="n">fg</span><span class="o">.</span><span class="n">add_entry</span><span class="p">()</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span><span class="o">.</span><span class="n">id</span><span class="p">(</span><span class="s1">'http://lernfunk.de/media/654321/1/file.mp3'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'The First Episode'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span><span class="o">.</span><span class="n">description</span><span class="p">(</span><span class="s1">'Enjoy our first episode.'</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fe</span><span class="o">.</span><span class="n">enclosure</span><span class="p">(</span><span class="s1">'http://lernfunk.de/media/654321/1/file.mp3'</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">'audio/mpeg'</span><span class="p">)</span>
|
||||||
|
<span class="gp">...</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">rss_str</span><span class="p">(</span><span class="n">pretty</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||||
|
<span class="gp">>>> </span><span class="n">fg</span><span class="o">.</span><span class="n">rss_file</span><span class="p">(</span><span class="s1">'podcast.xml'</span><span class="p">)</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>If the FeedGenerator class is used to load an extension, it is automatically
|
||||||
|
loaded for every feed entry as well. You can, however, load an extension for a
|
||||||
|
specific FeedEntry only by calling <cite>load_extension(…)</cite> on that entry.</p>
|
||||||
|
<p>Even if extensions are loaded, they can be temporarily disabled during the feed
|
||||||
|
generation by calling the generating method with the keyword argument
|
||||||
|
<cite>extensions</cite> set to <cite>False</cite>.</p>
|
||||||
|
<p><strong>Custom Extensions</strong></p>
|
||||||
|
<p>If you want to load custom extensions which are not part of the feedgen
|
||||||
|
package, you can use the method <cite>register_extension</cite> instead. You can directly
|
||||||
|
pass the classes for the feed and the entry extension to this method meaning
|
||||||
|
that you can define them everywhere.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="testing-the-generator">
|
||||||
|
<h2><a class="toc-backref" href="#id7">Testing the Generator</a><a class="headerlink" href="#testing-the-generator" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>You can test the module by simply executing:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ python -m feedgen
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>If you want to have a look at the code for this test to have a working code
|
||||||
|
example for a whole feed generation process, you can find it in the
|
||||||
|
<a class="reference external" href="https://github.com/lkiesow/python-feedgen/blob/master/feedgen/__main__.py">__main__.py</a>.</p>
|
||||||
|
<hr /></div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="module-documentation">
|
||||||
|
<h1><a class="toc-backref" href="#id8">Module documentation</a><a class="headerlink" href="#module-documentation" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<div class="toctree-wrapper compound">
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="api.html">API Documentation</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="api.html#feedgen">feedgen</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="api.feed.html">feedgen.feed</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="api.entry.html">feedgen.entry</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="api.util.html">feedgen.util</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="ext/api.ext.base.html">feedgen.ext.base</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="ext/api.ext.dc.html">feedgen.ext.dc</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="ext/api.ext.podcast.html">feedgen.ext.podcast</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="ext/api.ext.podcast_entry.html">feedgen.ext.podcast_entry</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="ext/api.ext.torrent.html">feedgen.ext.torrent</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="indices-and-tables">
|
||||||
|
<h1><a class="toc-backref" href="#id9">Indices and tables</a><a class="headerlink" href="#indices-and-tables" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></li>
|
||||||
|
<li><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></li>
|
||||||
|
<li><a class="reference internal" href="search.html"><span class="std std-ref">Search Page</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a class="uplink" href="#">Contents</a>
|
||||||
|
  ::  
|
||||||
|
<a href="api.html">API Documentation</a>  »
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
25
license.bsd
|
@ -1,25 +0,0 @@
|
||||||
BSD 2-Clause License
|
|
||||||
|
|
||||||
Copyright 2011, Lars Kiesow <lkiesow@uos.de>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
165
license.lgpl
|
@ -1,165 +0,0 @@
|
||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
|
||||||
General Public License.
|
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
|
||||||
other than an Application or a Combined Work as defined below.
|
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
|
||||||
by the Library, but which is not otherwise based on the Library.
|
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
|
||||||
of using an interface provided by the Library.
|
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
|
||||||
Application with the Library. The particular version of the Library
|
|
||||||
with which the Combined Work was made is also called the "Linked
|
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
|
||||||
based on the Application, and not on the Linked Version.
|
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
|
||||||
object code and/or source code for the Application, including any data
|
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
|
||||||
without being bound by section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
|
||||||
this License applicable to that copy.
|
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
|
||||||
a header file that is part of the Library. You may convey such object
|
|
||||||
code under terms of your choice, provided that, if the incorporated
|
|
||||||
material is not limited to numerical parameters, data structure
|
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
|
||||||
Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
4. Combined Works.
|
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
|
||||||
taken together, effectively do not restrict modification of the
|
|
||||||
portions of the Library contained in the Combined Work and reverse
|
|
||||||
engineering for debugging such modifications, if you also do each of
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
|
||||||
execution, include the copyright notice for the Library among
|
|
||||||
these notices, as well as a reference directing the user to the
|
|
||||||
copies of the GNU GPL and this license document.
|
|
||||||
|
|
||||||
d) Do one of the following:
|
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
|
||||||
License, and the Corresponding Application Code in a form
|
|
||||||
suitable for, and under terms that permit, the user to
|
|
||||||
recombine or relink the Application with a modified version of
|
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
|
||||||
Corresponding Source.
|
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
|
||||||
a copy of the Library already present on the user's computer
|
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
|
||||||
be required to provide such information under section 6 of the
|
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
|
||||||
Library side by side in a single library together with other library
|
|
||||||
facilities that are not Applications and are not covered by this
|
|
||||||
License, and convey such a combined library under terms of your
|
|
||||||
choice, if you do both of the following:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
|
||||||
on the Library, uncombined with any other library facilities,
|
|
||||||
conveyed under the terms of this License.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
|
||||||
is a work based on the Library, and explaining where to find the
|
|
||||||
accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Library as you received it specifies that a certain numbered version
|
|
||||||
of the GNU Lesser General Public License "or any later version"
|
|
||||||
applies to it, you have the option of following the terms and
|
|
||||||
conditions either of that published version or of any later version
|
|
||||||
published by the Free Software Foundation. If the Library as you
|
|
||||||
received it does not specify a version number of the GNU Lesser
|
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
|
||||||
permanent authorization for you to choose that version for the
|
|
||||||
Library.
|
|
111
py-modindex.html
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>Python Module Index — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>Python Module Index</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h1>Python Module Index</h1>
|
||||||
|
|
||||||
|
<div class="modindex-jumpbox">
|
||||||
|
<a href="#cap-f"><strong>f</strong></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="indextable modindextable">
|
||||||
|
<tr class="pcap"><td></td><td> </td><td></td></tr>
|
||||||
|
<tr class="cap" id="cap-f"><td></td><td>
|
||||||
|
<strong>f</strong></td><td></td></tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="_static/minus.png" class="toggler"
|
||||||
|
id="toggle-1" style="display: none" alt="-" /></td>
|
||||||
|
<td>
|
||||||
|
<a href="api.html#module-feedgen"><code class="xref">feedgen</code></a></td><td>
|
||||||
|
<em></em></td></tr>
|
||||||
|
<tr class="cg-1">
|
||||||
|
<td></td>
|
||||||
|
<td>   
|
||||||
|
<a href="api.entry.html#module-feedgen.entry"><code class="xref">feedgen.entry</code></a></td><td>
|
||||||
|
<em></em></td></tr>
|
||||||
|
<tr class="cg-1">
|
||||||
|
<td></td>
|
||||||
|
<td>   
|
||||||
|
<a href="ext/api.ext.base.html#module-feedgen.ext.base"><code class="xref">feedgen.ext.base</code></a></td><td>
|
||||||
|
<em></em></td></tr>
|
||||||
|
<tr class="cg-1">
|
||||||
|
<td></td>
|
||||||
|
<td>   
|
||||||
|
<a href="ext/api.ext.dc.html#module-feedgen.ext.dc"><code class="xref">feedgen.ext.dc</code></a></td><td>
|
||||||
|
<em></em></td></tr>
|
||||||
|
<tr class="cg-1">
|
||||||
|
<td></td>
|
||||||
|
<td>   
|
||||||
|
<a href="ext/api.ext.podcast.html#module-feedgen.ext.podcast"><code class="xref">feedgen.ext.podcast</code></a></td><td>
|
||||||
|
<em></em></td></tr>
|
||||||
|
<tr class="cg-1">
|
||||||
|
<td></td>
|
||||||
|
<td>   
|
||||||
|
<a href="ext/api.ext.podcast_entry.html#module-feedgen.ext.podcast_entry"><code class="xref">feedgen.ext.podcast_entry</code></a></td><td>
|
||||||
|
<em></em></td></tr>
|
||||||
|
<tr class="cg-1">
|
||||||
|
<td></td>
|
||||||
|
<td>   
|
||||||
|
<a href="ext/api.ext.torrent.html#module-feedgen.ext.torrent"><code class="xref">feedgen.ext.torrent</code></a></td><td>
|
||||||
|
<em></em></td></tr>
|
||||||
|
<tr class="cg-1">
|
||||||
|
<td></td>
|
||||||
|
<td>   
|
||||||
|
<a href="api.feed.html#module-feedgen.feed"><code class="xref">feedgen.feed</code></a></td><td>
|
||||||
|
<em></em></td></tr>
|
||||||
|
<tr class="cg-1">
|
||||||
|
<td></td>
|
||||||
|
<td>   
|
||||||
|
<a href="api.util.html#module-feedgen.util"><code class="xref">feedgen.util</code></a></td><td>
|
||||||
|
<em></em></td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,86 +0,0 @@
|
||||||
%global pypi_name feedgen
|
|
||||||
|
|
||||||
Name: python-%{pypi_name}
|
|
||||||
Version: 0.9.0
|
|
||||||
Release: 1%{?dist}
|
|
||||||
Summary: Feed Generator (ATOM, RSS, Podcasts)
|
|
||||||
|
|
||||||
License: BSD or LGPLv3
|
|
||||||
URL: http://lkiesow.github.io/python-feedgen
|
|
||||||
Source0: https://github.com/lkiesow/%{name}/archive/v%{version}.tar.gz
|
|
||||||
BuildArch: noarch
|
|
||||||
|
|
||||||
BuildRequires: python2-dateutil
|
|
||||||
BuildRequires: python2-devel
|
|
||||||
BuildRequires: python2-lxml
|
|
||||||
BuildRequires: python2-setuptools
|
|
||||||
|
|
||||||
BuildRequires: python3-dateutil
|
|
||||||
BuildRequires: python3-devel
|
|
||||||
BuildRequires: python3-lxml
|
|
||||||
BuildRequires: python3-setuptools
|
|
||||||
|
|
||||||
%description
|
|
||||||
Feedgenerator This module can be used to generate web feeds in both ATOM and
|
|
||||||
RSS format. It has support for extensions. Included is for example an extension
|
|
||||||
to produce Podcasts.
|
|
||||||
|
|
||||||
%package -n python2-%{pypi_name}
|
|
||||||
Summary: %{summary}
|
|
||||||
%{?python_provide:%python_provide python2-%{pypi_name}}
|
|
||||||
|
|
||||||
Requires: python2-dateutil
|
|
||||||
Requires: python2-lxml
|
|
||||||
%description -n python2-%{pypi_name}
|
|
||||||
Feedgenerator This module can be used to generate web feeds in both ATOM and
|
|
||||||
RSS format. It has support for extensions. Included is for example an extension
|
|
||||||
to produce Podcasts.
|
|
||||||
|
|
||||||
%package -n python3-%{pypi_name}
|
|
||||||
Summary: %{summary}
|
|
||||||
%{?python_provide:%python_provide python3-%{pypi_name}}
|
|
||||||
|
|
||||||
Requires: python3-dateutil
|
|
||||||
Requires: python3-lxml
|
|
||||||
%description -n python3-%{pypi_name}
|
|
||||||
Feedgenerator This module can be used to generate web feeds in both ATOM and
|
|
||||||
RSS format. It has support for extensions. Included is for example an extension
|
|
||||||
to produce Podcasts.
|
|
||||||
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%autosetup
|
|
||||||
# Remove bundled egg-info
|
|
||||||
rm -rf %{pypi_name}.egg-info
|
|
||||||
|
|
||||||
%build
|
|
||||||
%py2_build
|
|
||||||
%py3_build
|
|
||||||
|
|
||||||
%install
|
|
||||||
%py2_install
|
|
||||||
%py3_install
|
|
||||||
|
|
||||||
|
|
||||||
%check
|
|
||||||
%{__python2} setup.py test
|
|
||||||
%{__python3} setup.py test
|
|
||||||
|
|
||||||
%files -n python2-%{pypi_name}
|
|
||||||
%license license.lgpl license.bsd
|
|
||||||
%doc readme.rst
|
|
||||||
%{python2_sitelib}/%{pypi_name}
|
|
||||||
%{python2_sitelib}/%{pypi_name}-%{version}-py?.?.egg-info
|
|
||||||
|
|
||||||
%files -n python3-%{pypi_name}
|
|
||||||
%license license.lgpl license.bsd
|
|
||||||
%doc readme.rst
|
|
||||||
%{python3_sitelib}/%{pypi_name}
|
|
||||||
%{python3_sitelib}/%{pypi_name}-%{version}-py?.?.egg-info
|
|
||||||
|
|
||||||
%changelog
|
|
||||||
* Sat May 19 2018 Lars Kiesow <lkiesow@uos.de> - 0.7.0-1
|
|
||||||
- Update to 0.7.0
|
|
||||||
|
|
||||||
* Tue Oct 24 2017 Lumir Balhar <lbalhar@redhat.com> - 0.6.1-1
|
|
||||||
- Initial package.
|
|
193
readme.rst
|
@ -1,193 +0,0 @@
|
||||||
=============
|
|
||||||
Feedgenerator
|
|
||||||
=============
|
|
||||||
|
|
||||||
.. image:: https://travis-ci.org/lkiesow/python-feedgen.svg?branch=master
|
|
||||||
:target: https://travis-ci.org/lkiesow/python-feedgen
|
|
||||||
:alt: Build Status
|
|
||||||
|
|
||||||
.. image:: https://coveralls.io/repos/github/lkiesow/python-feedgen/badge.svg?branch=master
|
|
||||||
:target: https://coveralls.io/github/lkiesow/python-feedgen?branch=master
|
|
||||||
:alt: Test Coverage Status
|
|
||||||
|
|
||||||
|
|
||||||
This module can be used to generate web feeds in both ATOM and RSS format. It
|
|
||||||
has support for extensions. Included is for example an extension to produce
|
|
||||||
Podcasts.
|
|
||||||
|
|
||||||
It is licensed under the terms of both, the FreeBSD license and the LGPLv3+.
|
|
||||||
Choose the one which is more convenient for you. For more details have a look
|
|
||||||
at license.bsd and license.lgpl.
|
|
||||||
|
|
||||||
More details about the project:
|
|
||||||
|
|
||||||
- `Repository <https://github.com/lkiesow/python-feedgen>`_
|
|
||||||
- `Documentation <https://lkiesow.github.io/python-feedgen/>`_
|
|
||||||
- `Python Package Index <https://pypi.python.org/pypi/feedgen/>`_
|
|
||||||
|
|
||||||
|
|
||||||
------------
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
**Prebuild packages**
|
|
||||||
|
|
||||||
If your distribution includes this project as package, like Fedora Linux does,
|
|
||||||
you can simply use your package manager to install the package. For example::
|
|
||||||
|
|
||||||
$ dnf install python3-feedgen
|
|
||||||
|
|
||||||
|
|
||||||
**Using pip**
|
|
||||||
|
|
||||||
You can also use pip to install the feedgen module. Simply run::
|
|
||||||
|
|
||||||
$ pip install feedgen
|
|
||||||
|
|
||||||
|
|
||||||
-------------
|
|
||||||
Create a Feed
|
|
||||||
-------------
|
|
||||||
|
|
||||||
To create a feed simply instantiate the FeedGenerator class and insert some
|
|
||||||
data:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
fg = FeedGenerator()
|
|
||||||
fg.id('http://lernfunk.de/media/654321')
|
|
||||||
fg.title('Some Testfeed')
|
|
||||||
fg.author( {'name':'John Doe','email':'john@example.de'} )
|
|
||||||
fg.link( href='http://example.com', rel='alternate' )
|
|
||||||
fg.logo('http://ex.com/logo.jpg')
|
|
||||||
fg.subtitle('This is a cool feed!')
|
|
||||||
fg.link( href='http://larskiesow.de/test.atom', rel='self' )
|
|
||||||
fg.language('en')
|
|
||||||
|
|
||||||
Note that for the methods which set fields that can occur more than once in a
|
|
||||||
feed you can use all of the following ways to provide data:
|
|
||||||
|
|
||||||
- Provide the data for that element as keyword arguments
|
|
||||||
- Provide the data for that element as dictionary
|
|
||||||
- Provide a list of dictionaries with the data for several elements
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
fg.contributor( name='John Doe', email='jdoe@example.com' )
|
|
||||||
fg.contributor({'name':'John Doe', 'email':'jdoe@example.com'})
|
|
||||||
fg.contributor([{'name':'John Doe', 'email':'jdoe@example.com'}, ...])
|
|
||||||
|
|
||||||
-----------------
|
|
||||||
Generate the Feed
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
After that you can generate both RSS or ATOM by calling the respective method:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
atomfeed = fg.atom_str(pretty=True) # Get the ATOM feed as string
|
|
||||||
rssfeed = fg.rss_str(pretty=True) # Get the RSS feed as string
|
|
||||||
fg.atom_file('atom.xml') # Write the ATOM feed to a file
|
|
||||||
fg.rss_file('rss.xml') # Write the RSS feed to a file
|
|
||||||
|
|
||||||
|
|
||||||
----------------
|
|
||||||
Add Feed Entries
|
|
||||||
----------------
|
|
||||||
|
|
||||||
To add entries (items) to a feed you need to create new FeedEntry objects and
|
|
||||||
append them to the list of entries in the FeedGenerator. The most convenient
|
|
||||||
way to go is to use the FeedGenerator itself for the instantiation of the
|
|
||||||
FeedEntry object:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/media/654321/1')
|
|
||||||
fe.title('The First Episode')
|
|
||||||
fe.link(href="http://lernfunk.de/feed")
|
|
||||||
|
|
||||||
The FeedGenerator's method `add_entry(...)` will generate a new FeedEntry
|
|
||||||
object, automatically append it to the feeds internal list of entries and
|
|
||||||
return it, so that additional data can be added.
|
|
||||||
|
|
||||||
----------
|
|
||||||
Extensions
|
|
||||||
----------
|
|
||||||
|
|
||||||
The FeedGenerator supports extensions to include additional data into the XML
|
|
||||||
structure of the feeds. Extensions can be loaded like this:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
fg.load_extension('someext', atom=True, rss=True)
|
|
||||||
|
|
||||||
This example would try to load the extension “someext” from the file
|
|
||||||
`ext/someext.py`. It is required that `someext.py` contains a class named
|
|
||||||
“SomextExtension” which is required to have at least the two methods
|
|
||||||
`extend_rss(...)` and `extend_atom(...)`. Although not required, it is strongly
|
|
||||||
suggested to use `BaseExtension` from `ext/base.py` as superclass.
|
|
||||||
|
|
||||||
`load_extension('someext', ...)` will also try to load a class named
|
|
||||||
“SomextEntryExtension” for every entry of the feed. This class can be located
|
|
||||||
either in the same file as SomextExtension or in `ext/someext_entry.py` which
|
|
||||||
is suggested especially for large extensions.
|
|
||||||
|
|
||||||
The parameters `atom` and `rss` control if the extension is used for ATOM and
|
|
||||||
RSS feeds respectively. The default value for both parameters is `True`,
|
|
||||||
meaning the extension is used for both kinds of feeds.
|
|
||||||
|
|
||||||
**Example: Producing a Podcast**
|
|
||||||
|
|
||||||
One extension already provided is the podcast extension. A podcast is an RSS
|
|
||||||
feed with some additional elements for ITunes.
|
|
||||||
|
|
||||||
To produce a podcast simply load the `podcast` extension:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
fg = FeedGenerator()
|
|
||||||
fg.load_extension('podcast')
|
|
||||||
...
|
|
||||||
fg.podcast.itunes_category('Technology', 'Podcasting')
|
|
||||||
...
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/media/654321/1/file.mp3')
|
|
||||||
fe.title('The First Episode')
|
|
||||||
fe.description('Enjoy our first episode.')
|
|
||||||
fe.enclosure('http://lernfunk.de/media/654321/1/file.mp3', 0, 'audio/mpeg')
|
|
||||||
...
|
|
||||||
fg.rss_str(pretty=True)
|
|
||||||
fg.rss_file('podcast.xml')
|
|
||||||
|
|
||||||
If the FeedGenerator class is used to load an extension, it is automatically
|
|
||||||
loaded for every feed entry as well. You can, however, load an extension for a
|
|
||||||
specific FeedEntry only by calling `load_extension(...)` on that entry.
|
|
||||||
|
|
||||||
Even if extensions are loaded, they can be temporarily disabled during the feed
|
|
||||||
generation by calling the generating method with the keyword argument
|
|
||||||
`extensions` set to `False`.
|
|
||||||
|
|
||||||
**Custom Extensions**
|
|
||||||
|
|
||||||
If you want to load custom extensions which are not part of the feedgen
|
|
||||||
package, you can use the method `register_extension` instead. You can directly
|
|
||||||
pass the classes for the feed and the entry extension to this method meaning
|
|
||||||
that you can define them everywhere.
|
|
||||||
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
Testing the Generator
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
You can test the module by simply executing::
|
|
||||||
|
|
||||||
$ python -m feedgen
|
|
||||||
|
|
||||||
If you want to have a look at the code for this test to have a working code
|
|
||||||
example for a whole feed generation process, you can find it in the
|
|
||||||
`__main__.py <https://github.com/lkiesow/python-feedgen/blob/master/feedgen/__main__.py>`_.
|
|
|
@ -1,2 +0,0 @@
|
||||||
lxml==4.2.5
|
|
||||||
python_dateutil==2.8.0
|
|
81
search.html
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>Search — python-feedgen 0.8.0 documentation</title>
|
||||||
|
<link rel="stylesheet" href="_static/lernfunk.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
|
|
||||||
|
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/language_data.js"></script>
|
||||||
|
<script type="text/javascript" src="_static/searchtools.js"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="#" />
|
||||||
|
<script type="text/javascript">
|
||||||
|
jQuery(function() { Search.loadIndex("searchindex.js"); });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript" id="searchindexloader"></script>
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
<div class="header" role="banner"><h1 class="heading"><a href="index.html">
|
||||||
|
<span>python-feedgen 0.8.0 documentation</span></a></h1>
|
||||||
|
<h2 class="heading"><span>Search</span></h2>
|
||||||
|
</div>
|
||||||
|
<div class="topnav" role="navigation" aria-label="top navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
|
||||||
|
<h1 id="search-documentation">Search</h1>
|
||||||
|
<div id="fallback" class="admonition warning">
|
||||||
|
<script type="text/javascript">$('#fallback').hide();</script>
|
||||||
|
<p>
|
||||||
|
Please activate JavaScript to enable the search
|
||||||
|
functionality.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
From here you can search these documents. Enter your search
|
||||||
|
words into the box below and click "search". Note that the search
|
||||||
|
function will automatically search for all of the words. Pages
|
||||||
|
containing fewer words won't appear in the result list.
|
||||||
|
</p>
|
||||||
|
<form action="" method="get">
|
||||||
|
<input type="text" name="q" value="" />
|
||||||
|
<input type="submit" value="search" />
|
||||||
|
<span id="search-progress" style="padding-left: 10px"></span>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="search-results">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a class="uplink" href="index.html">Contents</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2013-2016, Lars Kiesow.
|
||||||
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.4.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
searchindex.js
Normal file
|
@ -1,2 +0,0 @@
|
||||||
[bdist_wheel]
|
|
||||||
universal=1
|
|
51
setup.py
|
@ -1,51 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from setuptools import setup
|
|
||||||
|
|
||||||
import feedgen.version
|
|
||||||
|
|
||||||
packages = ['feedgen', 'feedgen/ext']
|
|
||||||
|
|
||||||
setup(name='feedgen',
|
|
||||||
packages=packages,
|
|
||||||
version=feedgen.version.version_full_str,
|
|
||||||
description='Feed Generator (ATOM, RSS, Podcasts)',
|
|
||||||
author='Lars Kiesow',
|
|
||||||
author_email='lkiesow@uos.de',
|
|
||||||
url='https://lkiesow.github.io/python-feedgen',
|
|
||||||
keywords=['feed', 'ATOM', 'RSS', 'podcast'],
|
|
||||||
license='FreeBSD and LGPLv3+',
|
|
||||||
install_requires=['lxml', 'python-dateutil'],
|
|
||||||
classifiers=[
|
|
||||||
'Development Status :: 5 - Production/Stable',
|
|
||||||
'Intended Audience :: Developers',
|
|
||||||
'Intended Audience :: Information Technology',
|
|
||||||
'Intended Audience :: Science/Research',
|
|
||||||
'License :: OSI Approved :: BSD License',
|
|
||||||
'License :: OSI Approved :: GNU Lesser General Public License v3 ' +
|
|
||||||
'or later (LGPLv3+)',
|
|
||||||
'Natural Language :: English',
|
|
||||||
'Operating System :: OS Independent',
|
|
||||||
'Programming Language :: Python',
|
|
||||||
'Programming Language :: Python :: 2',
|
|
||||||
'Programming Language :: Python :: 3',
|
|
||||||
'Topic :: Communications',
|
|
||||||
'Topic :: Internet',
|
|
||||||
'Topic :: Text Processing',
|
|
||||||
'Topic :: Text Processing :: Markup',
|
|
||||||
'Topic :: Text Processing :: Markup :: XML'
|
|
||||||
],
|
|
||||||
test_suite="tests",
|
|
||||||
long_description='''\
|
|
||||||
Feedgenerator
|
|
||||||
=============
|
|
||||||
|
|
||||||
This module can be used to generate web feeds in both ATOM and RSS format. It
|
|
||||||
has support for extensions. Included is for example an extension to produce
|
|
||||||
Podcasts.
|
|
||||||
|
|
||||||
It is licensed under the terms of both, the FreeBSD license and the LGPLv3+.
|
|
||||||
Choose the one which is more convenient for you. For more details have a look
|
|
||||||
at license.bsd and license.lgpl.
|
|
||||||
''')
|
|
|
@ -1,179 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests for a basic entry
|
|
||||||
|
|
||||||
These are test cases for a basic entry.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
|
|
||||||
|
|
||||||
class TestSequenceFunctions(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
fg = FeedGenerator()
|
|
||||||
self.feedId = 'http://example.com'
|
|
||||||
self.title = 'Some Testfeed'
|
|
||||||
|
|
||||||
fg.id(self.feedId)
|
|
||||||
fg.title(self.title)
|
|
||||||
fg.link(href='http://lkiesow.de', rel='alternate')[0]
|
|
||||||
fg.description('...')
|
|
||||||
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/media/654321/1')
|
|
||||||
fe.title('The First Episode')
|
|
||||||
fe.content(u'…')
|
|
||||||
|
|
||||||
# Use also the different name add_item
|
|
||||||
fe = fg.add_item()
|
|
||||||
fe.id('http://lernfunk.de/media/654321/1')
|
|
||||||
fe.title('The Second Episode')
|
|
||||||
fe.content(u'…')
|
|
||||||
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/media/654321/1')
|
|
||||||
fe.title('The Third Episode')
|
|
||||||
fe.content(u'…')
|
|
||||||
|
|
||||||
self.fg = fg
|
|
||||||
|
|
||||||
def test_setEntries(self):
|
|
||||||
fg2 = FeedGenerator()
|
|
||||||
fg2.entry(self.fg.entry())
|
|
||||||
assert len(fg2.entry()) == 3
|
|
||||||
assert self.fg.entry() == fg2.entry()
|
|
||||||
|
|
||||||
def test_loadExtension(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.id('1')
|
|
||||||
fe.title(u'…')
|
|
||||||
fe.content(u'…')
|
|
||||||
fe.load_extension('base')
|
|
||||||
assert fe.base
|
|
||||||
assert self.fg.atom_str()
|
|
||||||
|
|
||||||
def test_checkEntryNumbers(self):
|
|
||||||
fg = self.fg
|
|
||||||
assert len(fg.entry()) == 3
|
|
||||||
|
|
||||||
def test_TestEntryItems(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('qwe')
|
|
||||||
assert fe.title() == 'qwe'
|
|
||||||
author = fe.author(email='ldoe@example.com')[0]
|
|
||||||
assert not author.get('name')
|
|
||||||
assert author.get('email') == 'ldoe@example.com'
|
|
||||||
author = fe.author(name='John Doe', email='jdoe@example.com',
|
|
||||||
replace=True)[0]
|
|
||||||
assert author.get('name') == 'John Doe'
|
|
||||||
assert author.get('email') == 'jdoe@example.com'
|
|
||||||
contributor = fe.contributor(name='John Doe', email='jdoe@ex.com')[0]
|
|
||||||
assert contributor == fe.contributor()[0]
|
|
||||||
assert contributor.get('name') == 'John Doe'
|
|
||||||
assert contributor.get('email') == 'jdoe@ex.com'
|
|
||||||
link = fe.link(href='http://lkiesow.de', rel='alternate')[0]
|
|
||||||
assert link == fe.link()[0]
|
|
||||||
assert link.get('href') == 'http://lkiesow.de'
|
|
||||||
assert link.get('rel') == 'alternate'
|
|
||||||
fe.guid('123')
|
|
||||||
assert fe.guid().get('guid') == '123'
|
|
||||||
fe.updated('2017-02-05 13:26:58+01:00')
|
|
||||||
assert fe.updated().year == 2017
|
|
||||||
fe.summary('asdf')
|
|
||||||
assert fe.summary() == {'summary': 'asdf'}
|
|
||||||
fe.description('asdfx')
|
|
||||||
assert fe.description() == 'asdfx'
|
|
||||||
fe.pubDate('2017-02-05 13:26:58+01:00')
|
|
||||||
assert fe.pubDate().year == 2017
|
|
||||||
fe.rights('asdfx')
|
|
||||||
assert fe.rights() == 'asdfx'
|
|
||||||
source = fe.source(url='https://example.com', title='Test')
|
|
||||||
assert source.get('title') == 'Test'
|
|
||||||
assert source.get('url') == 'https://example.com'
|
|
||||||
fe.comments('asdfx')
|
|
||||||
assert fe.comments() == 'asdfx'
|
|
||||||
fe.enclosure(url='http://lkiesow.de', type='text/plain', length='1')
|
|
||||||
assert fe.enclosure().get('url') == 'http://lkiesow.de'
|
|
||||||
fe.ttl(8)
|
|
||||||
assert fe.ttl() == 8
|
|
||||||
|
|
||||||
self.fg.rss_str()
|
|
||||||
self.fg.atom_str()
|
|
||||||
|
|
||||||
def test_checkItemNumbers(self):
|
|
||||||
fg = self.fg
|
|
||||||
assert len(fg.item()) == 3
|
|
||||||
|
|
||||||
def test_checkEntryContent(self):
|
|
||||||
fg = self.fg
|
|
||||||
assert fg.entry()
|
|
||||||
|
|
||||||
def test_removeEntryByIndex(self):
|
|
||||||
fg = FeedGenerator()
|
|
||||||
self.feedId = 'http://example.com'
|
|
||||||
self.title = 'Some Testfeed'
|
|
||||||
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/media/654321/1')
|
|
||||||
fe.title('The Third Episode')
|
|
||||||
assert len(fg.entry()) == 1
|
|
||||||
fg.remove_entry(0)
|
|
||||||
assert len(fg.entry()) == 0
|
|
||||||
|
|
||||||
def test_removeEntryByEntry(self):
|
|
||||||
fg = FeedGenerator()
|
|
||||||
self.feedId = 'http://example.com'
|
|
||||||
self.title = 'Some Testfeed'
|
|
||||||
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/media/654321/1')
|
|
||||||
fe.title('The Third Episode')
|
|
||||||
|
|
||||||
assert len(fg.entry()) == 1
|
|
||||||
fg.remove_entry(fe)
|
|
||||||
assert len(fg.entry()) == 0
|
|
||||||
|
|
||||||
def test_categoryHasDomain(self):
|
|
||||||
fg = FeedGenerator()
|
|
||||||
fg.title('some title')
|
|
||||||
fg.link(href='http://www.dontcare.com', rel='alternate')
|
|
||||||
fg.description('description')
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/media/654321/1')
|
|
||||||
fe.title('some title')
|
|
||||||
fe.category([
|
|
||||||
{'term': 'category',
|
|
||||||
'scheme': 'http://www.somedomain.com/category',
|
|
||||||
'label': 'Category',
|
|
||||||
}])
|
|
||||||
|
|
||||||
result = fg.rss_str()
|
|
||||||
assert b'domain="http://www.somedomain.com/category"' in result
|
|
||||||
|
|
||||||
def test_content_cdata_type(self):
|
|
||||||
fg = FeedGenerator()
|
|
||||||
fg.title('some title')
|
|
||||||
fg.id('http://lernfunk.de/media/654322/1')
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/media/654322/1')
|
|
||||||
fe.title('some title')
|
|
||||||
fe.content('content', type='CDATA')
|
|
||||||
result = fg.atom_str()
|
|
||||||
assert b'<content type="CDATA"><![CDATA[content]]></content>' in result
|
|
||||||
|
|
||||||
def test_summary_html_type(self):
|
|
||||||
fg = FeedGenerator()
|
|
||||||
fg.title('some title')
|
|
||||||
fg.id('http://lernfunk.de/media/654322/1')
|
|
||||||
fe = fg.add_entry()
|
|
||||||
fe.id('http://lernfunk.de/media/654322/1')
|
|
||||||
fe.title('some title')
|
|
||||||
fe.link(href='http://lernfunk.de/media/654322/1')
|
|
||||||
fe.summary('<p>summary</p>', type='html')
|
|
||||||
result = fg.atom_str()
|
|
||||||
expected = b'<summary type="html"><p>summary</p></summary>'
|
|
||||||
assert expected in result
|
|
|
@ -1,31 +0,0 @@
|
||||||
import unittest
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
|
|
||||||
|
|
||||||
class TestExtensionDc(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.fg = FeedGenerator()
|
|
||||||
self.fg.load_extension('dc')
|
|
||||||
self.fg.title('title')
|
|
||||||
self.fg.link(href='http://example.com', rel='self')
|
|
||||||
self.fg.description('description')
|
|
||||||
|
|
||||||
def test_entryLoadExtension(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
try:
|
|
||||||
fe.load_extension('dc')
|
|
||||||
except ImportError:
|
|
||||||
pass # Extension already loaded
|
|
||||||
|
|
||||||
def test_elements(self):
|
|
||||||
for method in dir(self.fg.dc):
|
|
||||||
if method.startswith('dc_'):
|
|
||||||
m = getattr(self.fg.dc, method)
|
|
||||||
m(method)
|
|
||||||
assert m() == [method]
|
|
||||||
|
|
||||||
self.fg.id('123')
|
|
||||||
assert self.fg.atom_str()
|
|
||||||
assert self.fg.rss_str()
|
|
|
@ -1,429 +0,0 @@
|
||||||
from itertools import chain
|
|
||||||
import unittest
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from lxml import etree
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
from feedgen.ext.geo_entry import GeoRSSPolygonInteriorWarning, GeoRSSGeometryError # noqa: E501
|
|
||||||
|
|
||||||
|
|
||||||
class Geom(object):
|
|
||||||
"""
|
|
||||||
Dummy geom to make testing easier
|
|
||||||
|
|
||||||
When we use the geo-interface we need a class with a `__geo_interface__`
|
|
||||||
property. Makes it easier for the other tests as well.
|
|
||||||
|
|
||||||
Ultimately this could be used to generate dummy geometries for testing
|
|
||||||
a wider variety of values (e.g. with the faker library, or the hypothesis
|
|
||||||
library)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, geom_type, coords):
|
|
||||||
self.geom_type = geom_type
|
|
||||||
self.coords = coords
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.geom_type == 'Point':
|
|
||||||
|
|
||||||
coords = '{:f} {:f}'.format(
|
|
||||||
self.coords[1], # latitude is y
|
|
||||||
self.coords[0]
|
|
||||||
)
|
|
||||||
return coords
|
|
||||||
|
|
||||||
elif self.geom_type == 'LineString':
|
|
||||||
|
|
||||||
coords = ' '.join(
|
|
||||||
'{:f} {:f}'.format(vertex[1], vertex[0])
|
|
||||||
for vertex in
|
|
||||||
self.coords
|
|
||||||
)
|
|
||||||
return coords
|
|
||||||
|
|
||||||
elif self.geom_type == 'Polygon':
|
|
||||||
|
|
||||||
coords = ' '.join(
|
|
||||||
'{:f} {:f}'.format(vertex[1], vertex[0])
|
|
||||||
for vertex in
|
|
||||||
self.coords[0]
|
|
||||||
)
|
|
||||||
return coords
|
|
||||||
|
|
||||||
elif self.geom_type == 'Box':
|
|
||||||
# box not really supported by GeoJSON, but it's a handy cheat here
|
|
||||||
# for testing
|
|
||||||
coords = ' '.join(
|
|
||||||
'{:f} {:f}'.format(vertex[1], vertex[0])
|
|
||||||
for vertex in
|
|
||||||
self.coords
|
|
||||||
)
|
|
||||||
return coords[:2]
|
|
||||||
|
|
||||||
else:
|
|
||||||
return 'Not a supported geometry'
|
|
||||||
|
|
||||||
@property
|
|
||||||
def __geo_interface__(self):
|
|
||||||
return {
|
|
||||||
'type': self.geom_type,
|
|
||||||
'coordinates': self.coords
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class TestExtensionGeo(unittest.TestCase):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
cls.point = Geom('Point', [-71.05, 42.36])
|
|
||||||
cls.line = Geom('LineString', [[-71.05, 42.36], [-71.15, 42.46]])
|
|
||||||
cls.polygon = Geom(
|
|
||||||
'Polygon',
|
|
||||||
[[[-71.05, 42.36], [-71.15, 42.46], [-71.15, 42.36]]]
|
|
||||||
)
|
|
||||||
cls.box = Geom('Box', [[-71.05, 42.36], [-71.15, 42.46]])
|
|
||||||
cls.polygon_with_interior = Geom(
|
|
||||||
'Polygon',
|
|
||||||
[
|
|
||||||
[ # exterior
|
|
||||||
[0, 0],
|
|
||||||
[0, 1],
|
|
||||||
[1, 1],
|
|
||||||
[1, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
[ # interior
|
|
||||||
[0.25, 0.25],
|
|
||||||
[0.25, 0.75],
|
|
||||||
[0.75, 0.75],
|
|
||||||
[0.75, 0.25],
|
|
||||||
[0.25, 0.25]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.fg = FeedGenerator()
|
|
||||||
self.fg.load_extension('geo')
|
|
||||||
self.fg.title('title')
|
|
||||||
self.fg.link(href='http://example.com', rel='self')
|
|
||||||
self.fg.description('description')
|
|
||||||
|
|
||||||
def test_point(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.point(str(self.point))
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.point(), str(self.point))
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
point = root.xpath('/rss/channel/item/georss:point/text()',
|
|
||||||
namespaces=ns)
|
|
||||||
self.assertEqual(point, [str(self.point)])
|
|
||||||
|
|
||||||
def test_line(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.line(str(self.line))
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.line(), str(self.line))
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
line = root.xpath(
|
|
||||||
'/rss/channel/item/georss:line/text()',
|
|
||||||
namespaces=ns
|
|
||||||
)
|
|
||||||
self.assertEqual(line, [str(self.line)])
|
|
||||||
|
|
||||||
def test_polygon(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.polygon(str(self.polygon))
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.polygon(), str(self.polygon))
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
poly = root.xpath(
|
|
||||||
'/rss/channel/item/georss:polygon/text()',
|
|
||||||
namespaces=ns
|
|
||||||
)
|
|
||||||
self.assertEqual(poly, [str(self.polygon)])
|
|
||||||
|
|
||||||
def test_box(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.box(str(self.box))
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.box(), str(self.box))
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
box = root.xpath(
|
|
||||||
'/rss/channel/item/georss:box/text()',
|
|
||||||
namespaces=ns
|
|
||||||
)
|
|
||||||
self.assertEqual(box, [str(self.box)])
|
|
||||||
|
|
||||||
def test_featuretypetag(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.featuretypetag('city')
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.featuretypetag(), 'city')
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
featuretypetag = root.xpath(
|
|
||||||
'/rss/channel/item/georss:featuretypetag/text()',
|
|
||||||
namespaces=ns
|
|
||||||
)
|
|
||||||
self.assertEqual(featuretypetag, ['city'])
|
|
||||||
|
|
||||||
def test_relationshiptag(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.relationshiptag('is-centred-at')
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.relationshiptag(), 'is-centred-at')
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
relationshiptag = root.xpath(
|
|
||||||
'/rss/channel/item/georss:relationshiptag/text()',
|
|
||||||
namespaces=ns
|
|
||||||
)
|
|
||||||
self.assertEqual(relationshiptag, ['is-centred-at'])
|
|
||||||
|
|
||||||
def test_featurename(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.featurename('Footscray')
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.featurename(), 'Footscray')
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
featurename = root.xpath(
|
|
||||||
'/rss/channel/item/georss:featurename/text()',
|
|
||||||
namespaces=ns
|
|
||||||
)
|
|
||||||
self.assertEqual(featurename, ['Footscray'])
|
|
||||||
|
|
||||||
def test_elev(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.elev(100.3)
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.elev(), 100.3)
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
elev = root.xpath(
|
|
||||||
'/rss/channel/item/georss:elev/text()',
|
|
||||||
namespaces=ns
|
|
||||||
)
|
|
||||||
self.assertEqual(elev, ['100.3'])
|
|
||||||
|
|
||||||
def test_elev_fails_nonnumeric(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
fe.geo.elev('100.3')
|
|
||||||
|
|
||||||
def test_floor(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.floor(4)
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.floor(), 4)
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
floor = root.xpath(
|
|
||||||
'/rss/channel/item/georss:floor/text()',
|
|
||||||
namespaces=ns
|
|
||||||
)
|
|
||||||
self.assertEqual(floor, ['4'])
|
|
||||||
|
|
||||||
def test_floor_fails_nonint(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
fe.geo.floor(100.3)
|
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
fe.geo.floor('4')
|
|
||||||
|
|
||||||
def test_radius(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.radius(100.3)
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.radius(), 100.3)
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
radius = root.xpath(
|
|
||||||
'/rss/channel/item/georss:radius/text()',
|
|
||||||
namespaces=ns
|
|
||||||
)
|
|
||||||
self.assertEqual(radius, ['100.3'])
|
|
||||||
|
|
||||||
def test_radius_fails_nonnumeric(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
fe.geo.radius('100.3')
|
|
||||||
|
|
||||||
def test_geom_from_geointerface_point(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.geom_from_geo_interface(self.point)
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.point(), str(self.point))
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
point = root.xpath('/rss/channel/item/georss:point/text()',
|
|
||||||
namespaces=ns)
|
|
||||||
self.assertEqual(point, [str(self.point)])
|
|
||||||
|
|
||||||
coords = [float(c) for c in point[0].split()]
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.assertCountEqual(
|
|
||||||
coords,
|
|
||||||
self.point.coords
|
|
||||||
)
|
|
||||||
except AttributeError: # was assertItemsEqual in Python 2.7
|
|
||||||
self.assertItemsEqual(
|
|
||||||
coords,
|
|
||||||
self.point.coords
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_geom_from_geointerface_line(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.geom_from_geo_interface(self.line)
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.line(), str(self.line))
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
line = root.xpath('/rss/channel/item/georss:line/text()',
|
|
||||||
namespaces=ns)
|
|
||||||
self.assertEqual(line, [str(self.line)])
|
|
||||||
|
|
||||||
coords = [float(c) for c in line[0].split()]
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.assertCountEqual(
|
|
||||||
coords,
|
|
||||||
list(chain.from_iterable(self.line.coords))
|
|
||||||
)
|
|
||||||
except AttributeError: # was assertItemsEqual in Python 2.7
|
|
||||||
self.assertItemsEqual(
|
|
||||||
coords,
|
|
||||||
list(chain.from_iterable(self.line.coords))
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_geom_from_geointerface_poly(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.geo.geom_from_geo_interface(self.polygon)
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.polygon(), str(self.polygon))
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
poly = root.xpath('/rss/channel/item/georss:polygon/text()',
|
|
||||||
namespaces=ns)
|
|
||||||
self.assertEqual(poly, [str(self.polygon)])
|
|
||||||
|
|
||||||
coords = [float(c) for c in poly[0].split()]
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.assertCountEqual(
|
|
||||||
coords,
|
|
||||||
list(chain.from_iterable(self.polygon.coords[0]))
|
|
||||||
)
|
|
||||||
except AttributeError: # was assertItemsEqual in Python 2.7
|
|
||||||
self.assertItemsEqual(
|
|
||||||
coords,
|
|
||||||
list(chain.from_iterable(self.polygon.coords[0]))
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_geom_from_geointerface_fail_other_geom(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
|
|
||||||
with self.assertRaises(GeoRSSGeometryError):
|
|
||||||
fe.geo.geom_from_geo_interface(self.box)
|
|
||||||
|
|
||||||
def test_geom_from_geointerface_fail_requires_geo_interface(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
|
|
||||||
with self.assertRaises(AttributeError):
|
|
||||||
fe.geo.geom_from_geo_interface(str(self.box))
|
|
||||||
|
|
||||||
def test_geom_from_geointerface_warn_poly_interior(self):
|
|
||||||
"""
|
|
||||||
Test complex polygons warn as expected. Taken from
|
|
||||||
|
|
||||||
https://stackoverflow.com/a/3892301/379566 and
|
|
||||||
https://docs.python.org/2.7/library/warnings.html#testing-warnings
|
|
||||||
"""
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
|
|
||||||
with warnings.catch_warnings(record=True) as w:
|
|
||||||
# Cause all warnings to always be triggered.
|
|
||||||
warnings.simplefilter("always")
|
|
||||||
# Trigger a warning.
|
|
||||||
fe.geo.geom_from_geo_interface(self.polygon_with_interior)
|
|
||||||
# Verify some things
|
|
||||||
assert len(w) == 1
|
|
||||||
assert issubclass(w[-1].category, GeoRSSPolygonInteriorWarning)
|
|
||||||
|
|
||||||
self.assertEqual(fe.geo.polygon(), str(self.polygon_with_interior))
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'georss': 'http://www.georss.org/georss'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
poly = root.xpath('/rss/channel/item/georss:polygon/text()',
|
|
||||||
namespaces=ns)
|
|
||||||
self.assertEqual(poly, [str(self.polygon_with_interior)])
|
|
||||||
|
|
||||||
coords = [float(c) for c in poly[0].split()]
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.assertCountEqual(
|
|
||||||
coords,
|
|
||||||
list(chain.from_iterable(self.polygon_with_interior.coords[0]))
|
|
||||||
)
|
|
||||||
except AttributeError: # was assertItemsEqual in Python 2.7
|
|
||||||
self.assertItemsEqual(
|
|
||||||
coords,
|
|
||||||
list(chain.from_iterable(self.polygon_with_interior.coords[0]))
|
|
||||||
)
|
|
|
@ -1,83 +0,0 @@
|
||||||
import unittest
|
|
||||||
|
|
||||||
from lxml import etree
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
|
|
||||||
|
|
||||||
class TestExtensionMedia(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.fg = FeedGenerator()
|
|
||||||
self.fg.load_extension('media')
|
|
||||||
self.fg.id('id')
|
|
||||||
self.fg.title('title')
|
|
||||||
self.fg.link(href='http://example.com', rel='self')
|
|
||||||
self.fg.description('description')
|
|
||||||
|
|
||||||
def test_media_content(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.id('id')
|
|
||||||
fe.title('title')
|
|
||||||
fe.content('content')
|
|
||||||
fe.media.content(url='file1.xy')
|
|
||||||
fe.media.content(url='file2.xy')
|
|
||||||
fe.media.content(url='file1.xy', group=2)
|
|
||||||
fe.media.content(url='file2.xy', group=2)
|
|
||||||
fe.media.content(url='file.xy', group=None)
|
|
||||||
|
|
||||||
ns = {'media': 'http://search.yahoo.com/mrss/',
|
|
||||||
'a': 'http://www.w3.org/2005/Atom'}
|
|
||||||
# Check that we have the item in the resulting RSS
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
url = root.xpath('/rss/channel/item/media:group/media:content[1]/@url',
|
|
||||||
namespaces=ns)
|
|
||||||
assert url == ['file1.xy', 'file1.xy']
|
|
||||||
|
|
||||||
# There is one without a group
|
|
||||||
url = root.xpath('/rss/channel/item/media:content[1]/@url',
|
|
||||||
namespaces=ns)
|
|
||||||
assert url == ['file.xy']
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting Atom feed
|
|
||||||
root = etree.fromstring(self.fg.atom_str())
|
|
||||||
url = root.xpath('/a:feed/a:entry/media:group/media:content[1]/@url',
|
|
||||||
namespaces=ns)
|
|
||||||
assert url == ['file1.xy', 'file1.xy']
|
|
||||||
|
|
||||||
fe.media.content(content=[], replace=True)
|
|
||||||
assert fe.media.content() == []
|
|
||||||
|
|
||||||
def test_media_thumbnail(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.id('id')
|
|
||||||
fe.title('title')
|
|
||||||
fe.content('content')
|
|
||||||
fe.media.thumbnail(url='file1.xy')
|
|
||||||
fe.media.thumbnail(url='file2.xy')
|
|
||||||
fe.media.thumbnail(url='file1.xy', group=2)
|
|
||||||
fe.media.thumbnail(url='file2.xy', group=2)
|
|
||||||
fe.media.thumbnail(url='file.xy', group=None)
|
|
||||||
|
|
||||||
ns = {'media': 'http://search.yahoo.com/mrss/',
|
|
||||||
'a': 'http://www.w3.org/2005/Atom'}
|
|
||||||
# Check that we have the item in the resulting RSS
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
url = root.xpath(
|
|
||||||
'/rss/channel/item/media:group/media:thumbnail[1]/@url',
|
|
||||||
namespaces=ns)
|
|
||||||
assert url == ['file1.xy', 'file1.xy']
|
|
||||||
|
|
||||||
# There is one without a group
|
|
||||||
url = root.xpath('/rss/channel/item/media:thumbnail[1]/@url',
|
|
||||||
namespaces=ns)
|
|
||||||
assert url == ['file.xy']
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting Atom feed
|
|
||||||
root = etree.fromstring(self.fg.atom_str())
|
|
||||||
url = root.xpath('/a:feed/a:entry/media:group/media:thumbnail[1]/@url',
|
|
||||||
namespaces=ns)
|
|
||||||
assert url == ['file1.xy', 'file1.xy']
|
|
||||||
|
|
||||||
fe.media.thumbnail(thumbnail=[], replace=True)
|
|
||||||
assert fe.media.thumbnail() == []
|
|
|
@ -1,96 +0,0 @@
|
||||||
import unittest
|
|
||||||
|
|
||||||
from lxml import etree
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
|
|
||||||
|
|
||||||
class TestExtensionPodcast(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.fg = FeedGenerator()
|
|
||||||
self.fg.load_extension('podcast')
|
|
||||||
self.fg.title('title')
|
|
||||||
self.fg.link(href='http://example.com', rel='self')
|
|
||||||
self.fg.description('description')
|
|
||||||
|
|
||||||
def test_category_new(self):
|
|
||||||
self.fg.podcast.itunes_category([{'cat': 'Technology',
|
|
||||||
'sub': 'Podcasting'}])
|
|
||||||
self.fg.podcast.itunes_explicit('no')
|
|
||||||
self.fg.podcast.itunes_complete('no')
|
|
||||||
self.fg.podcast.itunes_new_feed_url('http://example.com/new-feed.rss')
|
|
||||||
self.fg.podcast.itunes_owner('John Doe', 'john@example.com')
|
|
||||||
ns = {'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
cat = root.xpath('/rss/channel/itunes:category/@text', namespaces=ns)
|
|
||||||
scat = root.xpath('/rss/channel/itunes:category/itunes:category/@text',
|
|
||||||
namespaces=ns)
|
|
||||||
assert cat[0] == 'Technology'
|
|
||||||
assert scat[0] == 'Podcasting'
|
|
||||||
|
|
||||||
def test_category(self):
|
|
||||||
self.fg.podcast.itunes_category('Technology', 'Podcasting')
|
|
||||||
self.fg.podcast.itunes_explicit('no')
|
|
||||||
self.fg.podcast.itunes_complete('no')
|
|
||||||
self.fg.podcast.itunes_new_feed_url('http://example.com/new-feed.rss')
|
|
||||||
self.fg.podcast.itunes_owner('John Doe', 'john@example.com')
|
|
||||||
ns = {'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
cat = root.xpath('/rss/channel/itunes:category/@text', namespaces=ns)
|
|
||||||
scat = root.xpath('/rss/channel/itunes:category/itunes:category/@text',
|
|
||||||
namespaces=ns)
|
|
||||||
assert cat[0] == 'Technology'
|
|
||||||
assert scat[0] == 'Podcasting'
|
|
||||||
|
|
||||||
def test_podcastItems(self):
|
|
||||||
fg = self.fg
|
|
||||||
fg.podcast.itunes_author('Lars Kiesow')
|
|
||||||
fg.podcast.itunes_block('x')
|
|
||||||
fg.podcast.itunes_complete(False)
|
|
||||||
fg.podcast.itunes_explicit('no')
|
|
||||||
fg.podcast.itunes_image('x.png')
|
|
||||||
fg.podcast.itunes_subtitle('x')
|
|
||||||
fg.podcast.itunes_summary('x')
|
|
||||||
assert fg.podcast.itunes_author() == 'Lars Kiesow'
|
|
||||||
assert fg.podcast.itunes_block() == 'x'
|
|
||||||
assert fg.podcast.itunes_complete() == 'no'
|
|
||||||
assert fg.podcast.itunes_explicit() == 'no'
|
|
||||||
assert fg.podcast.itunes_image() == 'x.png'
|
|
||||||
assert fg.podcast.itunes_subtitle() == 'x'
|
|
||||||
assert fg.podcast.itunes_summary() == 'x'
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
author = root.xpath('/rss/channel/itunes:author/text()', namespaces=ns)
|
|
||||||
assert author == ['Lars Kiesow']
|
|
||||||
|
|
||||||
def test_podcastEntryItems(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.podcast.itunes_author('Lars Kiesow')
|
|
||||||
fe.podcast.itunes_block('x')
|
|
||||||
fe.podcast.itunes_duration('00:01:30')
|
|
||||||
fe.podcast.itunes_explicit('no')
|
|
||||||
fe.podcast.itunes_image('x.png')
|
|
||||||
fe.podcast.itunes_is_closed_captioned('yes')
|
|
||||||
fe.podcast.itunes_order(1)
|
|
||||||
fe.podcast.itunes_subtitle('x')
|
|
||||||
fe.podcast.itunes_summary('x')
|
|
||||||
assert fe.podcast.itunes_author() == 'Lars Kiesow'
|
|
||||||
assert fe.podcast.itunes_block() == 'x'
|
|
||||||
assert fe.podcast.itunes_duration() == '00:01:30'
|
|
||||||
assert fe.podcast.itunes_explicit() == 'no'
|
|
||||||
assert fe.podcast.itunes_image() == 'x.png'
|
|
||||||
assert fe.podcast.itunes_is_closed_captioned()
|
|
||||||
assert fe.podcast.itunes_order() == 1
|
|
||||||
assert fe.podcast.itunes_subtitle() == 'x'
|
|
||||||
assert fe.podcast.itunes_summary() == 'x'
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
author = root.xpath('/rss/channel/item/itunes:author/text()',
|
|
||||||
namespaces=ns)
|
|
||||||
assert author == ['Lars Kiesow']
|
|
|
@ -1,40 +0,0 @@
|
||||||
import unittest
|
|
||||||
|
|
||||||
from lxml import etree
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
|
|
||||||
|
|
||||||
class TestExtensionSyndication(unittest.TestCase):
|
|
||||||
|
|
||||||
SYN_NS = {'sy': 'http://purl.org/rss/1.0/modules/syndication/'}
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.fg = FeedGenerator()
|
|
||||||
self.fg.load_extension('syndication')
|
|
||||||
self.fg.title('title')
|
|
||||||
self.fg.link(href='http://example.com', rel='self')
|
|
||||||
self.fg.description('description')
|
|
||||||
|
|
||||||
def test_update_period(self):
|
|
||||||
for period_type in ('hourly', 'daily', 'weekly', 'monthly', 'yearly'):
|
|
||||||
self.fg.syndication.update_period(period_type)
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
a = root.xpath('/rss/channel/sy:UpdatePeriod',
|
|
||||||
namespaces=self.SYN_NS)
|
|
||||||
assert a[0].text == period_type
|
|
||||||
|
|
||||||
def test_update_frequency(self):
|
|
||||||
for frequency in (1, 100, 2000, 100000):
|
|
||||||
self.fg.syndication.update_frequency(frequency)
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
a = root.xpath('/rss/channel/sy:UpdateFrequency',
|
|
||||||
namespaces=self.SYN_NS)
|
|
||||||
assert a[0].text == str(frequency)
|
|
||||||
|
|
||||||
def test_update_base(self):
|
|
||||||
base = '2000-01-01T12:00+00:00'
|
|
||||||
self.fg.syndication.update_base(base)
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
a = root.xpath('/rss/channel/sy:UpdateBase', namespaces=self.SYN_NS)
|
|
||||||
assert a[0].text == base
|
|
|
@ -1,38 +0,0 @@
|
||||||
import unittest
|
|
||||||
|
|
||||||
from lxml import etree
|
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
|
|
||||||
|
|
||||||
class TestExtensionTorrent(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.fg = FeedGenerator()
|
|
||||||
self.fg.load_extension('torrent')
|
|
||||||
self.fg.title('title')
|
|
||||||
self.fg.link(href='http://example.com', rel='self')
|
|
||||||
self.fg.description('description')
|
|
||||||
|
|
||||||
def test_podcastEntryItems(self):
|
|
||||||
fe = self.fg.add_item()
|
|
||||||
fe.title('y')
|
|
||||||
fe.torrent.filename('file.xy')
|
|
||||||
fe.torrent.infohash('123')
|
|
||||||
fe.torrent.contentlength('23')
|
|
||||||
fe.torrent.seeds('1')
|
|
||||||
fe.torrent.peers('2')
|
|
||||||
fe.torrent.verified('1')
|
|
||||||
assert fe.torrent.filename() == 'file.xy'
|
|
||||||
assert fe.torrent.infohash() == '123'
|
|
||||||
assert fe.torrent.contentlength() == '23'
|
|
||||||
assert fe.torrent.seeds() == '1'
|
|
||||||
assert fe.torrent.peers() == '2'
|
|
||||||
assert fe.torrent.verified() == '1'
|
|
||||||
|
|
||||||
# Check that we have the item in the resulting XML
|
|
||||||
ns = {'torrent': 'http://xmlns.ezrss.it/0.1/dtd/'}
|
|
||||||
root = etree.fromstring(self.fg.rss_str())
|
|
||||||
filename = root.xpath('/rss/channel/item/torrent:filename/text()',
|
|
||||||
namespaces=ns)
|
|
||||||
assert filename == ['file.xy']
|
|
|
@ -1,340 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests for a basic feed
|
|
||||||
|
|
||||||
These are test cases for a basic feed.
|
|
||||||
A basic feed does not contain entries so far.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import tempfile
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from lxml import etree
|
|
||||||
|
|
||||||
from feedgen.ext.dc import DcEntryExtension, DcExtension
|
|
||||||
from feedgen.feed import FeedGenerator
|
|
||||||
|
|
||||||
|
|
||||||
class TestSequenceFunctions(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
|
|
||||||
fg = FeedGenerator()
|
|
||||||
|
|
||||||
self.nsAtom = "http://www.w3.org/2005/Atom"
|
|
||||||
self.nsRss = "http://purl.org/rss/1.0/modules/content/"
|
|
||||||
|
|
||||||
self.feedId = 'http://lernfunk.de/media/654321'
|
|
||||||
self.title = 'Some Testfeed'
|
|
||||||
|
|
||||||
self.authorName = 'John Doe'
|
|
||||||
self.authorMail = 'john@example.de'
|
|
||||||
self.author = {'name': self.authorName, 'email': self.authorMail}
|
|
||||||
|
|
||||||
self.linkHref = 'http://example.com'
|
|
||||||
self.linkRel = 'alternate'
|
|
||||||
|
|
||||||
self.logo = 'http://ex.com/logo.jpg'
|
|
||||||
self.subtitle = 'This is a cool feed!'
|
|
||||||
|
|
||||||
self.link2Href = 'http://larskiesow.de/test.atom'
|
|
||||||
self.link2Rel = 'self'
|
|
||||||
|
|
||||||
self.language = 'en'
|
|
||||||
|
|
||||||
self.categoryTerm = 'This category term'
|
|
||||||
self.categoryScheme = 'This category scheme'
|
|
||||||
self.categoryLabel = 'This category label'
|
|
||||||
|
|
||||||
self.cloudDomain = 'example.com'
|
|
||||||
self.cloudPort = '4711'
|
|
||||||
self.cloudPath = '/ws/example'
|
|
||||||
self.cloudRegisterProcedure = 'registerProcedure'
|
|
||||||
self.cloudProtocol = 'SOAP 1.1'
|
|
||||||
|
|
||||||
self.icon = "http://example.com/icon.png"
|
|
||||||
self.contributor = {'name': "Contributor Name",
|
|
||||||
'uri': "Contributor Uri",
|
|
||||||
'email': 'Contributor email'}
|
|
||||||
self.copyright = "The copyright notice"
|
|
||||||
self.docs = 'http://www.rssboard.org/rss-specification'
|
|
||||||
self.managingEditor = 'mail@example.com'
|
|
||||||
self.rating = '(PICS-1.1 "http://www.classify.org/safesurf/" ' + \
|
|
||||||
'1 r (SS~~000 1))'
|
|
||||||
self.skipDays = 'Tuesday'
|
|
||||||
self.skipHours = 23
|
|
||||||
|
|
||||||
self.textInputTitle = "Text input title"
|
|
||||||
self.textInputDescription = "Text input description"
|
|
||||||
self.textInputName = "Text input name"
|
|
||||||
self.textInputLink = "Text input link"
|
|
||||||
|
|
||||||
self.ttl = 900
|
|
||||||
|
|
||||||
self.webMaster = 'webmaster@example.com'
|
|
||||||
|
|
||||||
fg.id(self.feedId)
|
|
||||||
fg.title(self.title)
|
|
||||||
fg.author(self.author)
|
|
||||||
fg.link(href=self.linkHref, rel=self.linkRel)
|
|
||||||
fg.logo(self.logo)
|
|
||||||
fg.subtitle(self.subtitle)
|
|
||||||
fg.link(href=self.link2Href, rel=self.link2Rel)
|
|
||||||
fg.language(self.language)
|
|
||||||
fg.cloud(domain=self.cloudDomain, port=self.cloudPort,
|
|
||||||
path=self.cloudPath,
|
|
||||||
registerProcedure=self.cloudRegisterProcedure,
|
|
||||||
protocol=self.cloudProtocol)
|
|
||||||
fg.icon(self.icon)
|
|
||||||
fg.category(term=self.categoryTerm, scheme=self.categoryScheme,
|
|
||||||
label=self.categoryLabel)
|
|
||||||
fg.contributor(self.contributor)
|
|
||||||
fg.copyright(self.copyright)
|
|
||||||
fg.docs(docs=self.docs)
|
|
||||||
fg.managingEditor(self.managingEditor)
|
|
||||||
fg.rating(self.rating)
|
|
||||||
fg.skipDays(self.skipDays)
|
|
||||||
fg.skipHours(self.skipHours)
|
|
||||||
fg.textInput(title=self.textInputTitle,
|
|
||||||
description=self.textInputDescription,
|
|
||||||
name=self.textInputName, link=self.textInputLink)
|
|
||||||
fg.ttl(self.ttl)
|
|
||||||
fg.webMaster(self.webMaster)
|
|
||||||
fg.updated('2017-02-05 13:26:58+01:00')
|
|
||||||
fg.pubDate('2017-02-05 13:26:58+01:00')
|
|
||||||
fg.generator('python-feedgen', 'x', uri='http://github.com/lkie...')
|
|
||||||
fg.image(url=self.logo,
|
|
||||||
title=self.title,
|
|
||||||
link=self.link2Href,
|
|
||||||
width='123',
|
|
||||||
height='123',
|
|
||||||
description='Example Inage')
|
|
||||||
|
|
||||||
self.fg = fg
|
|
||||||
|
|
||||||
def test_baseFeed(self):
|
|
||||||
fg = self.fg
|
|
||||||
|
|
||||||
assert fg.id() == self.feedId
|
|
||||||
assert fg.title() == self.title
|
|
||||||
|
|
||||||
assert fg.author()[0]['name'] == self.authorName
|
|
||||||
assert fg.author()[0]['email'] == self.authorMail
|
|
||||||
|
|
||||||
assert fg.link()[0]['href'] == self.linkHref
|
|
||||||
assert fg.link()[0]['rel'] == self.linkRel
|
|
||||||
|
|
||||||
assert fg.logo() == self.logo
|
|
||||||
assert fg.subtitle() == self.subtitle
|
|
||||||
|
|
||||||
assert fg.link()[1]['href'] == self.link2Href
|
|
||||||
assert fg.link()[1]['rel'] == self.link2Rel
|
|
||||||
|
|
||||||
assert fg.language() == self.language
|
|
||||||
|
|
||||||
def test_atomFeedFile(self):
|
|
||||||
fg = self.fg
|
|
||||||
fh, filename = tempfile.mkstemp()
|
|
||||||
fg.atom_file(filename=filename, pretty=True, xml_declaration=False)
|
|
||||||
|
|
||||||
with open(filename, "r") as myfile:
|
|
||||||
atomString = myfile.read().replace('\n', '')
|
|
||||||
|
|
||||||
self.checkAtomString(atomString)
|
|
||||||
os.close(fh)
|
|
||||||
os.remove(filename)
|
|
||||||
|
|
||||||
def test_atomFeedString(self):
|
|
||||||
fg = self.fg
|
|
||||||
|
|
||||||
atomString = fg.atom_str(pretty=True, xml_declaration=False)
|
|
||||||
self.checkAtomString(atomString)
|
|
||||||
|
|
||||||
def test_rel_values_for_atom(self):
|
|
||||||
values_for_rel = [
|
|
||||||
'about', 'alternate', 'appendix', 'archives', 'author', 'bookmark',
|
|
||||||
'canonical', 'chapter', 'collection', 'contents', 'copyright',
|
|
||||||
'create-form', 'current', 'derivedfrom', 'describedby',
|
|
||||||
'describes', 'disclosure', 'duplicate', 'edit', 'edit-form',
|
|
||||||
'edit-media', 'enclosure', 'first', 'glossary', 'help', 'hosts',
|
|
||||||
'hub', 'icon', 'index', 'item', 'last', 'latest-version',
|
|
||||||
'license', 'lrdd', 'memento', 'monitor', 'monitor-group', 'next',
|
|
||||||
'next-archive', 'nofollow', 'noreferrer', 'original', 'payment',
|
|
||||||
'predecessor-version', 'prefetch', 'prev', 'preview', 'previous',
|
|
||||||
'prev-archive', 'privacy-policy', 'profile', 'related', 'replies',
|
|
||||||
'search', 'section', 'self', 'service', 'start', 'stylesheet',
|
|
||||||
'subsection', 'successor-version', 'tag', 'terms-of-service',
|
|
||||||
'timegate', 'timemap', 'type', 'up', 'version-history', 'via',
|
|
||||||
'working-copy', 'working-copy-of']
|
|
||||||
links = [{'href': '%s/%s' % (self.linkHref,
|
|
||||||
val.replace('-', '_')), 'rel': val}
|
|
||||||
for val in values_for_rel]
|
|
||||||
fg = self.fg
|
|
||||||
fg.link(links, replace=True)
|
|
||||||
atomString = fg.atom_str(pretty=True, xml_declaration=False)
|
|
||||||
feed = etree.fromstring(atomString)
|
|
||||||
nsAtom = self.nsAtom
|
|
||||||
feed_links = feed.findall("{%s}link" % nsAtom)
|
|
||||||
idx = 0
|
|
||||||
assert len(links) == len(feed_links)
|
|
||||||
while idx < len(values_for_rel):
|
|
||||||
assert feed_links[idx].get('href') == links[idx]['href']
|
|
||||||
assert feed_links[idx].get('rel') == links[idx]['rel']
|
|
||||||
idx += 1
|
|
||||||
|
|
||||||
def test_rel_values_for_rss(self):
|
|
||||||
values_for_rel = [
|
|
||||||
'about', 'alternate', 'appendix', 'archives', 'author', 'bookmark',
|
|
||||||
'canonical', 'chapter', 'collection', 'contents', 'copyright',
|
|
||||||
'create-form', 'current', 'derivedfrom', 'describedby',
|
|
||||||
'describes', 'disclosure', 'duplicate', 'edit', 'edit-form',
|
|
||||||
'edit-media', 'enclosure', 'first', 'glossary', 'help', 'hosts',
|
|
||||||
'hub', 'icon', 'index', 'item', 'last', 'latest-version',
|
|
||||||
'license', 'lrdd', 'memento', 'monitor', 'monitor-group', 'next',
|
|
||||||
'next-archive', 'nofollow', 'noreferrer', 'original', 'payment',
|
|
||||||
'predecessor-version', 'prefetch', 'prev', 'preview', 'previous',
|
|
||||||
'prev-archive', 'privacy-policy', 'profile', 'related', 'replies',
|
|
||||||
'search', 'section', 'self', 'service', 'start', 'stylesheet',
|
|
||||||
'subsection', 'successor-version', 'tag', 'terms-of-service',
|
|
||||||
'timegate', 'timemap', 'type', 'up', 'version-history', 'via',
|
|
||||||
'working-copy', 'working-copy-of']
|
|
||||||
links = [{'href': '%s/%s' % (self.linkHref,
|
|
||||||
val.replace('-', '_')), 'rel': val}
|
|
||||||
for val in values_for_rel]
|
|
||||||
fg = self.fg
|
|
||||||
fg.link(links, replace=True)
|
|
||||||
rssString = fg.rss_str(pretty=True, xml_declaration=False)
|
|
||||||
feed = etree.fromstring(rssString)
|
|
||||||
channel = feed.find("channel")
|
|
||||||
nsAtom = self.nsAtom
|
|
||||||
|
|
||||||
atom_links = channel.findall("{%s}link" % nsAtom)
|
|
||||||
# rss feed only implements atom's 'self' link
|
|
||||||
assert len(atom_links) == 1
|
|
||||||
assert atom_links[0].get('href') == '%s/%s' % (self.linkHref, 'self')
|
|
||||||
assert atom_links[0].get('rel') == 'self'
|
|
||||||
|
|
||||||
rss_links = channel.findall('link')
|
|
||||||
# RSS only needs one URL. We use the first link for RSS:
|
|
||||||
assert len(rss_links) == 1
|
|
||||||
assert rss_links[0].text == '%s/%s' % \
|
|
||||||
(self.linkHref, 'working-copy-of'.replace('-', '_'))
|
|
||||||
|
|
||||||
def checkAtomString(self, atomString):
|
|
||||||
|
|
||||||
feed = etree.fromstring(atomString)
|
|
||||||
|
|
||||||
nsAtom = self.nsAtom
|
|
||||||
|
|
||||||
assert feed.find("{%s}title" % nsAtom).text == self.title
|
|
||||||
assert feed.find("{%s}updated" % nsAtom).text is not None
|
|
||||||
assert feed.find("{%s}id" % nsAtom).text == self.feedId
|
|
||||||
assert feed.find("{%s}category" % nsAtom)\
|
|
||||||
.get('term') == self.categoryTerm
|
|
||||||
assert feed.find("{%s}category" % nsAtom)\
|
|
||||||
.get('label') == self.categoryLabel
|
|
||||||
assert feed.find("{%s}author" % nsAtom)\
|
|
||||||
.find("{%s}name" % nsAtom).text == self.authorName
|
|
||||||
assert feed.find("{%s}author" % nsAtom)\
|
|
||||||
.find("{%s}email" % nsAtom).text == self.authorMail
|
|
||||||
assert feed.findall("{%s}link" % nsAtom)[0]\
|
|
||||||
.get('href') == self.linkHref
|
|
||||||
assert feed.findall("{%s}link" % nsAtom)[0].get('rel') == self.linkRel
|
|
||||||
assert feed.findall("{%s}link" % nsAtom)[1]\
|
|
||||||
.get('href') == self.link2Href
|
|
||||||
assert feed.findall("{%s}link" % nsAtom)[1].get('rel') == self.link2Rel
|
|
||||||
assert feed.find("{%s}logo" % nsAtom).text == self.logo
|
|
||||||
assert feed.find("{%s}icon" % nsAtom).text == self.icon
|
|
||||||
assert feed.find("{%s}subtitle" % nsAtom).text == self.subtitle
|
|
||||||
assert feed.find("{%s}contributor" % nsAtom)\
|
|
||||||
.find("{%s}name" % nsAtom).text == self.contributor['name']
|
|
||||||
assert feed.find("{%s}contributor" % nsAtom)\
|
|
||||||
.find("{%s}email" % nsAtom).text == self.contributor['email']
|
|
||||||
assert feed.find("{%s}contributor" % nsAtom)\
|
|
||||||
.find("{%s}uri" % nsAtom).text == self.contributor['uri']
|
|
||||||
assert feed.find("{%s}rights" % nsAtom).text == self.copyright
|
|
||||||
|
|
||||||
def test_rssFeedFile(self):
|
|
||||||
fg = self.fg
|
|
||||||
_, filename = tempfile.mkstemp()
|
|
||||||
fg.rss_file(filename=filename, pretty=True, xml_declaration=False)
|
|
||||||
|
|
||||||
with open(filename, "r") as myfile:
|
|
||||||
rssString = myfile.read().replace('\n', '')
|
|
||||||
|
|
||||||
self.checkRssString(rssString)
|
|
||||||
|
|
||||||
def test_rssFeedString(self):
|
|
||||||
fg = self.fg
|
|
||||||
rssString = fg.rss_str(pretty=True, xml_declaration=False)
|
|
||||||
self.checkRssString(rssString)
|
|
||||||
|
|
||||||
def test_loadPodcastExtension(self):
|
|
||||||
fg = self.fg
|
|
||||||
fg.add_entry()
|
|
||||||
fg.load_extension('podcast', atom=True, rss=True)
|
|
||||||
fg.add_entry()
|
|
||||||
|
|
||||||
def test_loadDcExtension(self):
|
|
||||||
fg = self.fg
|
|
||||||
fg.add_entry()
|
|
||||||
fg.load_extension('dc', atom=True, rss=True)
|
|
||||||
fg.add_entry()
|
|
||||||
|
|
||||||
def test_extensionAlreadyLoaded(self):
|
|
||||||
fg = self.fg
|
|
||||||
fg.load_extension('dc', atom=True, rss=True)
|
|
||||||
with self.assertRaises(ImportError):
|
|
||||||
fg.load_extension('dc')
|
|
||||||
|
|
||||||
def test_registerCustomExtension(self):
|
|
||||||
fg = self.fg
|
|
||||||
fg.add_entry()
|
|
||||||
fg.register_extension('dc', DcExtension, DcEntryExtension)
|
|
||||||
fg.add_entry()
|
|
||||||
|
|
||||||
def checkRssString(self, rssString):
|
|
||||||
|
|
||||||
feed = etree.fromstring(rssString)
|
|
||||||
nsAtom = self.nsAtom
|
|
||||||
|
|
||||||
ch = feed.find("channel")
|
|
||||||
assert ch is not None
|
|
||||||
|
|
||||||
assert ch.find("title").text == self.title
|
|
||||||
assert ch.find("description").text == self.subtitle
|
|
||||||
assert ch.find("lastBuildDate").text is not None
|
|
||||||
docs = "http://www.rssboard.org/rss-specification"
|
|
||||||
assert ch.find("docs").text == docs
|
|
||||||
assert ch.find("generator").text == "python-feedgen"
|
|
||||||
assert ch.findall("{%s}link" % nsAtom)[0].get('href') == self.link2Href
|
|
||||||
assert ch.findall("{%s}link" % nsAtom)[0].get('rel') == self.link2Rel
|
|
||||||
assert ch.find("image").find("url").text == self.logo
|
|
||||||
assert ch.find("image").find("title").text == self.title
|
|
||||||
assert ch.find("image").find("link").text == self.link2Href
|
|
||||||
assert ch.find("category").text == self.categoryLabel
|
|
||||||
assert ch.find("cloud").get('domain') == self.cloudDomain
|
|
||||||
assert ch.find("cloud").get('port') == self.cloudPort
|
|
||||||
assert ch.find("cloud").get('path') == self.cloudPath
|
|
||||||
assert ch.find("cloud").get('registerProcedure') == \
|
|
||||||
self.cloudRegisterProcedure
|
|
||||||
assert ch.find("cloud").get('protocol') == self.cloudProtocol
|
|
||||||
assert ch.find("copyright").text == self.copyright
|
|
||||||
assert ch.find("docs").text == self.docs
|
|
||||||
assert ch.find("managingEditor").text == self.managingEditor
|
|
||||||
assert ch.find("rating").text == self.rating
|
|
||||||
assert ch.find("skipDays").find("day").text == self.skipDays
|
|
||||||
assert int(ch.find("skipHours").find("hour").text) == self.skipHours
|
|
||||||
assert ch.find("textInput").get('title') == self.textInputTitle
|
|
||||||
assert ch.find("textInput").get('description') == \
|
|
||||||
self.textInputDescription
|
|
||||||
assert ch.find("textInput").get('name') == self.textInputName
|
|
||||||
assert ch.find("textInput").get('link') == self.textInputLink
|
|
||||||
assert int(ch.find("ttl").text) == self.ttl
|
|
||||||
assert ch.find("webMaster").text == self.webMaster
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
|
@ -1,42 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
'''
|
|
||||||
Tests for feedgen main
|
|
||||||
'''
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from feedgen import __main__
|
|
||||||
|
|
||||||
|
|
||||||
class TestSequenceFunctions(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_usage(self):
|
|
||||||
sys.argv = ['feedgen']
|
|
||||||
try:
|
|
||||||
__main__.main()
|
|
||||||
except BaseException as e:
|
|
||||||
assert e.code is None
|
|
||||||
|
|
||||||
def test_feed(self):
|
|
||||||
for ftype in 'rss', 'atom', 'podcast', 'torrent', 'dc.rss', 'dc.atom',\
|
|
||||||
'syndication.rss', 'syndication.atom':
|
|
||||||
sys.argv = ['feedgen', ftype]
|
|
||||||
try:
|
|
||||||
__main__.main()
|
|
||||||
except Exception:
|
|
||||||
assert False
|
|
||||||
|
|
||||||
def test_file(self):
|
|
||||||
for extemsion in '.atom', '.rss':
|
|
||||||
fh, filename = tempfile.mkstemp(extemsion)
|
|
||||||
sys.argv = ['feedgen', filename]
|
|
||||||
try:
|
|
||||||
__main__.main()
|
|
||||||
except Exception:
|
|
||||||
assert False
|
|
||||||
os.close(fh)
|
|
||||||
os.remove(filename)
|
|