[Reproducible-commits] [sphinx] 01/03: imported from sphinx_1.2.3+dfsg.orig.tar.gz
Holger Levsen
holger at moszumanska.debian.org
Mon Mar 23 12:53:42 UTC 2015
This is an automated email from the git hooks/post-receive script.
holger pushed a commit to branch pu/reproducible_builds
in repository sphinx.
commit b54b09b384513f58530a3f5fcc1327c289779703
Author: Holger Levsen <holger at layer-acht.org>
Date: Mon Mar 23 13:50:09 2015 +0100
imported from sphinx_1.2.3+dfsg.orig.tar.gz
---
AUTHORS | 54 +
CHANGES | 1194 ++++++++++++++
EXAMPLES | 234 +++
LICENSE | 246 +++
MANIFEST.in | 27 +
Makefile | 64 +
PKG-INFO | 51 +
README.rst | 42 +
Sphinx.egg-info/PKG-INFO | 51 +
Sphinx.egg-info/SOURCES.txt | 617 +++++++
Sphinx.egg-info/dependency_links.txt | 1 +
Sphinx.egg-info/entry_points.txt | 9 +
Sphinx.egg-info/not-zip-safe | 1 +
Sphinx.egg-info/requires.txt | 3 +
Sphinx.egg-info/top_level.txt | 1 +
TODO | 5 +
babel.cfg | 21 +
custom_fixers/__init__.py | 0
custom_fixers/fix_alt_unicode.py | 12 +
doc/Makefile | 18 +
doc/_static/bookcover.png | Bin 0 -> 31844 bytes
doc/_static/pocoo.png | Bin 0 -> 2191 bytes
doc/_static/sphinx.png | Bin 0 -> 42490 bytes
doc/_templates/index.html | 100 ++
doc/_templates/indexsidebar.html | 33 +
doc/_themes/sphinx13/layout.html | 78 +
doc/_themes/sphinx13/static/bodybg.png | Bin 0 -> 602 bytes
doc/_themes/sphinx13/static/footerbg.png | Bin 0 -> 313 bytes
doc/_themes/sphinx13/static/headerbg.png | Bin 0 -> 344 bytes
doc/_themes/sphinx13/static/listitem.png | Bin 0 -> 207 bytes
doc/_themes/sphinx13/static/relbg.png | Bin 0 -> 332 bytes
doc/_themes/sphinx13/static/sphinx13.css | 396 +++++
doc/_themes/sphinx13/static/sphinxheader.png | Bin 0 -> 16255 bytes
doc/_themes/sphinx13/theme.conf | 4 +
doc/builders.rst | 419 +++++
doc/changes.rst | 8 +
doc/conf.py | 124 ++
doc/config.rst | 1459 +++++++++++++++++
doc/contents.rst | 37 +
doc/develop.rst | 133 ++
doc/devguide.rst | 245 +++
doc/domains.rst | 848 ++++++++++
doc/examples.rst | 5 +
doc/ext/autodoc.rst | 429 +++++
doc/ext/autosummary.rst | 233 +++
doc/ext/coverage.rst | 44 +
doc/ext/doctest.rst | 240 +++
doc/ext/extlinks.rst | 54 +
doc/ext/graphviz.rst | 113 ++
doc/ext/ifconfig.rst | 33 +
doc/ext/inheritance.rst | 63 +
doc/ext/intersphinx.rst | 109 ++
doc/ext/linkcode.rst | 46 +
doc/ext/math.rst | 241 +++
doc/ext/oldcmarkup.rst | 35 +
doc/ext/todo.rst | 30 +
doc/ext/viewcode.rst | 19 +
doc/extdev/appapi.rst | 595 +++++++
doc/extdev/builderapi.rst | 30 +
doc/extdev/domainapi.rst | 14 +
doc/extdev/envapi.rst | 54 +
doc/extdev/index.rst | 33 +
doc/extdev/markupapi.rst | 139 ++
doc/extdev/nodes.rst | 57 +
doc/extdev/tutorial.rst | 397 +++++
doc/extensions.rst | 71 +
doc/faq.rst | 268 ++++
doc/glossary.rst | 83 +
doc/install.rst | 151 ++
doc/installpython.jpg | Bin 0 -> 28408 bytes
doc/intl.rst | 298 ++++
doc/intro.rst | 72 +
doc/invocation.rst | 314 ++++
doc/man/sphinx-apidoc.rst | 68 +
doc/man/sphinx-build.rst | 130 ++
doc/man/sphinx-quickstart.rst | 33 +
doc/markup/code.rst | 183 +++
doc/markup/index.rst | 19 +
doc/markup/inline.rst | 371 +++++
doc/markup/misc.rst | 259 +++
doc/markup/para.rst | 231 +++
doc/markup/toctree.rst | 222 +++
doc/more.png | Bin 0 -> 1502 bytes
doc/pythonorg.png | Bin 0 -> 187195 bytes
doc/rest.rst | 489 ++++++
doc/templating.rst | 397 +++++
doc/themes/agogo.png | Bin 0 -> 38724 bytes
doc/themes/default.png | Bin 0 -> 57108 bytes
doc/themes/fullsize/agogo.png | Bin 0 -> 75005 bytes
doc/themes/fullsize/default.png | Bin 0 -> 96831 bytes
doc/themes/fullsize/haiku.png | Bin 0 -> 104662 bytes
doc/themes/fullsize/nature.png | Bin 0 -> 44469 bytes
doc/themes/fullsize/pyramid.png | Bin 0 -> 131965 bytes
doc/themes/fullsize/scrolls.png | Bin 0 -> 121464 bytes
doc/themes/fullsize/sphinxdoc.png | Bin 0 -> 99682 bytes
doc/themes/fullsize/traditional.png | Bin 0 -> 108985 bytes
doc/themes/haiku.png | Bin 0 -> 54252 bytes
doc/themes/nature.png | Bin 0 -> 42295 bytes
doc/themes/pyramid.png | Bin 0 -> 49630 bytes
doc/themes/scrolls.png | Bin 0 -> 44266 bytes
doc/themes/sphinxdoc.png | Bin 0 -> 42982 bytes
doc/themes/traditional.png | Bin 0 -> 45762 bytes
doc/theming.rst | 321 ++++
doc/translation.png | Bin 0 -> 40683 bytes
doc/tutorial.rst | 309 ++++
doc/web/api.rst | 65 +
doc/web/quickstart.rst | 254 +++
doc/web/searchadapters.rst | 45 +
doc/web/storagebackends.rst | 44 +
doc/websupport.rst | 16 +
ez_setup.py | 370 +++++
setup.cfg | 23 +
setup.py | 204 +++
sphinx-apidoc.py | 15 +
sphinx-autogen.py | 15 +
sphinx-build.py | 15 +
sphinx-quickstart.py | 15 +
sphinx/__init__.py | 97 ++
sphinx/addnodes.py | 181 +++
sphinx/apidoc.py | 363 +++++
sphinx/application.py | 656 ++++++++
sphinx/builders/__init__.py | 459 ++++++
sphinx/builders/changes.py | 162 ++
sphinx/builders/devhelp.py | 133 ++
sphinx/builders/epub.py | 761 +++++++++
sphinx/builders/gettext.py | 218 +++
sphinx/builders/html.py | 1107 +++++++++++++
sphinx/builders/htmlhelp.py | 299 ++++
sphinx/builders/latex.py | 183 +++
sphinx/builders/linkcheck.py | 264 +++
sphinx/builders/manpage.py | 93 ++
sphinx/builders/qthelp.py | 296 ++++
sphinx/builders/texinfo.py | 228 +++
sphinx/builders/text.py | 72 +
sphinx/builders/websupport.py | 160 ++
sphinx/builders/xml.py | 99 ++
sphinx/cmdline.py | 296 ++++
sphinx/config.py | 284 ++++
sphinx/directives/__init__.py | 192 +++
sphinx/directives/code.py | 219 +++
sphinx/directives/other.py | 418 +++++
sphinx/domains/__init__.py | 261 +++
sphinx/domains/c.py | 253 +++
sphinx/domains/cpp.py | 1317 +++++++++++++++
sphinx/domains/javascript.py | 220 +++
sphinx/domains/python.py | 710 +++++++++
sphinx/domains/rst.py | 137 ++
sphinx/domains/std.py | 639 ++++++++
sphinx/environment.py | 1677 ++++++++++++++++++++
sphinx/errors.py | 64 +
sphinx/ext/__init__.py | 10 +
sphinx/ext/autodoc.py | 1480 +++++++++++++++++
sphinx/ext/autosummary/__init__.py | 570 +++++++
sphinx/ext/autosummary/generate.py | 337 ++++
.../ext/autosummary/templates/autosummary/base.rst | 6 +
.../autosummary/templates/autosummary/class.rst | 30 +
.../autosummary/templates/autosummary/module.rst | 37 +
sphinx/ext/coverage.py | 265 ++++
sphinx/ext/doctest.py | 437 +++++
sphinx/ext/extlinks.py | 59 +
sphinx/ext/graphviz.py | 323 ++++
sphinx/ext/ifconfig.py | 74 +
sphinx/ext/inheritance_diagram.py | 407 +++++
sphinx/ext/intersphinx.py | 271 ++++
sphinx/ext/jsmath.py | 58 +
sphinx/ext/linkcode.py | 72 +
sphinx/ext/mathbase.py | 200 +++
sphinx/ext/mathjax.py | 68 +
sphinx/ext/oldcmarkup.py | 67 +
sphinx/ext/pngmath.py | 249 +++
sphinx/ext/todo.py | 174 ++
sphinx/ext/viewcode.py | 177 +++
sphinx/highlighting.py | 240 +++
sphinx/jinja2glue.py | 153 ++
sphinx/locale/.tx/config | 8 +
sphinx/locale/__init__.py | 225 +++
sphinx/locale/bn/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/bn/LC_MESSAGES/sphinx.mo | Bin 0 -> 13429 bytes
sphinx/locale/bn/LC_MESSAGES/sphinx.po | 840 ++++++++++
sphinx/locale/ca/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/ca/LC_MESSAGES/sphinx.mo | Bin 0 -> 10283 bytes
sphinx/locale/ca/LC_MESSAGES/sphinx.po | 838 ++++++++++
sphinx/locale/cs/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/cs/LC_MESSAGES/sphinx.mo | Bin 0 -> 10415 bytes
sphinx/locale/cs/LC_MESSAGES/sphinx.po | 838 ++++++++++
sphinx/locale/da/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/da/LC_MESSAGES/sphinx.mo | Bin 0 -> 10171 bytes
sphinx/locale/da/LC_MESSAGES/sphinx.po | 838 ++++++++++
sphinx/locale/de/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/de/LC_MESSAGES/sphinx.mo | Bin 0 -> 10500 bytes
sphinx/locale/de/LC_MESSAGES/sphinx.po | 841 ++++++++++
sphinx/locale/es/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/es/LC_MESSAGES/sphinx.mo | Bin 0 -> 10815 bytes
sphinx/locale/es/LC_MESSAGES/sphinx.po | 846 ++++++++++
sphinx/locale/et/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/et/LC_MESSAGES/sphinx.mo | Bin 0 -> 10208 bytes
sphinx/locale/et/LC_MESSAGES/sphinx.po | 837 ++++++++++
sphinx/locale/eu/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/eu/LC_MESSAGES/sphinx.mo | Bin 0 -> 10364 bytes
sphinx/locale/eu/LC_MESSAGES/sphinx.po | 836 ++++++++++
sphinx/locale/fa/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/fa/LC_MESSAGES/sphinx.mo | Bin 0 -> 10844 bytes
sphinx/locale/fa/LC_MESSAGES/sphinx.po | 831 ++++++++++
sphinx/locale/fi/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/fi/LC_MESSAGES/sphinx.mo | Bin 0 -> 9912 bytes
sphinx/locale/fi/LC_MESSAGES/sphinx.po | 830 ++++++++++
sphinx/locale/fr/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/fr/LC_MESSAGES/sphinx.mo | Bin 0 -> 10712 bytes
sphinx/locale/fr/LC_MESSAGES/sphinx.po | 849 ++++++++++
sphinx/locale/he/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/he/LC_MESSAGES/sphinx.mo | Bin 0 -> 10726 bytes
sphinx/locale/he/LC_MESSAGES/sphinx.po | 832 ++++++++++
sphinx/locale/hr/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/hr/LC_MESSAGES/sphinx.mo | Bin 0 -> 10283 bytes
sphinx/locale/hr/LC_MESSAGES/sphinx.po | 838 ++++++++++
sphinx/locale/hu/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/hu/LC_MESSAGES/sphinx.mo | Bin 0 -> 10765 bytes
sphinx/locale/hu/LC_MESSAGES/sphinx.po | 840 ++++++++++
sphinx/locale/id/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/id/LC_MESSAGES/sphinx.mo | Bin 0 -> 10159 bytes
sphinx/locale/id/LC_MESSAGES/sphinx.po | 842 ++++++++++
sphinx/locale/it/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/it/LC_MESSAGES/sphinx.mo | Bin 0 -> 10579 bytes
sphinx/locale/it/LC_MESSAGES/sphinx.po | 845 ++++++++++
sphinx/locale/ja/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/ja/LC_MESSAGES/sphinx.mo | Bin 0 -> 11082 bytes
sphinx/locale/ja/LC_MESSAGES/sphinx.po | 837 ++++++++++
sphinx/locale/ko/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/ko/LC_MESSAGES/sphinx.mo | Bin 0 -> 10153 bytes
sphinx/locale/ko/LC_MESSAGES/sphinx.po | 829 ++++++++++
sphinx/locale/lt/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/lt/LC_MESSAGES/sphinx.mo | Bin 0 -> 10606 bytes
sphinx/locale/lt/LC_MESSAGES/sphinx.po | 840 ++++++++++
sphinx/locale/lv/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/lv/LC_MESSAGES/sphinx.mo | Bin 0 -> 10503 bytes
sphinx/locale/lv/LC_MESSAGES/sphinx.po | 837 ++++++++++
sphinx/locale/mk/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/mk/LC_MESSAGES/sphinx.mo | Bin 0 -> 10421 bytes
sphinx/locale/mk/LC_MESSAGES/sphinx.po | 830 ++++++++++
sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo | Bin 0 -> 10000 bytes
sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po | 832 ++++++++++
sphinx/locale/ne/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/ne/LC_MESSAGES/sphinx.mo | Bin 0 -> 12972 bytes
sphinx/locale/ne/LC_MESSAGES/sphinx.po | 834 ++++++++++
sphinx/locale/nl/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/nl/LC_MESSAGES/sphinx.mo | Bin 0 -> 10242 bytes
sphinx/locale/nl/LC_MESSAGES/sphinx.po | 838 ++++++++++
sphinx/locale/pl/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/pl/LC_MESSAGES/sphinx.mo | Bin 0 -> 10459 bytes
sphinx/locale/pl/LC_MESSAGES/sphinx.po | 843 ++++++++++
sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo | Bin 0 -> 10665 bytes
sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po | 846 ++++++++++
sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo | Bin 0 -> 10646 bytes
sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po | 844 ++++++++++
sphinx/locale/ru/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/ru/LC_MESSAGES/sphinx.mo | Bin 0 -> 13029 bytes
sphinx/locale/ru/LC_MESSAGES/sphinx.po | 841 ++++++++++
sphinx/locale/si/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/si/LC_MESSAGES/sphinx.mo | Bin 0 -> 10930 bytes
sphinx/locale/si/LC_MESSAGES/sphinx.po | 830 ++++++++++
sphinx/locale/sk/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/sk/LC_MESSAGES/sphinx.mo | Bin 0 -> 10432 bytes
sphinx/locale/sk/LC_MESSAGES/sphinx.po | 842 ++++++++++
sphinx/locale/sl/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/sl/LC_MESSAGES/sphinx.mo | Bin 0 -> 10221 bytes
sphinx/locale/sl/LC_MESSAGES/sphinx.po | 838 ++++++++++
sphinx/locale/sphinx.pot | 819 ++++++++++
sphinx/locale/sv/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/sv/LC_MESSAGES/sphinx.mo | Bin 0 -> 10028 bytes
sphinx/locale/sv/LC_MESSAGES/sphinx.po | 834 ++++++++++
sphinx/locale/tr/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/tr/LC_MESSAGES/sphinx.mo | Bin 0 -> 10561 bytes
sphinx/locale/tr/LC_MESSAGES/sphinx.po | 841 ++++++++++
sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo | Bin 0 -> 11854 bytes
sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po | 840 ++++++++++
sphinx/locale/vi/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/vi/LC_MESSAGES/sphinx.mo | Bin 0 -> 10672 bytes
sphinx/locale/vi/LC_MESSAGES/sphinx.po | 834 ++++++++++
sphinx/locale/zh_CN/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo | Bin 0 -> 9754 bytes
sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po | 833 ++++++++++
sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js | 1 +
sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo | Bin 0 -> 10047 bytes
sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po | 830 ++++++++++
sphinx/make_mode.py | 259 +++
sphinx/pycode/Grammar-py2.txt | 135 ++
sphinx/pycode/Grammar-py3.txt | 126 ++
sphinx/pycode/__init__.py | 347 ++++
sphinx/pycode/nodes.py | 207 +++
sphinx/pycode/pgen2/__init__.py | 4 +
sphinx/pycode/pgen2/driver.py | 148 ++
sphinx/pycode/pgen2/grammar.py | 172 ++
sphinx/pycode/pgen2/literals.py | 96 ++
sphinx/pycode/pgen2/parse.py | 201 +++
sphinx/pycode/pgen2/pgen.py | 384 +++++
sphinx/pycode/pgen2/token.py | 83 +
sphinx/pycode/pgen2/tokenize.py | 412 +++++
sphinx/pygments_styles.py | 96 ++
sphinx/quickstart.py | 1284 +++++++++++++++
sphinx/roles.py | 317 ++++
sphinx/search/__init__.py | 333 ++++
sphinx/search/en.py | 244 +++
sphinx/search/ja.py | 276 ++++
sphinx/setup_command.py | 177 +++
sphinx/texinputs/Makefile | 66 +
sphinx/texinputs/fncychap.sty | 683 ++++++++
sphinx/texinputs/python.ist | 11 +
sphinx/texinputs/sphinx.sty | 524 ++++++
sphinx/texinputs/sphinxhowto.cls | 104 ++
sphinx/texinputs/sphinxmanual.cls | 148 ++
sphinx/texinputs/tabulary.sty | 452 ++++++
sphinx/themes/agogo/layout.html | 92 ++
sphinx/themes/agogo/static/agogo.css_t | 464 ++++++
sphinx/themes/agogo/static/bgfooter.png | Bin 0 -> 434 bytes
sphinx/themes/agogo/static/bgtop.png | Bin 0 -> 430 bytes
sphinx/themes/agogo/theme.conf | 19 +
sphinx/themes/basic/changes/frameset.html | 11 +
sphinx/themes/basic/changes/rstsource.html | 15 +
sphinx/themes/basic/changes/versionchanges.html | 33 +
sphinx/themes/basic/defindex.html | 35 +
sphinx/themes/basic/domainindex.html | 56 +
sphinx/themes/basic/genindex-single.html | 65 +
sphinx/themes/basic/genindex-split.html | 41 +
sphinx/themes/basic/genindex.html | 77 +
sphinx/themes/basic/globaltoc.html | 11 +
sphinx/themes/basic/layout.html | 203 +++
sphinx/themes/basic/localtoc.html | 13 +
sphinx/themes/basic/opensearch.xml | 10 +
sphinx/themes/basic/page.html | 13 +
sphinx/themes/basic/relations.html | 19 +
sphinx/themes/basic/search.html | 59 +
sphinx/themes/basic/searchbox.html | 24 +
sphinx/themes/basic/searchresults.html | 36 +
sphinx/themes/basic/sourcelink.html | 16 +
sphinx/themes/basic/static/ajax-loader.gif | Bin 0 -> 673 bytes
sphinx/themes/basic/static/basic.css_t | 537 +++++++
sphinx/themes/basic/static/comment-bright.png | Bin 0 -> 3500 bytes
sphinx/themes/basic/static/comment-close.png | Bin 0 -> 3578 bytes
sphinx/themes/basic/static/comment.png | Bin 0 -> 3445 bytes
sphinx/themes/basic/static/doctools.js | 238 +++
sphinx/themes/basic/static/down-pressed.png | Bin 0 -> 368 bytes
sphinx/themes/basic/static/down.png | Bin 0 -> 363 bytes
sphinx/themes/basic/static/file.png | Bin 0 -> 392 bytes
sphinx/themes/basic/static/minus.png | Bin 0 -> 199 bytes
sphinx/themes/basic/static/plus.png | Bin 0 -> 199 bytes
sphinx/themes/basic/static/searchtools.js_t | 442 ++++++
sphinx/themes/basic/static/up-pressed.png | Bin 0 -> 372 bytes
sphinx/themes/basic/static/up.png | Bin 0 -> 363 bytes
sphinx/themes/basic/static/websupport.js | 808 ++++++++++
sphinx/themes/basic/theme.conf | 8 +
sphinx/themes/default/layout.html | 14 +
sphinx/themes/default/static/default.css_t | 310 ++++
sphinx/themes/default/static/sidebar.js_t | 165 ++
sphinx/themes/default/theme.conf | 32 +
sphinx/themes/epub/epub-cover.html | 25 +
sphinx/themes/epub/layout.html | 29 +
sphinx/themes/epub/static/epub.css | 534 +++++++
sphinx/themes/epub/theme.conf | 8 +
sphinx/themes/haiku/layout.html | 66 +
sphinx/themes/haiku/static/alert_info_32.png | Bin 0 -> 1168 bytes
sphinx/themes/haiku/static/alert_warning_32.png | Bin 0 -> 1060 bytes
sphinx/themes/haiku/static/bg-page.png | Bin 0 -> 164 bytes
sphinx/themes/haiku/static/bullet_orange.png | Bin 0 -> 365 bytes
sphinx/themes/haiku/static/haiku.css_t | 371 +++++
sphinx/themes/haiku/theme.conf | 12 +
sphinx/themes/nature/static/nature.css_t | 245 +++
sphinx/themes/nature/theme.conf | 4 +
sphinx/themes/pyramid/layout.html | 24 +
sphinx/themes/pyramid/static/dialog-note.png | Bin 0 -> 1582 bytes
sphinx/themes/pyramid/static/dialog-seealso.png | Bin 0 -> 1502 bytes
sphinx/themes/pyramid/static/dialog-todo.png | Bin 0 -> 1334 bytes
sphinx/themes/pyramid/static/dialog-topic.png | Bin 0 -> 1910 bytes
sphinx/themes/pyramid/static/dialog-warning.png | Bin 0 -> 1391 bytes
sphinx/themes/pyramid/static/epub.css | 310 ++++
sphinx/themes/pyramid/static/footerbg.png | Bin 0 -> 333 bytes
sphinx/themes/pyramid/static/headerbg.png | Bin 0 -> 203 bytes
sphinx/themes/pyramid/static/ie6.css | 7 +
sphinx/themes/pyramid/static/middlebg.png | Bin 0 -> 2797 bytes
sphinx/themes/pyramid/static/pyramid.css_t | 342 ++++
sphinx/themes/pyramid/static/transparent.gif | Bin 0 -> 49 bytes
sphinx/themes/pyramid/theme.conf | 4 +
sphinx/themes/scrolls/artwork/logo.svg | 107 ++
sphinx/themes/scrolls/layout.html | 42 +
sphinx/themes/scrolls/static/darkmetal.png | Bin 0 -> 44361 bytes
sphinx/themes/scrolls/static/headerbg.png | Bin 0 -> 298 bytes
sphinx/themes/scrolls/static/logo.png | Bin 0 -> 11078 bytes
sphinx/themes/scrolls/static/metal.png | Bin 0 -> 21543 bytes
sphinx/themes/scrolls/static/navigation.png | Bin 0 -> 217 bytes
sphinx/themes/scrolls/static/print.css | 7 +
sphinx/themes/scrolls/static/scrolls.css_t | 431 +++++
sphinx/themes/scrolls/static/theme_extras.js | 26 +
sphinx/themes/scrolls/static/watermark.png | Bin 0 -> 107625 bytes
sphinx/themes/scrolls/static/watermark_blur.png | Bin 0 -> 14470 bytes
sphinx/themes/scrolls/theme.conf | 11 +
sphinx/themes/sphinxdoc/layout.html | 14 +
sphinx/themes/sphinxdoc/static/contents.png | Bin 0 -> 202 bytes
sphinx/themes/sphinxdoc/static/navigation.png | Bin 0 -> 218 bytes
sphinx/themes/sphinxdoc/static/sphinxdoc.css_t | 339 ++++
sphinx/themes/sphinxdoc/theme.conf | 4 +
sphinx/themes/traditional/static/traditional.css_t | 700 ++++++++
sphinx/themes/traditional/theme.conf | 3 +
sphinx/theming.py | 197 +++
sphinx/transforms.py | 490 ++++++
sphinx/util/__init__.py | 439 +++++
sphinx/util/compat.py | 39 +
sphinx/util/console.py | 101 ++
sphinx/util/docfields.py | 293 ++++
sphinx/util/docstrings.py | 62 +
sphinx/util/inspect.py | 156 ++
sphinx/util/jsdump.py | 195 +++
sphinx/util/jsonimpl.py | 48 +
sphinx/util/matching.py | 80 +
sphinx/util/nodes.py | 268 ++++
sphinx/util/osutil.py | 198 +++
sphinx/util/png.py | 59 +
sphinx/util/pycompat.py | 282 ++++
sphinx/util/smartypants.py | 299 ++++
sphinx/util/stemmer.py | 348 ++++
sphinx/util/tags.py | 90 ++
sphinx/util/texescape.py | 112 ++
sphinx/util/websupport.py | 13 +
sphinx/versioning.py | 127 ++
sphinx/websupport/__init__.py | 458 ++++++
sphinx/websupport/errors.py | 26 +
sphinx/websupport/search/__init__.py | 126 ++
sphinx/websupport/search/nullsearch.py | 24 +
sphinx/websupport/search/whooshsearch.py | 59 +
sphinx/websupport/search/xapiansearch.py | 81 +
sphinx/websupport/storage/__init__.py | 115 ++
sphinx/websupport/storage/differ.py | 86 +
sphinx/websupport/storage/sqlalchemy_db.py | 222 +++
sphinx/websupport/storage/sqlalchemystorage.py | 177 +++
sphinx/writers/__init__.py | 10 +
sphinx/writers/html.py | 656 ++++++++
sphinx/writers/latex.py | 1545 ++++++++++++++++++
sphinx/writers/manpage.py | 354 +++++
sphinx/writers/texinfo.py | 1403 ++++++++++++++++
sphinx/writers/text.py | 855 ++++++++++
sphinx/writers/websupport.py | 46 +
sphinx/writers/xml.py | 51 +
tests/coverage.py | 1172 ++++++++++++++
tests/etree13/ElementPath.py | 226 +++
tests/etree13/ElementTree.py | 1546 ++++++++++++++++++
tests/etree13/HTMLTreeBuilder.py | 230 +++
tests/etree13/__init__.py | 30 +
tests/path.py | 196 +++
tests/root/Makefile | 70 +
tests/root/_static/README | 1 +
tests/root/_static/excluded.css | 1 +
tests/root/_static/subdir/foo.css | 1 +
tests/root/_templates/contentssb.html | 2 +
tests/root/_templates/customsb.html | 4 +
tests/root/_templates/layout.html | 15 +
tests/root/autodoc.txt | 47 +
tests/root/autodoc_fodder.py | 7 +
tests/root/autosummary.txt | 31 +
tests/root/bom.po | 12 +
tests/root/bom.txt | 5 +
tests/root/conf.py | 128 ++
tests/root/contents.txt | 45 +
tests/root/doctest.txt | 129 ++
tests/root/ext.py | 4 +
tests/root/extapi.txt | 10 +
tests/root/extensions.txt | 28 +
tests/root/footnote.txt | 46 +
tests/root/images.txt | 28 +
tests/root/img.gif | Bin 0 -> 24976 bytes
tests/root/img.pdf | Bin 0 -> 141783 bytes
tests/root/img.png | Bin 0 -> 67861 bytes
tests/root/includes.txt | 84 +
tests/root/lists.txt | 54 +
tests/root/literal.inc | 13 +
tests/root/markup.txt | 359 +++++
tests/root/math.txt | 22 +
tests/root/metadata.txt | 53 +
tests/root/objects.txt | 198 +++
tests/root/quotes.inc | 1 +
tests/root/rimg.png | Bin 0 -> 218 bytes
tests/root/robots.txt | 2 +
tests/root/special/api.h | 1 +
tests/root/special/code.py | 2 +
tests/root/subdir.po | 9 +
tests/root/subdir/excluded.txt | 2 +
tests/root/subdir/images.txt | 6 +
tests/root/subdir/img.png | Bin 0 -> 67861 bytes
tests/root/subdir/include.inc | 5 +
tests/root/subdir/includes.txt | 18 +
tests/root/subdir/simg.png | Bin 0 -> 67861 bytes
tests/root/svgimg.pdf | Bin 0 -> 141783 bytes
tests/root/svgimg.svg | 158 ++
tests/root/tabs.inc | 5 +
tests/root/templated.css_t | 2 +
tests/root/test.inc | 3 +
tests/root/testtheme/layout.html | 5 +
tests/root/testtheme/static/staticimg.png | Bin 0 -> 218 bytes
tests/root/testtheme/static/statictmpl.html_t | 2 +
tests/root/testtheme/theme.conf | 7 +
tests/root/versioning/added.txt | 20 +
tests/root/versioning/deleted.txt | 12 +
tests/root/versioning/deleted_end.txt | 11 +
tests/root/versioning/index.txt | 13 +
tests/root/versioning/insert.txt | 18 +
tests/root/versioning/insert_beginning.txt | 18 +
tests/root/versioning/insert_similar.txt | 17 +
tests/root/versioning/modified.txt | 17 +
tests/root/versioning/original.txt | 15 +
tests/root/wrongenc.inc | 3 +
tests/root/ziptheme.zip | Bin 0 -> 1039 bytes
tests/roots/test-autosummary/conf.py | 5 +
tests/roots/test-autosummary/contents.rst | 6 +
tests/roots/test-autosummary/dummy_module.py | 71 +
tests/roots/test-docutilsconf/conf.py | 5 +
tests/roots/test-docutilsconf/contents.txt | 15 +
tests/roots/test-docutilsconf/docutils.conf | 0
tests/roots/test-intl/_templates/index.html | 10 +
tests/roots/test-intl/admonitions.po | 81 +
tests/roots/test-intl/admonitions.txt | 46 +
tests/roots/test-intl/bom.po | 12 +
tests/roots/test-intl/bom.txt | 5 +
tests/roots/test-intl/conf.py | 8 +
tests/roots/test-intl/contents.txt | 23 +
tests/roots/test-intl/definition_terms.po | 32 +
tests/roots/test-intl/definition_terms.txt | 11 +
tests/roots/test-intl/docfields.po | 39 +
tests/roots/test-intl/docfields.txt | 46 +
tests/roots/test-intl/external_links.po | 47 +
tests/roots/test-intl/external_links.txt | 35 +
tests/roots/test-intl/figure_caption.po | 35 +
tests/roots/test-intl/figure_caption.txt | 26 +
tests/roots/test-intl/footnote.po | 36 +
tests/roots/test-intl/footnote.txt | 12 +
tests/roots/test-intl/glossary_terms.po | 35 +
tests/roots/test-intl/glossary_terms.txt | 14 +
.../test-intl/glossary_terms_inconsistency.po | 23 +
.../test-intl/glossary_terms_inconsistency.txt | 6 +
tests/roots/test-intl/i18n.png | Bin 0 -> 67861 bytes
tests/roots/test-intl/index_entries.po | 77 +
tests/roots/test-intl/index_entries.txt | 31 +
tests/roots/test-intl/label_target.po | 66 +
tests/roots/test-intl/label_target.txt | 67 +
tests/roots/test-intl/literalblock.po | 30 +
tests/roots/test-intl/literalblock.txt | 13 +
tests/roots/test-intl/refs_inconsistency.po | 39 +
tests/roots/test-intl/refs_inconsistency.txt | 13 +
tests/roots/test-intl/refs_python_domain.po | 25 +
tests/roots/test-intl/refs_python_domain.txt | 15 +
tests/roots/test-intl/role_xref.po | 47 +
tests/roots/test-intl/role_xref.txt | 40 +
tests/roots/test-intl/rubric.po | 29 +
tests/roots/test-intl/rubric.txt | 14 +
tests/roots/test-intl/seealso.po | 33 +
tests/roots/test-intl/seealso.txt | 15 +
tests/roots/test-intl/sphinx.po | 23 +
tests/roots/test-intl/subdir/contents.txt | 2 +
tests/roots/test-intl/versionchange.po | 33 +
tests/roots/test-intl/versionchange.txt | 16 +
tests/roots/test-intl/warnings.po | 23 +
tests/roots/test-intl/warnings.txt | 5 +
tests/roots/test-only-directive/conf.py | 2 +
tests/roots/test-only-directive/contents.rst | 6 +
tests/roots/test-only-directive/only.rst | 203 +++
tests/roots/test-setup/doc/conf.py | 5 +
tests/roots/test-setup/doc/contents.txt | 5 +
tests/roots/test-setup/setup.cfg | 5 +
tests/roots/test-setup/setup.py | 9 +
.../_templates/autosummary/class.rst | 8 +
tests/roots/test-templating/_templates/layout.html | 6 +
.../test-templating/autosummary_templating.txt | 13 +
tests/roots/test-templating/conf.py | 11 +
tests/roots/test-templating/contents.txt | 7 +
tests/run.py | 61 +
tests/test_application.py | 99 ++
tests/test_autodoc.py | 914 +++++++++++
tests/test_autosummary.py | 129 ++
tests/test_build.py | 81 +
tests/test_build_gettext.py | 150 ++
tests/test_build_html.py | 378 +++++
tests/test_build_latex.py | 98 ++
tests/test_build_texinfo.py | 69 +
tests/test_build_text.py | 167 ++
tests/test_config.py | 133 ++
tests/test_coverage.py | 48 +
tests/test_cpp_domain.py | 157 ++
tests/test_doctest.py | 35 +
tests/test_docutilsconf.py | 128 ++
tests/test_env.py | 120 ++
tests/test_footnote.py | 37 +
tests/test_highlighting.py | 84 +
tests/test_i18n.py | 17 +
tests/test_intersphinx.py | 180 +++
tests/test_intl.py | 689 ++++++++
tests/test_linkcode.py | 25 +
tests/test_markup.py | 139 ++
tests/test_metadata.py | 69 +
tests/test_only_directive.py | 61 +
tests/test_py_domain.py | 44 +
tests/test_quickstart.py | 292 ++++
tests/test_rst_domain.py | 26 +
tests/test_search.py | 42 +
tests/test_searchadapters.py | 77 +
tests/test_setup_command.py | 105 ++
tests/test_templating.py | 36 +
tests/test_theming.py | 57 +
tests/test_util_nodes.py | 121 ++
tests/test_versioning.py | 118 ++
tests/test_websupport.py | 276 ++++
tests/util.py | 252 +++
utils/check_sources.py | 247 +++
utils/convert.py | 43 +
utils/pylintrc | 301 ++++
utils/reindent.py | 311 ++++
utils/release-checklist | 21 +
616 files changed, 103519 insertions(+)
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..2a9dbba
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,54 @@
+Sphinx is written and maintained by Georg Brandl <georg at python.org>.
+
+Substantial parts of the templates were written by Armin Ronacher
+<armin.ronacher at active-4.com>.
+
+Other contributors, listed alphabetically, are:
+
+* Andi Albrecht -- agogo theme
+* Henrique Bastos -- SVG support for graphviz extension
+* Daniel Bültmann -- todo extension
+* Etienne Desautels -- apidoc module
+* Michael Droettboom -- inheritance_diagram extension
+* Charles Duffy -- original graphviz extension
+* Kevin Dunn -- MathJax extension
+* Josip Dzolonga -- coverage builder
+* Hernan Grecco -- search improvements
+* Horst Gutmann -- internationalization support
+* Martin Hans -- autodoc improvements
+* Doug Hellmann -- graphviz improvements
+* Dave Kuhlman -- original LaTeX writer
+* Blaise Laflamme -- pyramid theme
+* Thomas Lamb -- linkcheck builder
+* Łukasz Langa -- partial support for autodoc
+* Robert Lehmann -- gettext builder (GSOC project)
+* Dan MacKinlay -- metadata fixes
+* Martin Mahner -- nature theme
+* Will Maier -- directory HTML builder
+* Jacob Mason -- websupport library (GSOC project)
+* Roland Meister -- epub builder
+* Ezio Melotti -- collapsible sidebar JavaScript
+* Daniel Neuhäuser -- JavaScript domain, Python 3 support (GSOC)
+* Christopher Perkins -- autosummary integration
+* Benjamin Peterson -- unittests
+* T. Powers -- HTML output improvements
+* Stefan Seefeld -- toctree improvements
+* Shibukawa Yoshiki -- pluggable search API and Japanese search
+* Antonio Valentino -- qthelp builder
+* Pauli Virtanen -- autodoc improvements, autosummary extension
+* Stefan van der Walt -- autosummary extension
+* Thomas Waldmann -- apidoc module fixes
+* John Waltman -- Texinfo builder
+* Barry Warsaw -- setup command improvements
+* Sebastian Wiesner -- image handling, distutils support
+* Joel Wurtz -- cellspanning support in LaTeX
+
+Many thanks for all contributions!
+
+There are also a few modules or functions incorporated from other
+authors and projects:
+
+* sphinx.util.jsdump uses the basestring encoding from simplejson,
+ written by Bob Ippolito, released under the MIT license
+* sphinx.util.stemmer was written by Vivake Gupta, placed in the
+ Public Domain
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..f0802cc
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,1194 @@
+Release 1.2.3 (released Sep 1, 2014)
+====================================
+
+Features added
+--------------
+
+* #1518: `sphinx-apidoc` command now have a `--version` option to show version
+ information and exit
+* New locales: Hebrew, European Portuguese, Vietnamese.
+
+Bugs fixed
+----------
+
+* #636: Keep straight single quotes in literal blocks in the LaTeX build.
+* #1419: Generated i18n sphinx.js files are missing message catalog entries
+ from '.js_t' and '.html'. The issue was introduced from Sphinx-1.1
+* #1363: Fix i18n: missing python domain's cross-references with currentmodule
+ directive or currentclass directive.
+* #1444: autosummary does not create the description from attributes docstring.
+* #1457: In python3 environment, make linkcheck cause "Can't convert 'bytes'
+ object to str implicitly" error when link target url has a hash part.
+ Thanks to Jorge_C.
+* #1467: Exception on Python3 if nonexistent method is specified by automethod
+* #1441: autosummary can't handle nested classes correctly.
+* #1499: With non-callable `setup` in a conf.py, now sphinx-build emits
+ user-friendly error message.
+* #1502: In autodoc, fix display of parameter defaults containing backslashes.
+* #1226: autodoc, autosummary: importing setup.py by automodule will invoke
+ setup process and execute `sys.exit()`. Now sphinx avoids SystemExit
+ exception and emits warnings without unexpected termination.
+* #1503: py:function directive generate incorrectly signature when specifying
+ a default parameter with an empty list `[]`. Thanks to Geert Jansen.
+* #1508: Non-ASCII filename raise exception on make singlehtml, latex, man,
+ texinfo and changes.
+* #1531: On Python3 environment, docutils.conf with 'source_link=true' in the
+ general section cause type error.
+* PR#270, #1533: Non-ASCII docstring cause UnicodeDecodeError when uses with
+ inheritance-diagram directive. Thanks to WAKAYAMA shirou.
+* PR#281, PR#282, #1509: TODO extension not compatible with websupport. Thanks
+ to Takeshi Komiya.
+* #1477: gettext does not extract nodes.line in a table or list.
+* #1544: `make text` generate wrong table when it has empty table cells.
+* #1522: Footnotes from table get displayed twice in LaTeX. This problem has
+ been appeared from Sphinx-1.2.1 by #949.
+* #508: Sphinx every time exit with zero when is invoked from setup.py command.
+ ex. `python setup.py build_sphinx -b doctest` return zero even if doctest
+ failed.
+
+Release 1.2.2 (released Mar 2, 2014)
+====================================
+
+Bugs fixed
+----------
+
+* PR#211: When checking for existence of the :confval:`html_logo` file, check
+ the full relative path and not the basename.
+* PR#212: Fix traceback with autodoc and ``__init__`` methods without docstring.
+* PR#213: Fix a missing import in the setup command.
+* #1357: Option names documented by :rst:dir:`option` are now again allowed to
+ not start with a dash or slash, and referencing them will work correctly.
+* #1358: Fix handling of image paths outside of the source directory when using
+ the "wildcard" style reference.
+* #1374: Fix for autosummary generating overly-long summaries if first line
+ doesn't end with a period.
+* #1383: Fix Python 2.5 compatibility of sphinx-apidoc.
+* #1391: Actually prevent using "pngmath" and "mathjax" extensions at the same
+ time in sphinx-quickstart.
+* #1386: Fix bug preventing more than one theme being added by the entry point
+ mechanism.
+* #1370: Ignore "toctree" nodes in text writer, instead of raising.
+* #1364: Fix 'make gettext' fails when the '.. todolist::' directive is present.
+* #1367: Fix a change of PR#96 that break sphinx.util.docfields.Field.make_field
+ interface/behavior for `item` argument usage.
+
+Documentation
+-------------
+
+* Extended the :ref:`documentation about building extensions <dev-extensions>`.
+
+
+Release 1.2.1 (released Jan 19, 2014)
+=====================================
+
+Bugs fixed
+----------
+
+* #1335: Fix autosummary template overloading with exclamation prefix like
+ ``{% extends "!autosummary/class.rst" %}`` cause infinite recursive function
+ call. This was caused by PR#181.
+* #1337: Fix autodoc with ``autoclass_content="both"`` uses useless
+ ``object.__init__`` docstring when class does not have ``__init__``.
+ This was caused by a change for #1138.
+* #1340: Can't search alphabetical words on the HTML quick search generated
+ with language='ja'.
+* #1319: Do not crash if the :confval:`html_logo` file does not exist.
+* #603: Do not use the HTML-ized title for building the search index (that
+ resulted in "literal" being found on every page with a literal in the
+ title).
+* #751: Allow production lists longer than a page in LaTeX by using longtable.
+* #764: Always look for stopwords lowercased in JS search.
+* #814: autodoc: Guard against strange type objects that don't have
+ ``__bases__``.
+* #932: autodoc: Do not crash if ``__doc__`` is not a string.
+* #933: Do not crash if an :rst:role:`option` value is malformed (contains
+ spaces but no option name).
+* #908: On Python 3, handle error messages from LaTeX correctly in the pngmath
+ extension.
+* #943: In autosummary, recognize "first sentences" to pull from the docstring
+ if they contain uppercase letters.
+* #923: Take the entire LaTeX document into account when caching
+ pngmath-generated images. This rebuilds them correctly when
+ :confval:`pngmath_latex_preamble` changes.
+* #901: Emit a warning when using docutils' new "math" markup without a Sphinx
+ math extension active.
+* #845: In code blocks, when the selected lexer fails, display line numbers
+ nevertheless if configured.
+* #929: Support parsed-literal blocks in LaTeX output correctly.
+* #949: Update the tabulary.sty packed with Sphinx.
+* #1050: Add anonymous labels into ``objects.inv`` to be referenced via
+ :mod:`~sphinx.ext.intersphinx`.
+* #1095: Fix print-media stylesheet being included always in the "scrolls"
+ theme.
+* #1085: Fix current classname not getting set if class description has
+ ``:noindex:`` set.
+* #1181: Report option errors in autodoc directives more gracefully.
+* #1155: Fix autodocumenting C-defined methods as attributes in Python 3.
+* #1233: Allow finding both Python classes and exceptions with the "class" and
+ "exc" roles in intersphinx.
+* #1198: Allow "image" for the "figwidth" option of the :rst:dir:`figure`
+ directive as documented by docutils.
+* #1152: Fix pycode parsing errors of Python 3 code by including two grammar
+ versions for Python 2 and 3, and loading the appropriate version for the
+ running Python version.
+* #1017: Be helpful and tell the user when the argument to :rst:dir:`option`
+ does not match the required format.
+* #1345: Fix two bugs with :confval:`nitpick_ignore`; now you don't have to
+ remove the store environment for changes to have effect.
+* #1072: In the JS search, fix issues searching for upper-cased words by
+ lowercasing words before stemming.
+* #1299: Make behavior of the :rst:dir:`math` directive more consistent and
+ avoid producing empty environments in LaTeX output.
+* #1308: Strip HTML tags from the content of "raw" nodes before feeding it
+ to the search indexer.
+* #1249: Fix duplicate LaTeX page numbering for manual documents.
+* #1292: In the linkchecker, retry HEAD requests when denied by HTTP 405.
+ Also make the redirect code apparent and tweak the output a bit to be
+ more obvious.
+* #1285: Avoid name clashes between C domain objects and section titles.
+* #848: Always take the newest code in incremental rebuilds with the
+ :mod:`sphinx.ext.viewcode` extension.
+* #979, #1266: Fix exclude handling in ``sphinx-apidoc``.
+* #1302: Fix regression in :mod:`sphinx.ext.inheritance_diagram` when
+ documenting classes that can't be pickled.
+* #1316: Remove hard-coded ``font-face`` resources from epub theme.
+* #1329: Fix traceback with empty translation msgstr in .po files.
+* #1300: Fix references not working in translated documents in some instances.
+* #1283: Fix a bug in the detection of changed files that would try to access
+ doctrees of deleted documents.
+* #1330: Fix :confval:`exclude_patterns` behavior with subdirectories in the
+ :confval:`html_static_path`.
+* #1323: Fix emitting empty ``<ul>`` tags in the HTML writer, which is not
+ valid HTML.
+* #1147: Don't emit a sidebar search box in the "singlehtml" builder.
+
+Documentation
+-------------
+
+* #1325: Added a "Intersphinx" tutorial section. (:file:`doc/tutorial.rst`)
+
+
+Release 1.2 (released Dec 10, 2013)
+===================================
+
+Features added
+--------------
+
+* Added ``sphinx.version_info`` tuple for programmatic checking of the Sphinx
+ version.
+
+Incompatible changes
+--------------------
+
+* Removed the ``sphinx.ext.refcounting`` extension -- it is very specific to
+ CPython and has no place in the main distribution.
+
+Bugs fixed
+----------
+
+* Restore ``versionmodified`` CSS class for versionadded/changed and deprecated
+ directives.
+
+* PR#181: Fix `html_theme_path=['.']` is a trigger of rebuild all documents
+ always (This change keeps the current "theme changes cause a rebuild"
+ feature).
+
+* #1296: Fix invalid charset in HTML help generated HTML files for default
+ locale.
+
+* PR#190: Fix gettext does not extract figure caption and rubric title inside
+ other blocks. Thanks to Michael Schlenker.
+
+* PR#176: Make sure setup_command test can always import Sphinx. Thanks to
+ Dmitry Shachnev.
+
+* #1311: Fix test_linkcode.test_html fails with C locale and Python 3.
+
+* #1269: Fix ResourceWarnings with Python 3.2 or later.
+
+* #1138: Fix: When ``autodoc_docstring_signature = True`` and
+ ``autoclass_content = 'init'`` or ``'both'``, __init__ line should be
+ removed from class documentation.
+
+
+Release 1.2 beta3 (released Oct 3, 2013)
+========================================
+
+Features added
+--------------
+
+* The Sphinx error log files will now include a list of the loaded extensions
+ for help in debugging.
+
+Incompatible changes
+--------------------
+
+* PR#154: Remove "sphinx" prefix from LaTeX class name except 'sphinxmanual'
+ and 'sphinxhowto'. Now you can use your custom document class without
+ 'sphinx' prefix. Thanks to Erik B.
+
+Bugs fixed
+----------
+
+* #1265: Fix i18n: crash when translating a section name that is pointed to from
+ a named target.
+* A wrong condition broke the search feature on first page that is usually
+ index.rst. This issue was introduced in 1.2b1.
+* #703: When Sphinx can't decode filenames with non-ASCII characters, Sphinx now
+ catches UnicodeError and will continue if possible instead of raising the
+ exception.
+
+
+Release 1.2 beta2 (released Sep 17, 2013)
+=========================================
+
+Features added
+--------------
+
+* ``apidoc`` now ignores "_private" modules by default, and has an option ``-P``
+ to include them.
+* ``apidoc`` now has an option to not generate headings for packages and
+ modules, for the case that the module docstring already includes a reST
+ heading.
+* PR#161: ``apidoc`` can now write each module to a standalone page instead of
+ combining all modules in a package on one page.
+* Builders: rebuild i18n target document when catalog updated.
+* Support docutils.conf 'writers' and 'html4css1 writer' section in the HTML
+ writer. The latex, manpage and texinfo writers also support their respective
+ 'writers' sections.
+* The new :confval:`html_extra_path` config value allows to specify directories
+ with files that should be copied directly to the HTML output directory.
+* Autodoc directives for module data and attributes now support an
+ ``annotation`` option, so that the default display of the data/attribute
+ value can be overridden.
+* PR#136: Autodoc directives now support an ``imported-members`` option to
+ include members imported from different modules.
+* New locales: Macedonian, Sinhala, Indonesian.
+* Theme package collection by using setuptools plugin mechanism.
+
+Incompatible changes
+--------------------
+
+* PR#144, #1182: Force timezone offset to LocalTimeZone on POT-Creation-Date
+ that was generated by gettext builder. Thanks to masklinn and Jakub Wilk.
+
+Bugs fixed
+----------
+
+* PR#132: Updated jQuery version to 1.8.3.
+* PR#141, #982: Avoid crash when writing PNG file using Python 3. Thanks to
+ Marcin Wojdyr.
+* PR#145: In parallel builds, sphinx drops second document file to write.
+ Thanks to tychoish.
+* PR#151: Some styling updates to tables in LaTeX.
+* PR#153: The "extensions" config value can now be overridden.
+* PR#155: Added support for some C++11 function qualifiers.
+* Fix: 'make gettext' caused UnicodeDecodeError when templates contain utf-8
+ encoded strings.
+* #828: use inspect.getfullargspec() to be able to document functions with
+ keyword-only arguments on Python 3.
+* #1090: Fix i18n: multiple cross references (term, ref, doc) in the same line
+ return the same link.
+* #1157: Combination of 'globaltoc.html' and hidden toctree caused exception.
+* #1159: fix wrong generation of objects inventory for Python modules, and
+ add a workaround in intersphinx to fix handling of affected inventories.
+* #1160: Citation target missing caused an AssertionError.
+* #1162, PR#139: singlehtml builder didn't copy images to _images/.
+* #1173: Adjust setup.py dependencies because Jinja2 2.7 discontinued
+ compatibility with Python < 3.3 and Python < 2.6. Thanks to Alexander Dupuy.
+* #1185: Don't crash when a Python module has a wrong or no encoding declared,
+ and non-ASCII characters are included.
+* #1188: sphinx-quickstart raises UnicodeEncodeError if "Project version"
+ includes non-ASCII characters.
+* #1189: "Title underline is too short" WARNING is given when using fullwidth
+ characters to "Project name" on quickstart.
+* #1190: Output TeX/texinfo/man filename has no basename (only extension)
+ when using non-ASCII characters in the "Project name" on quickstart.
+* #1192: Fix escaping problem for hyperlinks in the manpage writer.
+* #1193: Fix i18n: multiple link references in the same line return the same
+ link.
+* #1176: Fix i18n: footnote reference number missing for auto numbered named
+ footnote and auto symbol footnote.
+* PR#146,#1172: Fix ZeroDivisionError in parallel builds. Thanks to tychoish.
+* #1204: Fix wrong generation of links to local intersphinx targets.
+* #1206: Fix i18n: gettext did not translate admonition directive's title.
+* #1232: Sphinx generated broken ePub files on Windows.
+* #1259: Guard the debug output call when emitting events; to prevent the
+ repr() implementation of arbitrary objects causing build failures.
+* #1142: Fix NFC/NFD normalizing problem of rst filename on Mac OS X.
+* #1234: Ignoring the string consists only of white-space characters.
+
+
+Release 1.2 beta1 (released Mar 31, 2013)
+=========================================
+
+Incompatible changes
+--------------------
+
+* Removed ``sphinx.util.compat.directive_dwim()`` and
+ ``sphinx.roles.xfileref_role()`` which were deprecated since version 1.0.
+* PR#122: the files given in :confval:`latex_additional_files` now override TeX
+ files included by Sphinx, such as ``sphinx.sty``.
+* PR#124: the node generated by :rst:dir:`versionadded`,
+ :rst:dir:`versionchanged` and :rst:dir:`deprecated` directives now includes
+ all added markup (such as "New in version X") as child nodes, and no
+ additional text must be generated by writers.
+* PR#99: the :rst:dir:`seealso` directive now generates admonition nodes instead
+ of the custom ``seealso`` node.
+
+Features added
+--------------
+
+* Markup
+
+ - The :rst:dir:`toctree` directive and the ``toctree()`` template function now
+ have an ``includehidden`` option that includes hidden toctree entries (bugs
+ #790 and #1047). A bug in the ``maxdepth`` option for the ``toctree()``
+ template function has been fixed (bug #1046).
+ - PR#99: Strip down seealso directives to normal admonitions. This removes
+ their unusual CSS classes (admonition-see-also), inconsistent LaTeX
+ admonition title ("See Also" instead of "See also"), and spurious indentation
+ in the text builder.
+
+* HTML builder
+
+ - #783: Create a link to full size image if it is scaled with width or height.
+ - #1067: Improve the ordering of the JavaScript search results: matches in titles
+ come before matches in full text, and object results are better categorized.
+ Also implement a pluggable search scorer.
+ - #1053: The "rightsidebar" and "collapsiblesidebar" HTML theme options now work
+ together.
+ - Update to jQuery 1.7.1 and Underscore.js 1.3.1.
+
+* Texinfo builder
+
+ - An "Index" node is no longer added when there are no entries.
+ - "deffn" categories are no longer capitalized if they contain capital
+ letters.
+ - ``desc_annotation`` nodes are now rendered.
+ - ``strong`` and ``emphasis`` nodes are now formatted like
+ ``literal``\s. The reason for this is because the standard Texinfo markup
+ (``*strong*`` and ``_emphasis_``) resulted in confusing output due to the
+ common usage of using these constructs for documenting parameter names.
+ - Field lists formatting has been tweaked to better display
+ "Info field lists".
+ - ``system_message`` and ``problematic`` nodes are now formatted in a similar
+ fashion as done by the text builder.
+ - "en-dash" and "em-dash" conversion of hyphens is no longer performed in
+ option directive signatures.
+ - ``@ref`` is now used instead of ``@pxref`` for cross-references which
+ prevents the word "see" from being added before the link (does not affect
+ the Info output).
+ - The ``@finalout`` command has been added for better TeX output.
+ - ``transition`` nodes are now formatted using underscores ("_") instead of
+ asterisks ("*").
+ - The default value for the ``paragraphindent`` has been changed from 2 to 0
+ meaning that paragraphs are no longer indented by default.
+ - #1110: A new configuration value :confval:`texinfo_no_detailmenu` has been
+ added for controlling whether a ``@detailmenu`` is added in the "Top"
+ node's menu.
+ - Detailed menus are no longer created except for the "Top" node.
+ - Fixed an issue where duplicate domain indices would result in invalid
+ output.
+
+* LaTeX builder:
+
+ - PR#115: Add ``'transition'`` item in :confval:`latex_elements` for
+ customizing how transitions are displayed. Thanks to Jeff Klukas.
+ - PR#114: The LaTeX writer now includes the "cmap" package by default. The
+ ``'cmappkg'`` item in :confval:`latex_elements` can be used to control this.
+ Thanks to Dmitry Shachnev.
+ - The ``'fontpkg'`` item in :confval:`latex_elements` now defaults to ``''``
+ when the :confval:`language` uses the Cyrillic script. Suggested by Dmitry
+ Shachnev.
+ - The :confval:`latex_documents`, :confval:`texinfo_documents`, and
+ :confval:`man_pages` configuration values will be set to default values based
+ on the :confval:`master_doc` if not explicitly set in :file:`conf.py`.
+ Previously, if these values were not set, no output would be genereted by
+ their respective builders.
+
+* Internationalization:
+
+ - Add i18n capabilities for custom templates. For example: The Sphinx
+ reference documentation in doc directory provides a ``sphinx.pot`` file with
+ message strings from ``doc/_templates/*.html`` when using ``make gettext``.
+
+ - PR#61,#703: Add support for non-ASCII filename handling.
+
+* Other builders:
+
+ - Added the Docutils-native XML and pseudo-XML builders. See
+ :class:`XMLBuilder` and :class:`PseudoXMLBuilder`.
+ - PR#45: The linkcheck builder now checks ``#anchor``\ s for existence.
+ - PR#123, #1106: Add :confval:`epub_use_index` configuration value. If
+ provided, it will be used instead of :confval:`html_use_index` for epub
+ builder.
+ - PR#126: Add :confval:`epub_tocscope` configuration value. The setting
+ controls the generation of the epub toc. The user can now also include
+ hidden toc entries.
+ - PR#112: Add :confval:`epub_show_urls` configuration value.
+
+* Extensions:
+
+ - PR#52: ``special_members`` flag to autodoc now behaves like ``members``.
+ - PR#47: Added :mod:`sphinx.ext.linkcode` extension.
+ - PR#25: In inheritance diagrams, the first line of the class docstring
+ is now the tooltip for the class.
+
+* Command-line interfaces:
+
+ - PR#75: Added ``--follow-links`` option to sphinx-apidoc.
+ - #869: sphinx-build now has the option :option:`-T` for printing the full
+ traceback after an unhandled exception.
+ - sphinx-build now supports the standard :option:`--help` and
+ :option:`--version` options.
+ - sphinx-build now provides more specific error messages when called with
+ invalid options or arguments.
+ - sphinx-build now has a verbose option :option:`-v` which can be repeated for
+ greater effect. A single occurrance provides a slightly more verbose output
+ than normal. Two or more occurrences of this option provides more detailed
+ output which may be useful for debugging.
+
+* Locales:
+
+ - PR#74: Fix some Russian translation.
+ - PR#54: Added Norwegian bokmaal translation.
+ - PR#35: Added Slovak translation.
+ - PR#28: Added Hungarian translation.
+ - #1113: Add Hebrew locale.
+ - #1097: Add Basque locale.
+ - #1037: Fix typos in Polish translation. Thanks to Jakub Wilk.
+ - #1012: Update Estonian translation.
+
+* Optimizations:
+
+ - Speed up building the search index by caching the results of the word
+ stemming routines. Saves about 20 seconds when building the Python
+ documentation.
+ - PR#108: Add experimental support for parallel building with a new
+ :option:`-j` option.
+
+Documentation
+-------------
+
+* PR#88: Added the "Sphinx Developer's Guide" (:file:`doc/devguide.rst`)
+ which outlines the basic development process of the Sphinx project.
+* Added a detailed "Installing Sphinx" document (:file:`doc/install.rst`).
+
+Bugs fixed
+----------
+
+* PR#124: Fix paragraphs in versionmodified are ignored when it has no
+ dangling paragraphs. Fix wrong html output (nested ``<p>`` tag). Fix
+ versionmodified is not translatable. Thanks to Nozomu Kaneko.
+* PR#111: Respect add_autodoc_attrgetter() even when inherited-members is set.
+ Thanks to A. Jesse Jiryu Davis.
+* PR#97: Fix footnote handling in translated documents.
+* Fix text writer not handling visit_legend for figure directive contents.
+* Fix text builder not respecting wide/fullwidth characters: title underline
+ width, table layout width and text wrap width.
+* Fix leading space in LaTeX table header cells.
+* #1132: Fix LaTeX table output for multi-row cells in the first column.
+* #1128: Fix Unicode errors when trying to format time strings with a
+ non-standard locale.
+* #1127: Fix traceback when autodoc tries to tokenize a non-Python file.
+* #1126: Fix double-hyphen to en-dash conversion in wrong places such as
+ command-line option names in LaTeX.
+* #1123: Allow whitespaces in filenames given to :rst:dir:`literalinclude`.
+* #1120: Added improvements about i18n for themes "basic", "haiku" and
+ "scrolls" that Sphinx built-in. Thanks to Leonardo J. Caballero G.
+* #1118: Updated Spanish translation. Thanks to Leonardo J. Caballero G.
+* #1117: Handle .pyx files in sphinx-apidoc.
+* #1112: Avoid duplicate download files when referenced from documents in
+ different ways (absolute/relative).
+* #1111: Fix failure to find uppercase words in search when
+ :confval:`html_search_language` is 'ja'. Thanks to Tomo Saito.
+* #1108: The text writer now correctly numbers enumerated lists with
+ non-default start values (based on patch by Ewan Edwards).
+* #1102: Support multi-context "with" statements in autodoc.
+* #1090: Fix gettext not extracting glossary terms.
+* #1074: Add environment version info to the generated search index to avoid
+ compatibility issues with old builds.
+* #1070: Avoid un-pickling issues when running Python 3 and the saved
+ environment was created under Python 2.
+* #1069: Fixed error caused when autodoc would try to format signatures of
+ "partial" functions without keyword arguments (patch by Artur Gaspar).
+* #1062: sphinx.ext.autodoc use __init__ method signature for class signature.
+* #1055: Fix web support with relative path to source directory.
+* #1043: Fix sphinx-quickstart asking again for yes/no questions because
+ ``input()`` returns values with an extra '\r' on Python 3.2.0 +
+ Windows. Thanks to Régis Décamps.
+* #1041: Fix failure of the cpp domain parser to parse a const type with a
+ modifier.
+* #1038: Fix failure of the cpp domain parser to parse C+11 "static constexpr"
+ declarations. Thanks to Jakub Wilk.
+* #1029: Fix intersphinx_mapping values not being stable if the mapping has
+ plural key/value set with Python 3.3.
+* #1028: Fix line block output in the text builder.
+* #1024: Improve Makefile/make.bat error message if Sphinx is not found. Thanks
+ to Anatoly Techtonik.
+* #1018: Fix "container" directive handling in the text builder.
+* #1015: Stop overriding jQuery contains() in the JavaScript.
+* #1010: Make pngmath images transparent by default; IE7+ should handle it.
+* #1008: Fix test failures with Python 3.3.
+* #995: Fix table-of-contents and page numbering for the LaTeX "howto" class.
+* #976: Fix gettext does not extract index entries.
+* PR#72: #975: Fix gettext not extracting definition terms before docutils 0.10.
+* #961: Fix LaTeX output for triple quotes in code snippets.
+* #958: Do not preserve ``environment.pickle`` after a failed build.
+* #955: Fix i18n transformation.
+* #940: Fix gettext does not extract figure caption.
+* #920: Fix PIL packaging issue that allowed to import ``Image`` without PIL
+ namespace. Thanks to Marc Schlaich.
+* #723: Fix the search function on local files in WebKit based browsers.
+* #440: Fix coarse timestamp resolution in some filesystem generating a wrong
+ list of outdated files.
+
+
+Release 1.1.3 (Mar 10, 2012)
+============================
+
+* PR#40: Fix ``safe_repr`` function to decode bytestrings with non-ASCII
+ characters correctly.
+
+* PR#37: Allow configuring sphinx-apidoc via ``SPHINX_APIDOC_OPTIONS``.
+
+* PR#34: Restore Python 2.4 compatibility.
+
+* PR#36: Make the "bibliography to TOC" fix in LaTeX output specific to
+ the document class.
+
+* #695: When the highlight language "python" is specified explicitly,
+ do not try to parse the code to recognize non-Python snippets.
+
+* #859: Fix exception under certain circumstances when not finding
+ appropriate objects to link to.
+
+* #860: Do not crash when encountering invalid doctest examples, just
+ emit a warning.
+
+* #864: Fix crash with some settings of :confval:`modindex_common_prefix`.
+
+* #862: Fix handling of ``-D`` and ``-A`` options on Python 3.
+
+* #851: Recognize and warn about circular toctrees, instead of running
+ into recursion errors.
+
+* #853: Restore compatibility with docutils trunk.
+
+* #852: Fix HtmlHelp index entry links again.
+
+* #854: Fix inheritance_diagram raising attribute errors on builtins.
+
+* #832: Fix crashes when putting comments or lone terms in a glossary.
+
+* #834, #818: Fix HTML help language/encoding mapping for all Sphinx
+ supported languages.
+
+* #844: Fix crashes when dealing with Unicode output in doctest extension.
+
+* #831: Provide ``--project`` flag in setup_command as advertised.
+
+* #875: Fix reading config files under Python 3.
+
+* #876: Fix quickstart test under Python 3.
+
+* #870: Fix spurious KeyErrors when removing documents.
+
+* #892: Fix single-HTML builder misbehaving with the master document in a
+ subdirectory.
+
+* #873: Fix assertion errors with empty ``only`` directives.
+
+* #816: Fix encoding issues in the Qt help builder.
+
+
+Release 1.1.2 (Nov 1, 2011) -- 1.1.1 is a silly version number anyway!
+======================================================================
+
+* #809: Include custom fixers in the source distribution.
+
+
+Release 1.1.1 (Nov 1, 2011)
+===========================
+
+* #791: Fix QtHelp, DevHelp and HtmlHelp index entry links.
+
+* #792: Include "sphinx-apidoc" in the source distribution.
+
+* #797: Don't crash on a misformatted glossary.
+
+* #801: Make intersphinx work properly without SSL support.
+
+* #805: Make the ``Sphinx.add_index_to_domain`` method work correctly.
+
+* #780: Fix Python 2.5 compatibility.
+
+
+Release 1.1 (Oct 9, 2011)
+=========================
+
+Incompatible changes
+--------------------
+
+* The :rst:dir:`py:module` directive doesn't output its ``platform`` option
+ value anymore. (It was the only thing that the directive did output, and
+ therefore quite inconsistent.)
+
+* Removed support for old dependency versions; requirements are now:
+
+ - Pygments >= 1.2
+ - Docutils >= 0.7
+ - Jinja2 >= 2.3
+
+Features added
+--------------
+
+* Added Python 3.x support.
+
+* New builders and subsystems:
+
+ - Added a Texinfo builder.
+ - Added i18n support for content, a ``gettext`` builder and related
+ utilities.
+ - Added the ``websupport`` library and builder.
+ - #98: Added a ``sphinx-apidoc`` script that autogenerates a hierarchy
+ of source files containing autodoc directives to document modules
+ and packages.
+ - #273: Add an API for adding full-text search support for languages
+ other than English. Add support for Japanese.
+
+* Markup:
+
+ - #138: Added an :rst:role:`index` role, to make inline index entries.
+ - #454: Added more index markup capabilities: marking see/seealso entries,
+ and main entries for a given key.
+ - #460: Allowed limiting the depth of section numbers for HTML using the
+ :rst:dir:`toctree`\'s ``numbered`` option.
+ - #586: Implemented improved :rst:dir:`glossary` markup which allows
+ multiple terms per definition.
+ - #478: Added :rst:dir:`py:decorator` directive to describe decorators.
+ - C++ domain now supports array definitions.
+ - C++ domain now supports doc fields (``:param x:`` inside directives).
+ - Section headings in :rst:dir:`only` directives are now correctly
+ handled.
+ - Added ``emphasize-lines`` option to source code directives.
+ - #678: C++ domain now supports superclasses.
+
+* HTML builder:
+
+ - Added ``pyramid`` theme.
+ - #559: :confval:`html_add_permalinks` is now a string giving the
+ text to display in permalinks.
+ - #259: HTML table rows now have even/odd CSS classes to enable
+ "Zebra styling".
+ - #554: Add theme option ``sidebarwidth`` to the basic theme.
+
+* Other builders:
+
+ - #516: Added new value of the :confval:`latex_show_urls` option to
+ show the URLs in footnotes.
+ - #209: Added :confval:`text_newlines` and :confval:`text_sectionchars`
+ config values.
+ - Added :confval:`man_show_urls` config value.
+ - #472: linkcheck builder: Check links in parallel, use HTTP HEAD
+ requests and allow configuring the timeout. New config values:
+ :confval:`linkcheck_timeout` and :confval:`linkcheck_workers`.
+ - #521: Added :confval:`linkcheck_ignore` config value.
+ - #28: Support row/colspans in tables in the LaTeX builder.
+
+* Configuration and extensibility:
+
+ - #537: Added :confval:`nitpick_ignore`.
+ - #306: Added :event:`env-get-outdated` event.
+ - :meth:`.Application.add_stylesheet` now accepts full URIs.
+
+* Autodoc:
+
+ - #564: Add :confval:`autodoc_docstring_signature`. When enabled (the
+ default), autodoc retrieves the signature from the first line of the
+ docstring, if it is found there.
+ - #176: Provide ``private-members`` option for autodoc directives.
+ - #520: Provide ``special-members`` option for autodoc directives.
+ - #431: Doc comments for attributes can now be given on the same line
+ as the assignment.
+ - #437: autodoc now shows values of class data attributes.
+ - autodoc now supports documenting the signatures of
+ ``functools.partial`` objects.
+
+* Other extensions:
+
+ - Added the :mod:`sphinx.ext.mathjax` extension.
+ - #443: Allow referencing external graphviz files.
+ - Added ``inline`` option to graphviz directives, and fixed the
+ default (block-style) in LaTeX output.
+ - #590: Added ``caption`` option to graphviz directives.
+ - #553: Added :rst:dir:`testcleanup` blocks in the doctest extension.
+ - #594: :confval:`trim_doctest_flags` now also removes ``<BLANKLINE>``
+ indicators.
+ - #367: Added automatic exclusion of hidden members in inheritance
+ diagrams, and an option to selectively enable it.
+ - Added :confval:`pngmath_add_tooltips`.
+ - The math extension displaymath directives now support ``name`` in
+ addition to ``label`` for giving the equation label, for compatibility
+ with Docutils.
+
+* New locales:
+
+ - #221: Added Swedish locale.
+ - #526: Added Iranian locale.
+ - #694: Added Latvian locale.
+ - Added Nepali locale.
+ - #714: Added Korean locale.
+ - #766: Added Estonian locale.
+
+* Bugs fixed:
+
+ - #778: Fix "hide search matches" link on pages linked by search.
+ - Fix the source positions referenced by the "viewcode" extension.
+
+
+Release 1.0.8 (Sep 23, 2011)
+============================
+
+* #627: Fix tracebacks for AttributeErrors in autosummary generation.
+
+* Fix the ``abbr`` role when the abbreviation has newlines in it.
+
+* #727: Fix the links to search results with custom object types.
+
+* #648: Fix line numbers reported in warnings about undefined
+ references.
+
+* #696, #666: Fix C++ array definitions and template arguments
+ that are not type names.
+
+* #633: Allow footnotes in section headers in LaTeX output.
+
+* #616: Allow keywords to be linked via intersphinx.
+
+* #613: Allow Unicode characters in production list token names.
+
+* #720: Add dummy visitors for graphviz nodes for text and man.
+
+* #704: Fix image file duplication bug.
+
+* #677: Fix parsing of multiple signatures in C++ domain.
+
+* #637: Ignore Emacs lock files when looking for source files.
+
+* #544: Allow .pyw extension for importable modules in autodoc.
+
+* #700: Use ``$(MAKE)`` in quickstart-generated Makefiles.
+
+* #734: Make sidebar search box width consistent in browsers.
+
+* #644: Fix spacing of centered figures in HTML output.
+
+* #767: Safely encode SphinxError messages when printing them to
+ sys.stderr.
+
+* #611: Fix LaTeX output error with a document with no sections but
+ a link target.
+
+* Correctly treat built-in method descriptors as methods in autodoc.
+
+* #706: Stop monkeypatching the Python textwrap module.
+
+* #657: viewcode now works correctly with source files that have
+ non-ASCII encoding.
+
+* #669: Respect the ``noindex`` flag option in py:module directives.
+
+* #675: Fix IndexErrors when including nonexisting lines with
+ :rst:dir:`literalinclude`.
+
+* #676: Respect custom function/method parameter separator strings.
+
+* #682: Fix JS incompatibility with jQuery >= 1.5.
+
+* #693: Fix double encoding done when writing HTMLHelp .hhk files.
+
+* #647: Do not apply SmartyPants in parsed-literal blocks.
+
+* C++ domain now supports array definitions.
+
+
+Release 1.0.7 (Jan 15, 2011)
+============================
+
+* #347: Fix wrong generation of directives of static methods in
+ autosummary.
+
+* #599: Import PIL as ``from PIL import Image``.
+
+* #558: Fix longtables with captions in LaTeX output.
+
+* Make token references work as hyperlinks again in LaTeX output.
+
+* #572: Show warnings by default when reference labels cannot be
+ found.
+
+* #536: Include line number when complaining about missing reference
+ targets in nitpicky mode.
+
+* #590: Fix inline display of graphviz diagrams in LaTeX output.
+
+* #589: Build using app.build() in setup command.
+
+* Fix a bug in the inheritance diagram exception that caused base
+ classes to be skipped if one of them is a builtin.
+
+* Fix general index links for C++ domain objects.
+
+* #332: Make admonition boundaries in LaTeX output visible.
+
+* #573: Fix KeyErrors occurring on rebuild after removing a file.
+
+* Fix a traceback when removing files with globbed toctrees.
+
+* If an autodoc object cannot be imported, always re-read the
+ document containing the directive on next build.
+
+* If an autodoc object cannot be imported, show the full traceback
+ of the import error.
+
+* Fix a bug where the removal of download files and images wasn't
+ noticed.
+
+* #571: Implement ``~`` cross-reference prefix for the C domain.
+
+* Fix regression of LaTeX output with the fix of #556.
+
+* #568: Fix lookup of class attribute documentation on descriptors
+ so that comment documentation now works.
+
+* Fix traceback with ``only`` directives preceded by targets.
+
+* Fix tracebacks occurring for duplicate C++ domain objects.
+
+* Fix JavaScript domain links to objects with ``$`` in their name.
+
+
+Release 1.0.6 (Jan 04, 2011)
+============================
+
+* #581: Fix traceback in Python domain for empty cross-reference
+ targets.
+
+* #283: Fix literal block display issues on Chrome browsers.
+
+* #383, #148: Support sorting a limited range of accented characters
+ in the general index and the glossary.
+
+* #570: Try decoding ``-D`` and ``-A`` command-line arguments with
+ the locale's preferred encoding.
+
+* #528: Observe :confval:`locale_dirs` when looking for the JS
+ translations file.
+
+* #574: Add special code for better support of Japanese documents
+ in the LaTeX builder.
+
+* Regression of #77: If there is only one parameter given with
+ ``:param:`` markup, the bullet list is now suppressed again.
+
+* #556: Fix missing paragraph breaks in LaTeX output in certain
+ situations.
+
+* #567: Emit the ``autodoc-process-docstring`` event even for objects
+ without a docstring so that it can add content.
+
+* #565: In the LaTeX builder, not only literal blocks require different
+ table handling, but also quite a few other list-like block elements.
+
+* #515: Fix tracebacks in the viewcode extension for Python objects
+ that do not have a valid signature.
+
+* Fix strange reportings of line numbers for warnings generated from
+ autodoc-included docstrings, due to different behavior depending
+ on docutils version.
+
+* Several fixes to the C++ domain.
+
+
+Release 1.0.5 (Nov 12, 2010)
+============================
+
+* #557: Add CSS styles required by docutils 0.7 for aligned images
+ and figures.
+
+* In the Makefile generated by LaTeX output, do not delete pdf files
+ on clean; they might be required images.
+
+* #535: Fix LaTeX output generated for line blocks.
+
+* #544: Allow ``.pyw`` as a source file extension.
+
+
+Release 1.0.4 (Sep 17, 2010)
+============================
+
+* #524: Open intersphinx inventories in binary mode on Windows,
+ since version 2 contains zlib-compressed data.
+
+* #513: Allow giving non-local URIs for JavaScript files, e.g.
+ in the JSMath extension.
+
+* #512: Fix traceback when ``intersphinx_mapping`` is empty.
+
+
+Release 1.0.3 (Aug 23, 2010)
+============================
+
+* #495: Fix internal vs. external link distinction for links coming
+ from a docutils table-of-contents.
+
+* #494: Fix the ``maxdepth`` option for the ``toctree()`` template
+ callable when used with ``collapse=True``.
+
+* #507: Fix crash parsing Python argument lists containing brackets
+ in string literals.
+
+* #501: Fix regression when building LaTeX docs with figures that
+ don't have captions.
+
+* #510: Fix inheritance diagrams for classes that are not picklable.
+
+* #497: Introduce separate background color for the sidebar collapse
+ button, making it easier to see.
+
+* #502, #503, #496: Fix small layout bugs in several builtin themes.
+
+
+Release 1.0.2 (Aug 14, 2010)
+============================
+
+* #490: Fix cross-references to objects of types added by the
+ :func:`~.Sphinx.add_object_type` API function.
+
+* Fix handling of doc field types for different directive types.
+
+* Allow breaking long signatures, continuing with backlash-escaped
+ newlines.
+
+* Fix unwanted styling of C domain references (because of a namespace
+ clash with Pygments styles).
+
+* Allow references to PEPs and RFCs with explicit anchors.
+
+* #471: Fix LaTeX references to figures.
+
+* #482: When doing a non-exact search, match only the given type
+ of object.
+
+* #481: Apply non-exact search for Python reference targets with
+ ``.name`` for modules too.
+
+* #484: Fix crash when duplicating a parameter in an info field list.
+
+* #487: Fix setting the default role to one provided by the
+ ``oldcmarkup`` extension.
+
+* #488: Fix crash when json-py is installed, which provides a
+ ``json`` module but is incompatible to simplejson.
+
+* #480: Fix handling of target naming in intersphinx.
+
+* #486: Fix removal of ``!`` for all cross-reference roles.
+
+
+Release 1.0.1 (Jul 27, 2010)
+============================
+
+* #470: Fix generated target names for reST domain objects; they
+ are not in the same namespace.
+
+* #266: Add Bengali language.
+
+* #473: Fix a bug in parsing JavaScript object names.
+
+* #474: Fix building with SingleHTMLBuilder when there is no toctree.
+
+* Fix display names for objects linked to by intersphinx with
+ explicit targets.
+
+* Fix building with the JSON builder.
+
+* Fix hyperrefs in object descriptions for LaTeX.
+
+
+Release 1.0 (Jul 23, 2010)
+==========================
+
+Incompatible changes
+--------------------
+
+* Support for domains has been added. A domain is a collection of
+ directives and roles that all describe objects belonging together,
+ e.g. elements of a programming language. A few builtin domains are
+ provided:
+
+ - Python
+ - C
+ - C++
+ - JavaScript
+ - reStructuredText
+
+* The old markup for defining and linking to C directives is now
+ deprecated. It will not work anymore in future versions without
+ activating the :mod:`~sphinx.ext.oldcmarkup` extension; in Sphinx
+ 1.0, it is activated by default.
+
+* Removed support for old dependency versions; requirements are now:
+
+ - docutils >= 0.5
+ - Jinja2 >= 2.2
+
+* Removed deprecated elements:
+
+ - ``exclude_dirs`` config value
+ - ``sphinx.builder`` module
+
+Features added
+--------------
+
+* General:
+
+ - Added a "nitpicky" mode that emits warnings for all missing
+ references. It is activated by the :option:`-n` command-line switch
+ or the :confval:`nitpicky` config value.
+ - Added ``latexpdf`` target in quickstart Makefile.
+
+* Markup:
+
+ - The :rst:role:`menuselection` and :rst:role:`guilabel` roles now
+ support ampersand accelerators.
+ - New more compact doc field syntax is now recognized: ``:param type
+ name: description``.
+ - Added ``tab-width`` option to :rst:dir:`literalinclude` directive.
+ - Added ``titlesonly`` option to :rst:dir:`toctree` directive.
+ - Added the ``prepend`` and ``append`` options to the
+ :rst:dir:`literalinclude` directive.
+ - #284: All docinfo metadata is now put into the document metadata, not
+ just the author.
+ - The :rst:role:`ref` role can now also reference tables by caption.
+ - The :rst:dir:`include` directive now supports absolute paths, which
+ are interpreted as relative to the source directory.
+ - In the Python domain, references like ``:func:`.name``` now look for
+ matching names with any prefix if no direct match is found.
+
+* Configuration:
+
+ - Added :confval:`rst_prolog` config value.
+ - Added :confval:`html_secnumber_suffix` config value to control
+ section numbering format.
+ - Added :confval:`html_compact_lists` config value to control
+ docutils' compact lists feature.
+ - The :confval:`html_sidebars` config value can now contain patterns
+ as keys, and the values can be lists that explicitly select which
+ sidebar templates should be rendered. That means that the builtin
+ sidebar contents can be included only selectively.
+ - :confval:`html_static_path` can now contain single file entries.
+ - The new universal config value :confval:`exclude_patterns` makes the
+ old :confval:`unused_docs`, :confval:`exclude_trees` and
+ :confval:`exclude_dirnames` obsolete.
+ - Added :confval:`html_output_encoding` config value.
+ - Added the :confval:`latex_docclass` config value and made the
+ "twoside" documentclass option overridable by "oneside".
+ - Added the :confval:`trim_doctest_flags` config value, which is true
+ by default.
+ - Added :confval:`html_show_copyright` config value.
+ - Added :confval:`latex_show_pagerefs` and :confval:`latex_show_urls`
+ config values.
+ - The behavior of :confval:`html_file_suffix` changed slightly: the
+ empty string now means "no suffix" instead of "default suffix", use
+ ``None`` for "default suffix".
+
+* New builders:
+
+ - Added a builder for the Epub format.
+ - Added a builder for manual pages.
+ - Added a single-file HTML builder.
+
+* HTML output:
+
+ - Inline roles now get a CSS class with their name, allowing styles to
+ customize their appearance. Domain-specific roles get two classes,
+ ``domain`` and ``domain-rolename``.
+ - References now get the class ``internal`` if they are internal to
+ the whole project, as opposed to internal to the current page.
+ - External references can be styled differently with the new
+ ``externalrefs`` theme option for the default theme.
+ - In the default theme, the sidebar can experimentally now be made
+ collapsible using the new ``collapsiblesidebar`` theme option.
+ - #129: Toctrees are now wrapped in a ``div`` tag with class
+ ``toctree-wrapper`` in HTML output.
+ - The :data:`toctree` callable in templates now has a ``maxdepth``
+ keyword argument to control the depth of the generated tree.
+ - The :data:`toctree` callable in templates now accepts a
+ ``titles_only`` keyword argument.
+ - Added ``htmltitle`` block in layout template.
+ - In the JavaScript search, allow searching for object names including
+ the module name, like ``sys.argv``.
+ - Added new theme ``haiku``, inspired by the Haiku OS user guide.
+ - Added new theme ``nature``.
+ - Added new theme ``agogo``, created by Andi Albrecht.
+ - Added new theme ``scrolls``, created by Armin Ronacher.
+ - #193: Added a ``visitedlinkcolor`` theme option to the default
+ theme.
+ - #322: Improved responsiveness of the search page by loading the
+ search index asynchronously.
+
+* Extension API:
+
+ - Added :event:`html-collect-pages`.
+ - Added :confval:`needs_sphinx` config value and
+ :meth:`~sphinx.application.Sphinx.require_sphinx` application API
+ method.
+ - #200: Added :meth:`~sphinx.application.Sphinx.add_stylesheet`
+ application API method.
+
+* Extensions:
+
+ - Added the :mod:`~sphinx.ext.viewcode` extension.
+ - Added the :mod:`~sphinx.ext.extlinks` extension.
+ - Added support for source ordering of members in autodoc, with
+ ``autodoc_member_order = 'bysource'``.
+ - Added :confval:`autodoc_default_flags` config value, which can be
+ used to select default flags for all autodoc directives.
+ - Added a way for intersphinx to refer to named labels in other
+ projects, and to specify the project you want to link to.
+ - #280: Autodoc can now document instance attributes assigned in
+ ``__init__`` methods.
+ - Many improvements and fixes to the :mod:`~sphinx.ext.autosummary`
+ extension, thanks to Pauli Virtanen.
+ - #309: The :mod:`~sphinx.ext.graphviz` extension can now output SVG
+ instead of PNG images, controlled by the
+ :confval:`graphviz_output_format` config value.
+ - Added ``alt`` option to :rst:dir:`graphviz` extension directives.
+ - Added ``exclude`` argument to :func:`.autodoc.between`.
+
+* Translations:
+
+ - Added Croatian translation, thanks to Bojan Mihelač.
+ - Added Turkish translation, thanks to Firat Ozgul.
+ - Added Catalan translation, thanks to Pau Fernández.
+ - Added simplified Chinese translation.
+ - Added Danish translation, thanks to Hjorth Larsen.
+ - Added Lithuanian translation, thanks to Dalius Dobravolskas.
+
+* Bugs fixed:
+
+ - #445: Fix links to result pages when using the search function
+ of HTML built with the ``dirhtml`` builder.
+ - #444: In templates, properly re-escape values treated with the
+ "striptags" Jinja filter.
+
+
+Previous versions
+=================
+
+The changelog for versions before 1.0 can be found in the file ``CHANGES.old``
+in the source distribution or `at BitBucket
+<https://bitbucket.org/birkenfeld/sphinx/raw/tip/CHANGES.old>`__.
diff --git a/EXAMPLES b/EXAMPLES
new file mode 100644
index 0000000..cc4c4de
--- /dev/null
+++ b/EXAMPLES
@@ -0,0 +1,234 @@
+Projects using Sphinx
+=====================
+
+This is an (incomplete) alphabetic list of projects that use Sphinx or
+are experimenting with using it for their documentation. If you like to
+be included, please mail to `the Google group
+<https://groups.google.com/group/sphinx-users>`_.
+
+I've grouped the list into sections to make it easier to find
+interesting examples.
+
+Documentation using the default theme
+-------------------------------------
+
+* APSW: http://apidoc.apsw.googlecode.com/hg/index.html
+* ASE: https://wiki.fysik.dtu.dk/ase/
+* boostmpi: http://documen.tician.de/boostmpi/
+* Calibre: http://manual.calibre-ebook.com/
+* CodePy: http://documen.tician.de/codepy/
+* Cython: http://docs.cython.org/
+* C\\C++ Python language binding project: http://language-binding.net/index.html
+* Cormoran: http://cormoran.nhopkg.org/docs/
+* Director: http://pythonhosted.org/director/
+* Dirigible: http://www.projectdirigible.com/documentation/
+* Elemental: http://elemental.googlecode.com/hg/doc/build/html/index.html
+* F2py: http://f2py.sourceforge.net/docs/
+* GeoDjango: http://geodjango.org/docs/
+* Genomedata: http://noble.gs.washington.edu/proj/genomedata/doc/1.2.2/genomedata.html
+* gevent: http://www.gevent.org/
+* Google Wave API: http://wave-robot-python-client.googlecode.com/svn/trunk/pydocs/index.html
+* GSL Shell: http://www.nongnu.org/gsl-shell/
+* Heapkeeper: http://heapkeeper.org/
+* Hands-on Python Tutorial: http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/
+* Hedge: http://documen.tician.de/hedge/
+* Kaa: http://doc.freevo.org/api/kaa/
+* Leo: http://webpages.charter.net/edreamleo/front.html
+* Lino: http://lino.saffre-rumma.net/
+* MeshPy: http://documen.tician.de/meshpy/
+* mpmath: http://mpmath.googlecode.com/svn/trunk/doc/build/index.html
+* OpenEXR: http://excamera.com/articles/26/doc/index.html
+* OpenGDA: http://www.opengda.org/gdadoc/html/
+* openWNS: http://docs.openwns.org/
+* Paste: http://pythonpaste.org/script/
+* Paver: http://paver.github.com/paver/
+* Pioneers and Prominent Men of Utah: http://pioneers.rstebbing.com/
+* Pyccuracy: https://github.com/heynemann/pyccuracy/wiki/
+* PyCuda: http://documen.tician.de/pycuda/
+* Pyevolve: http://pyevolve.sourceforge.net/
+* Pylo: http://documen.tician.de/pylo/
+* PyMQI: http://packages.python.org/pymqi/
+* PyPubSub: http://pubsub.sourceforge.net/
+* pyrticle: http://documen.tician.de/pyrticle/
+* Python: http://docs.python.org/
+* python-apt: http://apt.alioth.debian.org/python-apt-doc/
+* PyUblas: http://documen.tician.de/pyublas/
+* Quex: http://quex.sourceforge.net/doc/html/main.html
+* Scapy: http://www.secdev.org/projects/scapy/doc/
+* Segway: http://noble.gs.washington.edu/proj/segway/doc/1.1.0/segway.html
+* SimPy: http://simpy.sourceforge.net/SimPyDocs/index.html
+* SymPy: http://docs.sympy.org/
+* WTForms: http://wtforms.simplecodes.com/docs/
+* z3c: http://docs.carduner.net/z3c-tutorial/
+
+
+Documentation using a customized version of the default theme
+-------------------------------------------------------------
+
+* Advanced Generic Widgets:
+ http://xoomer.virgilio.it/infinity77/AGW_Docs/index.html
+* Bazaar: http://doc.bazaar.canonical.com/en/
+* CakePHP: http://book.cakephp.org/2.0/en/index.html
+* Chaco: http://code.enthought.com/projects/chaco/docs/html/
+* Chef: http://docs.opscode.com/
+* Djagios: http://djagios.org/
+* GetFEM++: http://home.gna.org/getfem/
+* Google or-tools: https://or-tools.googlecode.com/svn/trunk/documentation/user_manual/index.html
+* GPAW: https://wiki.fysik.dtu.dk/gpaw/
+* Grok: http://grok.zope.org/doc/current/
+* IFM: http://fluffybunny.memebot.com/ifm-docs/index.html
+* LEPL: http://www.acooke.org/lepl/
+* Mayavi: http://code.enthought.com/projects/mayavi/docs/development/html/mayavi
+* NOC: http://redmine.nocproject.org/projects/noc
+* NumPy: http://docs.scipy.org/doc/numpy/reference/
+* OpenCV: http://docs.opencv.org/
+* Peach^3: http://peach3.nl/doc/latest/userdoc/
+* PyLit: http://pylit.berlios.de/
+* Sage: http://sagemath.org/doc/
+* SciPy: http://docs.scipy.org/doc/scipy/reference/
+* simuPOP: http://simupop.sourceforge.net/manual_release/build/userGuide.html
+* Sprox: http://sprox.org/
+* TurboGears: http://turbogears.org/2.0/docs/
+* Varnish: https://www.varnish-cache.org/docs/
+* Zentyal: http://doc.zentyal.org/
+* Zope: http://docs.zope.org/zope2/index.html
+* zc.async: http://packages.python.org/zc.async/1.5.0/
+
+
+Documentation using the sphinxdoc theme
+---------------------------------------
+
+* Fityk: http://fityk.nieto.pl/
+* MapServer: http://mapserver.org/
+* Matplotlib: http://matplotlib.sourceforge.net/
+* Music21: http://mit.edu/music21/doc/html/contents.html
+* MyHDL: http://www.myhdl.org/doc/0.6/
+* NetworkX: http://networkx.lanl.gov/
+* Pweave: http://mpastell.com/pweave/
+* Pyre: http://docs.danse.us/pyre/sphinx/
+* Pysparse: http://pysparse.sourceforge.net/
+* PyTango:
+ http://www.tango-controls.org/static/PyTango/latest/doc/html/index.html
+* Python Wild Magic:
+ http://python-wild-magic.googlecode.com/svn/doc/html/index.html
+* Reteisi: http://www.reteisi.org/contents.html
+* Satchmo: http://www.satchmoproject.com/docs/dev/
+* Sphinx: http://sphinx-doc.org/
+* Sqlkit: http://sqlkit.argolinux.org/
+* Tau: http://www.tango-controls.org/static/tau/latest/doc/html/index.html
+* Total Open Station: http://tops.berlios.de/
+* Turbulenz: http://docs.turbulenz.com/
+* WebFaction: http://docs.webfaction.com/
+
+
+Documentation using another builtin theme
+-----------------------------------------
+
+* C/C++ Development with Eclipse: http://eclipsebook.in/ (agogo)
+* Distribute: http://packages.python.org/distribute/ (nature)
+* Jinja: http://jinja.pocoo.org/ (scrolls)
+* jsFiddle: http://doc.jsfiddle.net/ (nature)
+* libLAS: http://liblas.org/ (nature)
+* MPipe: http://vmlaker.github.io/mpipe/ (sphinx13)
+* pip: http://pip.openplans.org/ (nature)
+* Programmieren mit PyGTK und Glade (German):
+ http://www.florian-diesch.de/doc/python-und-glade/online/ (agogo)
+* Spring Python: http://springpython.webfactional.com/current/sphinx/index.html
+ (nature)
+* sqlparse: http://python-sqlparse.googlecode.com/svn/docs/api/index.html
+ (agogo)
+* Sylli: http://sylli.sourceforge.net/ (nature)
+* Tuleap Open ALM: https://tuleap.net/doc/en/ (nature)
+* Valence: http://docs.valence.desire2learn.com/ (haiku)
+
+
+Documentation using a custom theme/integrated in a site
+-------------------------------------------------------
+
+* Blender: http://www.blender.org/documentation/250PythonDoc/
+* Blinker: http://discorporate.us/projects/Blinker/docs/
+* Ceph: http://ceph.com/docs/master/
+* Classy: http://classy.pocoo.org/
+* DEAP: http://deap.gel.ulaval.ca/doc/0.8/index.html
+* Django: http://docs.djangoproject.com/
+* Enterprise Toolkit for Acrobat products: http://www.adobe.com/devnet-docs/acrobatetk/
+* e-cidadania: http://e-cidadania.readthedocs.org/en/latest/
+* Flask: http://flask.pocoo.org/docs/
+* Flask-OpenID: http://packages.python.org/Flask-OpenID/
+* Gameduino: http://excamera.com/sphinx/gameduino/
+* GeoServer: http://docs.geoserver.org/
+* Glashammer: http://glashammer.org/
+* Istihza (Turkish Python documentation project): http://www.istihza.com/py2/icindekiler_python.html
+* MathJax: http://docs.mathjax.org/en/latest/
+* MirrorBrain: http://mirrorbrain.org/docs/
+* nose: http://somethingaboutorange.com/mrl/projects/nose/
+* NoTex: https://notex.ch/overview/
+* ObjectListView: http://objectlistview.sourceforge.net/python
+* Open ERP: http://doc.openerp.com/
+* OpenCV: http://docs.opencv.org/
+* Open Dylan: http://opendylan.org/documentation/ and also provides
+ `dylan domain <https://github.com/dylan-lang/sphinx-extensions/blob/master/dylandomain/reference.rst>`__
+* OpenLayers: http://docs.openlayers.org/
+* PyEphem: http://rhodesmill.org/pyephem/
+* German Plone user manual: http://www.hasecke.com/plone-benutzerhandbuch/
+* PSI4: http://sirius.chem.vt.edu/psi4manual/latest/index.html
+* Pylons: http://pylonshq.com/docs/en/0.9.7/
+* PyMOTW: http://www.doughellmann.com/PyMOTW/
+* pypol: http://pypol.altervista.org/ (celery)
+* QGIS: http://qgis.org/
+* qooxdoo: http://manual.qooxdoo.org/current
+* Roundup: http://www.roundup-tracker.org/
+* Selenium: http://seleniumhq.org/docs/
+* Self: http://selflanguage.org/
+* Tablib: http://tablib.org/
+* SQLAlchemy: http://www.sqlalchemy.org/docs/
+* tinyTiM: http://tinytim.sourceforge.net/docs/2.0/
+* tipfy: http://www.tipfy.org/docs/
+* Ubuntu packaging guide: http://packaging.ubuntu.com/html/
+* Werkzeug: http://werkzeug.pocoo.org/docs/
+* WFront: http://discorporate.us/projects/WFront/
+
+
+Homepages and other non-documentation sites
+-------------------------------------------
+
+* Applied Mathematics at the Stellenbosch University: http://dip.sun.ac.za/
+* A personal page: http://www.dehlia.in/
+* Benoit Boissinot: http://bboissin.appspot.com/
+* lunarsite: http://lunaryorn.de/
+* Red Hot Chili Python: http://redhotchilipython.com/
+* The Wine Cellar Book: http://www.thewinecellarbook.com/doc/en/
+* Uni. Berkeley Advanced Control Systems course: http://www.me.berkeley.edu/ME233/sp14/
+* VOR: http://www.vor-cycling.be/
+
+
+Books produced using Sphinx
+---------------------------
+
+* "The ``repoze.bfg`` Web Application Framework":
+ http://www.amazon.com/repoze-bfg-Web-Application-Framework-Version/dp/0615345379
+* A Theoretical Physics Reference book: http://theoretical-physics.net/
+* "Simple and Steady Way of Learning for Software Engineering" (in Japanese):
+ http://www.amazon.co.jp/dp/477414259X/
+* "Expert Python Programming":
+ http://www.packtpub.com/expert-python-programming/book
+* "Expert Python Programming" (Japanese translation):
+ http://www.amazon.co.jp/dp/4048686291/
+* "Pomodoro Technique Illustrated" (Japanese translation):
+ http://www.amazon.co.jp/dp/4048689525/
+* "Python Professional Programming" (in Japanese):
+ http://www.amazon.co.jp/dp/4798032948/
+* "Die Wahrheit des Sehens. Der DEKALOG von Krzysztof Kieślowski":
+ http://www.hasecke.eu/Dekalog/
+* The "Varnish Book":
+ https://www.varnish-software.com/static/book/
+* "Learning Sphinx" (in Japanese):
+ http://www.oreilly.co.jp/books/9784873116488/
+
+
+Thesis using Sphinx
+-------------------
+
+* "A Web-Based System for Comparative Analysis of OpenStreetMap Data
+ by the Use of CouchDB":
+ http://gisforge.no-ip.org/files/MasterThesis_MarkusMayr_0542042.pdf
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7aa7620
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,246 @@
+License for Sphinx
+==================
+
+Copyright (c) 2007-2013 by the Sphinx team (see AUTHORS file).
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* 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
+OWNER 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.
+
+
+Licenses for incorporated software
+==================================
+
+The pgen2 package, included in this distribution under the name
+sphinx.pycode.pgen2, is available in the Python 2.6 distribution under
+the PSF license agreement for Python:
+
+----------------------------------------------------------------------
+Copyright © 2001-2008 Python Software Foundation; All Rights Reserved.
+
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+--------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+ ("PSF"), and the Individual or Organization ("Licensee") accessing
+ and otherwise using Python 2.6 software in source or binary form
+ and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+ hereby grants Licensee a nonexclusive, royalty-free, world-wide
+ license to reproduce, analyze, test, perform and/or display
+ publicly, prepare derivative works, distribute, and otherwise use
+ Python 2.6 alone or in any derivative version, provided, however,
+ that PSF's License Agreement and PSF's notice of copyright, i.e.,
+ "Copyright © 2001-2008 Python Software Foundation; All Rights
+ Reserved" are retained in Python 2.6 alone or in any derivative
+ version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+ or incorporates Python 2.6 or any part thereof, and wants to make
+ the derivative work available to others as provided herein, then
+ Licensee hereby agrees to include in any such work a brief summary
+ of the changes made to Python 2.6.
+
+4. PSF is making Python 2.6 available to Licensee on an "AS IS" basis.
+ PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY
+ WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY
+ REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY
+ PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.6 WILL NOT INFRINGE
+ ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+ 2.6 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
+ AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON
+ 2.6, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY
+ THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+ breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+ relationship of agency, partnership, or joint venture between PSF
+ and Licensee. This License Agreement does not grant permission to
+ use PSF trademarks or trade name in a trademark sense to endorse or
+ promote products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python 2.6, Licensee
+ agrees to be bound by the terms and conditions of this License
+ Agreement.
+----------------------------------------------------------------------
+
+The included smartypants module, included as sphinx.util.smartypants,
+is available under the following license:
+
+----------------------------------------------------------------------
+SmartyPants_ license::
+
+ Copyright (c) 2003 John Gruber
+ (http://daringfireball.net/)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name "SmartyPants" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+ 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 owner 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.
+
+
+smartypants.py license::
+
+ smartypants.py is a derivative work of SmartyPants.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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 owner 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.
+----------------------------------------------------------------------
+
+The ElementTree package, included in this distribution in
+test/etree13, is available under the following license:
+
+----------------------------------------------------------------------
+The ElementTree toolkit is
+
+Copyright (c) 1999-2007 by Fredrik Lundh
+
+By obtaining, using, and/or copying this software and/or its
+associated documentation, you agree that you have read, understood,
+and will comply with the following terms and conditions:
+
+Permission to use, copy, modify, and distribute this software and its
+associated documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies, and that both that copyright notice and this permission notice
+appear in supporting documentation, and that the name of Secret Labs
+AB or the author not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- ABILITY
+AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+----------------------------------------------------------------------
+
+The included JQuery JavaScript library is available under the MIT
+license:
+
+----------------------------------------------------------------------
+Copyright (c) 2008 John Resig, http://jquery.com/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+----------------------------------------------------------------------
+
+The included Underscore JavaScript library is available under the MIT
+license:
+
+----------------------------------------------------------------------
+Copyright (c) 2009 Jeremy Ashkenas, DocumentCloud
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..5db26b8
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,27 @@
+include README.rst
+include LICENSE
+include AUTHORS
+include CHANGES
+include EXAMPLES
+include TODO
+
+include babel.cfg
+include Makefile
+include ez_setup.py
+include sphinx-autogen.py
+include sphinx-build.py
+include sphinx-quickstart.py
+include sphinx-apidoc.py
+
+recursive-include sphinx/texinputs *
+recursive-include sphinx/themes *
+recursive-include sphinx/locale *
+recursive-include sphinx/ext/autosummary/templates *
+recursive-include tests *
+recursive-include utils *
+recursive-include custom_fixers *
+include sphinx/pycode/Grammar-py2.txt
+include sphinx/pycode/Grammar-py3.txt
+
+recursive-include doc *
+prune doc/_build
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..128b2c8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,64 @@
+PYTHON ?= python
+
+.PHONY: all check clean clean-pyc clean-patchfiles clean-backupfiles \
+ clean-generated pylint reindent test covertest build convert-utils
+
+DONT_CHECK = -i build -i dist -i sphinx/style/jquery.js \
+ -i sphinx/pycode/pgen2 -i sphinx/util/smartypants.py \
+ -i .ropeproject -i doc/_build -i tests/path.py \
+ -i tests/coverage.py -i env -i utils/convert.py \
+ -i sphinx/search/ja.py \
+ -i utils/reindent3.py -i utils/check_sources3.py -i .tox
+
+all: clean-pyc clean-backupfiles check test
+
+ifeq ($(PYTHON), python3)
+check: convert-utils
+ @$(PYTHON) utils/check_sources3.py $(DONT_CHECK) .
+else
+check:
+ @$(PYTHON) utils/check_sources.py $(DONT_CHECK) .
+endif
+
+clean: clean-pyc clean-patchfiles clean-backupfiles clean-generated
+
+clean-pyc:
+ find . -name '*.pyc' -exec rm -f {} +
+ find . -name '*.pyo' -exec rm -f {} +
+
+clean-patchfiles:
+ find . -name '*.orig' -exec rm -f {} +
+ find . -name '*.rej' -exec rm -f {} +
+
+clean-backupfiles:
+ find . -name '*~' -exec rm -f {} +
+ find . -name '*.bak' -exec rm -f {} +
+
+clean-generated:
+ rm -f utils/*3.py*
+
+pylint:
+ @pylint --rcfile utils/pylintrc sphinx
+
+ifeq ($(PYTHON), python3)
+reindent: convert-utils
+ @$(PYTHON) utils/reindent3.py -r -n .
+else
+reindent:
+ @$(PYTHON) utils/reindent.py -r -n .
+endif
+
+test: build
+ @cd tests; $(PYTHON) run.py -d -m '^[tT]est' $(TEST)
+
+covertest: build
+ @cd tests; $(PYTHON) run.py -d -m '^[tT]est' --with-coverage \
+ --cover-package=sphinx $(TEST)
+
+build:
+ @$(PYTHON) setup.py build
+
+ifeq ($(PYTHON), python3)
+convert-utils:
+ @python3 utils/convert.py -i utils/convert.py utils/
+endif
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..5af5cd4
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,51 @@
+Metadata-Version: 1.1
+Name: Sphinx
+Version: 1.2.3
+Summary: Python documentation generator
+Home-page: http://sphinx-doc.org/
+Author: Georg Brandl
+Author-email: georg at python.org
+License: BSD
+Download-URL: http://pypi.python.org/pypi/Sphinx
+Description:
+ Sphinx is a tool that makes it easy to create intelligent and beautiful
+ documentation for Python projects (or other documents consisting of multiple
+ reStructuredText sources), written by Georg Brandl. It was originally created
+ for the new Python documentation, and has excellent facilities for Python
+ project documentation, but C/C++ is supported as well, and more languages are
+ planned.
+
+ Sphinx uses reStructuredText as its markup language, and many of its strengths
+ come from the power and straightforwardness of reStructuredText and its parsing
+ and translating suite, the Docutils.
+
+ Among its features are the following:
+
+ * Output formats: HTML (including derivative formats such as HTML Help, Epub
+ and Qt Help), plain text, manual pages and LaTeX or direct PDF output
+ using rst2pdf
+ * Extensive cross-references: semantic markup and automatic links
+ for functions, classes, glossary terms and similar pieces of information
+ * Hierarchical structure: easy definition of a document tree, with automatic
+ links to siblings, parents and children
+ * Automatic indices: general index as well as a module index
+ * Code handling: automatic highlighting using the Pygments highlighter
+ * Flexible HTML output using the Jinja 2 templating engine
+ * Various extensions are available, e.g. for automatic testing of snippets
+ and inclusion of appropriately formatted docstrings
+ * Setuptools integration
+
+Platform: any
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Console
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Education
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Documentation
+Classifier: Topic :: Text Processing
+Classifier: Topic :: Utilities
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..5963a0a
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,42 @@
+=================
+README for Sphinx
+=================
+
+Installing
+==========
+
+Use ``setup.py``::
+
+ python setup.py build
+ sudo python setup.py install
+
+
+Reading the docs
+================
+
+After installing::
+
+ cd doc
+ sphinx-build . _build/html
+
+Then, direct your browser to ``_build/html/index.html``.
+
+Or read them online at <http://sphinx-doc.org/>.
+
+
+Testing
+=======
+
+To run the tests with the interpreter available as ``python``, use::
+
+ make test
+
+If you want to use a different interpreter, e.g. ``python3``, use::
+
+ PYTHON=python3 make test
+
+
+Contributing
+============
+
+Send wishes, comments, patches, etc. to sphinx-dev at googlegroups.com.
diff --git a/Sphinx.egg-info/PKG-INFO b/Sphinx.egg-info/PKG-INFO
new file mode 100644
index 0000000..5af5cd4
--- /dev/null
+++ b/Sphinx.egg-info/PKG-INFO
@@ -0,0 +1,51 @@
+Metadata-Version: 1.1
+Name: Sphinx
+Version: 1.2.3
+Summary: Python documentation generator
+Home-page: http://sphinx-doc.org/
+Author: Georg Brandl
+Author-email: georg at python.org
+License: BSD
+Download-URL: http://pypi.python.org/pypi/Sphinx
+Description:
+ Sphinx is a tool that makes it easy to create intelligent and beautiful
+ documentation for Python projects (or other documents consisting of multiple
+ reStructuredText sources), written by Georg Brandl. It was originally created
+ for the new Python documentation, and has excellent facilities for Python
+ project documentation, but C/C++ is supported as well, and more languages are
+ planned.
+
+ Sphinx uses reStructuredText as its markup language, and many of its strengths
+ come from the power and straightforwardness of reStructuredText and its parsing
+ and translating suite, the Docutils.
+
+ Among its features are the following:
+
+ * Output formats: HTML (including derivative formats such as HTML Help, Epub
+ and Qt Help), plain text, manual pages and LaTeX or direct PDF output
+ using rst2pdf
+ * Extensive cross-references: semantic markup and automatic links
+ for functions, classes, glossary terms and similar pieces of information
+ * Hierarchical structure: easy definition of a document tree, with automatic
+ links to siblings, parents and children
+ * Automatic indices: general index as well as a module index
+ * Code handling: automatic highlighting using the Pygments highlighter
+ * Flexible HTML output using the Jinja 2 templating engine
+ * Various extensions are available, e.g. for automatic testing of snippets
+ and inclusion of appropriately formatted docstrings
+ * Setuptools integration
+
+Platform: any
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Console
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Education
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Documentation
+Classifier: Topic :: Text Processing
+Classifier: Topic :: Utilities
diff --git a/Sphinx.egg-info/SOURCES.txt b/Sphinx.egg-info/SOURCES.txt
new file mode 100644
index 0000000..2f9ea11
--- /dev/null
+++ b/Sphinx.egg-info/SOURCES.txt
@@ -0,0 +1,617 @@
+AUTHORS
+CHANGES
+EXAMPLES
+LICENSE
+MANIFEST.in
+Makefile
+README.rst
+TODO
+babel.cfg
+ez_setup.py
+setup.cfg
+setup.py
+sphinx-apidoc.py
+sphinx-autogen.py
+sphinx-build.py
+sphinx-quickstart.py
+Sphinx.egg-info/PKG-INFO
+Sphinx.egg-info/SOURCES.txt
+Sphinx.egg-info/dependency_links.txt
+Sphinx.egg-info/entry_points.txt
+Sphinx.egg-info/not-zip-safe
+Sphinx.egg-info/requires.txt
+Sphinx.egg-info/top_level.txt
+custom_fixers/__init__.py
+custom_fixers/fix_alt_unicode.py
+doc/Makefile
+doc/builders.rst
+doc/changes.rst
+doc/conf.py
+doc/config.rst
+doc/contents.rst
+doc/develop.rst
+doc/devguide.rst
+doc/domains.rst
+doc/examples.rst
+doc/extensions.rst
+doc/faq.rst
+doc/glossary.rst
+doc/install.rst
+doc/installpython.jpg
+doc/intl.rst
+doc/intro.rst
+doc/invocation.rst
+doc/more.png
+doc/pythonorg.png
+doc/rest.rst
+doc/templating.rst
+doc/theming.rst
+doc/translation.png
+doc/tutorial.rst
+doc/websupport.rst
+doc/_static/bookcover.png
+doc/_static/pocoo.png
+doc/_static/sphinx.png
+doc/_templates/index.html
+doc/_templates/indexsidebar.html
+doc/_themes/sphinx13/layout.html
+doc/_themes/sphinx13/theme.conf
+doc/_themes/sphinx13/static/bodybg.png
+doc/_themes/sphinx13/static/footerbg.png
+doc/_themes/sphinx13/static/headerbg.png
+doc/_themes/sphinx13/static/listitem.png
+doc/_themes/sphinx13/static/relbg.png
+doc/_themes/sphinx13/static/sphinx13.css
+doc/_themes/sphinx13/static/sphinxheader.png
+doc/ext/autodoc.rst
+doc/ext/autosummary.rst
+doc/ext/coverage.rst
+doc/ext/doctest.rst
+doc/ext/extlinks.rst
+doc/ext/graphviz.rst
+doc/ext/ifconfig.rst
+doc/ext/inheritance.rst
+doc/ext/intersphinx.rst
+doc/ext/linkcode.rst
+doc/ext/math.rst
+doc/ext/oldcmarkup.rst
+doc/ext/todo.rst
+doc/ext/viewcode.rst
+doc/extdev/appapi.rst
+doc/extdev/builderapi.rst
+doc/extdev/domainapi.rst
+doc/extdev/envapi.rst
+doc/extdev/index.rst
+doc/extdev/markupapi.rst
+doc/extdev/nodes.rst
+doc/extdev/tutorial.rst
+doc/man/sphinx-apidoc.rst
+doc/man/sphinx-build.rst
+doc/man/sphinx-quickstart.rst
+doc/markup/code.rst
+doc/markup/index.rst
+doc/markup/inline.rst
+doc/markup/misc.rst
+doc/markup/para.rst
+doc/markup/toctree.rst
+doc/themes/agogo.png
+doc/themes/default.png
+doc/themes/haiku.png
+doc/themes/nature.png
+doc/themes/pyramid.png
+doc/themes/scrolls.png
+doc/themes/sphinxdoc.png
+doc/themes/traditional.png
+doc/themes/fullsize/agogo.png
+doc/themes/fullsize/default.png
+doc/themes/fullsize/haiku.png
+doc/themes/fullsize/nature.png
+doc/themes/fullsize/pyramid.png
+doc/themes/fullsize/scrolls.png
+doc/themes/fullsize/sphinxdoc.png
+doc/themes/fullsize/traditional.png
+doc/web/api.rst
+doc/web/quickstart.rst
+doc/web/searchadapters.rst
+doc/web/storagebackends.rst
+sphinx/__init__.py
+sphinx/addnodes.py
+sphinx/apidoc.py
+sphinx/application.py
+sphinx/cmdline.py
+sphinx/config.py
+sphinx/environment.py
+sphinx/errors.py
+sphinx/highlighting.py
+sphinx/jinja2glue.py
+sphinx/make_mode.py
+sphinx/pygments_styles.py
+sphinx/quickstart.py
+sphinx/roles.py
+sphinx/setup_command.py
+sphinx/theming.py
+sphinx/transforms.py
+sphinx/versioning.py
+sphinx/builders/__init__.py
+sphinx/builders/changes.py
+sphinx/builders/devhelp.py
+sphinx/builders/epub.py
+sphinx/builders/gettext.py
+sphinx/builders/html.py
+sphinx/builders/htmlhelp.py
+sphinx/builders/latex.py
+sphinx/builders/linkcheck.py
+sphinx/builders/manpage.py
+sphinx/builders/qthelp.py
+sphinx/builders/texinfo.py
+sphinx/builders/text.py
+sphinx/builders/websupport.py
+sphinx/builders/xml.py
+sphinx/directives/__init__.py
+sphinx/directives/code.py
+sphinx/directives/other.py
+sphinx/domains/__init__.py
+sphinx/domains/c.py
+sphinx/domains/cpp.py
+sphinx/domains/javascript.py
+sphinx/domains/python.py
+sphinx/domains/rst.py
+sphinx/domains/std.py
+sphinx/ext/__init__.py
+sphinx/ext/autodoc.py
+sphinx/ext/coverage.py
+sphinx/ext/doctest.py
+sphinx/ext/extlinks.py
+sphinx/ext/graphviz.py
+sphinx/ext/ifconfig.py
+sphinx/ext/inheritance_diagram.py
+sphinx/ext/intersphinx.py
+sphinx/ext/jsmath.py
+sphinx/ext/linkcode.py
+sphinx/ext/mathbase.py
+sphinx/ext/mathjax.py
+sphinx/ext/oldcmarkup.py
+sphinx/ext/pngmath.py
+sphinx/ext/todo.py
+sphinx/ext/viewcode.py
+sphinx/ext/autosummary/__init__.py
+sphinx/ext/autosummary/generate.py
+sphinx/ext/autosummary/templates/autosummary/base.rst
+sphinx/ext/autosummary/templates/autosummary/class.rst
+sphinx/ext/autosummary/templates/autosummary/module.rst
+sphinx/locale/__init__.py
+sphinx/locale/sphinx.pot
+sphinx/locale/.tx/config
+sphinx/locale/bn/LC_MESSAGES/sphinx.js
+sphinx/locale/bn/LC_MESSAGES/sphinx.mo
+sphinx/locale/bn/LC_MESSAGES/sphinx.po
+sphinx/locale/ca/LC_MESSAGES/sphinx.js
+sphinx/locale/ca/LC_MESSAGES/sphinx.mo
+sphinx/locale/ca/LC_MESSAGES/sphinx.po
+sphinx/locale/cs/LC_MESSAGES/sphinx.js
+sphinx/locale/cs/LC_MESSAGES/sphinx.mo
+sphinx/locale/cs/LC_MESSAGES/sphinx.po
+sphinx/locale/da/LC_MESSAGES/sphinx.js
+sphinx/locale/da/LC_MESSAGES/sphinx.mo
+sphinx/locale/da/LC_MESSAGES/sphinx.po
+sphinx/locale/de/LC_MESSAGES/sphinx.js
+sphinx/locale/de/LC_MESSAGES/sphinx.mo
+sphinx/locale/de/LC_MESSAGES/sphinx.po
+sphinx/locale/es/LC_MESSAGES/sphinx.js
+sphinx/locale/es/LC_MESSAGES/sphinx.mo
+sphinx/locale/es/LC_MESSAGES/sphinx.po
+sphinx/locale/et/LC_MESSAGES/sphinx.js
+sphinx/locale/et/LC_MESSAGES/sphinx.mo
+sphinx/locale/et/LC_MESSAGES/sphinx.po
+sphinx/locale/eu/LC_MESSAGES/sphinx.js
+sphinx/locale/eu/LC_MESSAGES/sphinx.mo
+sphinx/locale/eu/LC_MESSAGES/sphinx.po
+sphinx/locale/fa/LC_MESSAGES/sphinx.js
+sphinx/locale/fa/LC_MESSAGES/sphinx.mo
+sphinx/locale/fa/LC_MESSAGES/sphinx.po
+sphinx/locale/fi/LC_MESSAGES/sphinx.js
+sphinx/locale/fi/LC_MESSAGES/sphinx.mo
+sphinx/locale/fi/LC_MESSAGES/sphinx.po
+sphinx/locale/fr/LC_MESSAGES/sphinx.js
+sphinx/locale/fr/LC_MESSAGES/sphinx.mo
+sphinx/locale/fr/LC_MESSAGES/sphinx.po
+sphinx/locale/he/LC_MESSAGES/sphinx.js
+sphinx/locale/he/LC_MESSAGES/sphinx.mo
+sphinx/locale/he/LC_MESSAGES/sphinx.po
+sphinx/locale/hr/LC_MESSAGES/sphinx.js
+sphinx/locale/hr/LC_MESSAGES/sphinx.mo
+sphinx/locale/hr/LC_MESSAGES/sphinx.po
+sphinx/locale/hu/LC_MESSAGES/sphinx.js
+sphinx/locale/hu/LC_MESSAGES/sphinx.mo
+sphinx/locale/hu/LC_MESSAGES/sphinx.po
+sphinx/locale/id/LC_MESSAGES/sphinx.js
+sphinx/locale/id/LC_MESSAGES/sphinx.mo
+sphinx/locale/id/LC_MESSAGES/sphinx.po
+sphinx/locale/it/LC_MESSAGES/sphinx.js
+sphinx/locale/it/LC_MESSAGES/sphinx.mo
+sphinx/locale/it/LC_MESSAGES/sphinx.po
+sphinx/locale/ja/LC_MESSAGES/sphinx.js
+sphinx/locale/ja/LC_MESSAGES/sphinx.mo
+sphinx/locale/ja/LC_MESSAGES/sphinx.po
+sphinx/locale/ko/LC_MESSAGES/sphinx.js
+sphinx/locale/ko/LC_MESSAGES/sphinx.mo
+sphinx/locale/ko/LC_MESSAGES/sphinx.po
+sphinx/locale/lt/LC_MESSAGES/sphinx.js
+sphinx/locale/lt/LC_MESSAGES/sphinx.mo
+sphinx/locale/lt/LC_MESSAGES/sphinx.po
+sphinx/locale/lv/LC_MESSAGES/sphinx.js
+sphinx/locale/lv/LC_MESSAGES/sphinx.mo
+sphinx/locale/lv/LC_MESSAGES/sphinx.po
+sphinx/locale/mk/LC_MESSAGES/sphinx.js
+sphinx/locale/mk/LC_MESSAGES/sphinx.mo
+sphinx/locale/mk/LC_MESSAGES/sphinx.po
+sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js
+sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo
+sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po
+sphinx/locale/ne/LC_MESSAGES/sphinx.js
+sphinx/locale/ne/LC_MESSAGES/sphinx.mo
+sphinx/locale/ne/LC_MESSAGES/sphinx.po
+sphinx/locale/nl/LC_MESSAGES/sphinx.js
+sphinx/locale/nl/LC_MESSAGES/sphinx.mo
+sphinx/locale/nl/LC_MESSAGES/sphinx.po
+sphinx/locale/pl/LC_MESSAGES/sphinx.js
+sphinx/locale/pl/LC_MESSAGES/sphinx.mo
+sphinx/locale/pl/LC_MESSAGES/sphinx.po
+sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js
+sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo
+sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po
+sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js
+sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo
+sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po
+sphinx/locale/ru/LC_MESSAGES/sphinx.js
+sphinx/locale/ru/LC_MESSAGES/sphinx.mo
+sphinx/locale/ru/LC_MESSAGES/sphinx.po
+sphinx/locale/si/LC_MESSAGES/sphinx.js
+sphinx/locale/si/LC_MESSAGES/sphinx.mo
+sphinx/locale/si/LC_MESSAGES/sphinx.po
+sphinx/locale/sk/LC_MESSAGES/sphinx.js
+sphinx/locale/sk/LC_MESSAGES/sphinx.mo
+sphinx/locale/sk/LC_MESSAGES/sphinx.po
+sphinx/locale/sl/LC_MESSAGES/sphinx.js
+sphinx/locale/sl/LC_MESSAGES/sphinx.mo
+sphinx/locale/sl/LC_MESSAGES/sphinx.po
+sphinx/locale/sv/LC_MESSAGES/sphinx.js
+sphinx/locale/sv/LC_MESSAGES/sphinx.mo
+sphinx/locale/sv/LC_MESSAGES/sphinx.po
+sphinx/locale/tr/LC_MESSAGES/sphinx.js
+sphinx/locale/tr/LC_MESSAGES/sphinx.mo
+sphinx/locale/tr/LC_MESSAGES/sphinx.po
+sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js
+sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo
+sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po
+sphinx/locale/vi/LC_MESSAGES/sphinx.js
+sphinx/locale/vi/LC_MESSAGES/sphinx.mo
+sphinx/locale/vi/LC_MESSAGES/sphinx.po
+sphinx/locale/zh_CN/LC_MESSAGES/sphinx.js
+sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo
+sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po
+sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js
+sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo
+sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po
+sphinx/pycode/Grammar-py2.txt
+sphinx/pycode/Grammar-py3.txt
+sphinx/pycode/__init__.py
+sphinx/pycode/nodes.py
+sphinx/pycode/pgen2/__init__.py
+sphinx/pycode/pgen2/driver.py
+sphinx/pycode/pgen2/grammar.py
+sphinx/pycode/pgen2/literals.py
+sphinx/pycode/pgen2/parse.py
+sphinx/pycode/pgen2/pgen.py
+sphinx/pycode/pgen2/token.py
+sphinx/pycode/pgen2/tokenize.py
+sphinx/search/__init__.py
+sphinx/search/en.py
+sphinx/search/ja.py
+sphinx/texinputs/Makefile
+sphinx/texinputs/fncychap.sty
+sphinx/texinputs/python.ist
+sphinx/texinputs/sphinx.sty
+sphinx/texinputs/sphinxhowto.cls
+sphinx/texinputs/sphinxmanual.cls
+sphinx/texinputs/tabulary.sty
+sphinx/themes/agogo/layout.html
+sphinx/themes/agogo/theme.conf
+sphinx/themes/agogo/static/agogo.css_t
+sphinx/themes/agogo/static/bgfooter.png
+sphinx/themes/agogo/static/bgtop.png
+sphinx/themes/basic/defindex.html
+sphinx/themes/basic/domainindex.html
+sphinx/themes/basic/genindex-single.html
+sphinx/themes/basic/genindex-split.html
+sphinx/themes/basic/genindex.html
+sphinx/themes/basic/globaltoc.html
+sphinx/themes/basic/layout.html
+sphinx/themes/basic/localtoc.html
+sphinx/themes/basic/opensearch.xml
+sphinx/themes/basic/page.html
+sphinx/themes/basic/relations.html
+sphinx/themes/basic/search.html
+sphinx/themes/basic/searchbox.html
+sphinx/themes/basic/searchresults.html
+sphinx/themes/basic/sourcelink.html
+sphinx/themes/basic/theme.conf
+sphinx/themes/basic/changes/frameset.html
+sphinx/themes/basic/changes/rstsource.html
+sphinx/themes/basic/changes/versionchanges.html
+sphinx/themes/basic/static/ajax-loader.gif
+sphinx/themes/basic/static/basic.css_t
+sphinx/themes/basic/static/comment-bright.png
+sphinx/themes/basic/static/comment-close.png
+sphinx/themes/basic/static/comment.png
+sphinx/themes/basic/static/doctools.js
+sphinx/themes/basic/static/down-pressed.png
+sphinx/themes/basic/static/down.png
+sphinx/themes/basic/static/file.png
+sphinx/themes/basic/static/jquery.js
+sphinx/themes/basic/static/minus.png
+sphinx/themes/basic/static/plus.png
+sphinx/themes/basic/static/searchtools.js_t
+sphinx/themes/basic/static/underscore.js
+sphinx/themes/basic/static/up-pressed.png
+sphinx/themes/basic/static/up.png
+sphinx/themes/basic/static/websupport.js
+sphinx/themes/default/layout.html
+sphinx/themes/default/theme.conf
+sphinx/themes/default/static/default.css_t
+sphinx/themes/default/static/sidebar.js_t
+sphinx/themes/epub/epub-cover.html
+sphinx/themes/epub/layout.html
+sphinx/themes/epub/theme.conf
+sphinx/themes/epub/static/epub.css
+sphinx/themes/haiku/layout.html
+sphinx/themes/haiku/theme.conf
+sphinx/themes/haiku/static/alert_info_32.png
+sphinx/themes/haiku/static/alert_warning_32.png
+sphinx/themes/haiku/static/bg-page.png
+sphinx/themes/haiku/static/bullet_orange.png
+sphinx/themes/haiku/static/haiku.css_t
+sphinx/themes/nature/theme.conf
+sphinx/themes/nature/static/nature.css_t
+sphinx/themes/pyramid/layout.html
+sphinx/themes/pyramid/theme.conf
+sphinx/themes/pyramid/static/dialog-note.png
+sphinx/themes/pyramid/static/dialog-seealso.png
+sphinx/themes/pyramid/static/dialog-todo.png
+sphinx/themes/pyramid/static/dialog-topic.png
+sphinx/themes/pyramid/static/dialog-warning.png
+sphinx/themes/pyramid/static/epub.css
+sphinx/themes/pyramid/static/footerbg.png
+sphinx/themes/pyramid/static/headerbg.png
+sphinx/themes/pyramid/static/ie6.css
+sphinx/themes/pyramid/static/middlebg.png
+sphinx/themes/pyramid/static/pyramid.css_t
+sphinx/themes/pyramid/static/transparent.gif
+sphinx/themes/scrolls/layout.html
+sphinx/themes/scrolls/theme.conf
+sphinx/themes/scrolls/artwork/logo.svg
+sphinx/themes/scrolls/static/darkmetal.png
+sphinx/themes/scrolls/static/headerbg.png
+sphinx/themes/scrolls/static/logo.png
+sphinx/themes/scrolls/static/metal.png
+sphinx/themes/scrolls/static/navigation.png
+sphinx/themes/scrolls/static/print.css
+sphinx/themes/scrolls/static/scrolls.css_t
+sphinx/themes/scrolls/static/theme_extras.js
+sphinx/themes/scrolls/static/watermark.png
+sphinx/themes/scrolls/static/watermark_blur.png
+sphinx/themes/sphinxdoc/layout.html
+sphinx/themes/sphinxdoc/theme.conf
+sphinx/themes/sphinxdoc/static/contents.png
+sphinx/themes/sphinxdoc/static/navigation.png
+sphinx/themes/sphinxdoc/static/sphinxdoc.css_t
+sphinx/themes/traditional/theme.conf
+sphinx/themes/traditional/static/traditional.css_t
+sphinx/util/__init__.py
+sphinx/util/compat.py
+sphinx/util/console.py
+sphinx/util/docfields.py
+sphinx/util/docstrings.py
+sphinx/util/inspect.py
+sphinx/util/jsdump.py
+sphinx/util/jsonimpl.py
+sphinx/util/matching.py
+sphinx/util/nodes.py
+sphinx/util/osutil.py
+sphinx/util/png.py
+sphinx/util/pycompat.py
+sphinx/util/smartypants.py
+sphinx/util/stemmer.py
+sphinx/util/tags.py
+sphinx/util/texescape.py
+sphinx/util/websupport.py
+sphinx/websupport/__init__.py
+sphinx/websupport/errors.py
+sphinx/websupport/search/__init__.py
+sphinx/websupport/search/nullsearch.py
+sphinx/websupport/search/whooshsearch.py
+sphinx/websupport/search/xapiansearch.py
+sphinx/websupport/storage/__init__.py
+sphinx/websupport/storage/differ.py
+sphinx/websupport/storage/sqlalchemy_db.py
+sphinx/websupport/storage/sqlalchemystorage.py
+sphinx/writers/__init__.py
+sphinx/writers/html.py
+sphinx/writers/latex.py
+sphinx/writers/manpage.py
+sphinx/writers/texinfo.py
+sphinx/writers/text.py
+sphinx/writers/websupport.py
+sphinx/writers/xml.py
+tests/coverage.py
+tests/path.py
+tests/run.py
+tests/test_application.py
+tests/test_autodoc.py
+tests/test_autosummary.py
+tests/test_build.py
+tests/test_build_gettext.py
+tests/test_build_html.py
+tests/test_build_latex.py
+tests/test_build_texinfo.py
+tests/test_build_text.py
+tests/test_config.py
+tests/test_coverage.py
+tests/test_cpp_domain.py
+tests/test_doctest.py
+tests/test_docutilsconf.py
+tests/test_env.py
+tests/test_footnote.py
+tests/test_highlighting.py
+tests/test_i18n.py
+tests/test_intersphinx.py
+tests/test_intl.py
+tests/test_linkcode.py
+tests/test_markup.py
+tests/test_metadata.py
+tests/test_only_directive.py
+tests/test_py_domain.py
+tests/test_quickstart.py
+tests/test_rst_domain.py
+tests/test_search.py
+tests/test_searchadapters.py
+tests/test_setup_command.py
+tests/test_templating.py
+tests/test_theming.py
+tests/test_util_nodes.py
+tests/test_versioning.py
+tests/test_websupport.py
+tests/util.py
+tests/etree13/ElementPath.py
+tests/etree13/ElementTree.py
+tests/etree13/HTMLTreeBuilder.py
+tests/etree13/__init__.py
+tests/root/Makefile
+tests/root/autodoc.txt
+tests/root/autodoc_fodder.py
+tests/root/autosummary.txt
+tests/root/bom.po
+tests/root/bom.txt
+tests/root/conf.py
+tests/root/contents.txt
+tests/root/doctest.txt
+tests/root/ext.py
+tests/root/extapi.txt
+tests/root/extensions.txt
+tests/root/footnote.txt
+tests/root/images.txt
+tests/root/img.gif
+tests/root/img.pdf
+tests/root/img.png
+tests/root/includes.txt
+tests/root/lists.txt
+tests/root/literal.inc
+tests/root/markup.txt
+tests/root/math.txt
+tests/root/metadata.txt
+tests/root/objects.txt
+tests/root/quotes.inc
+tests/root/rimg.png
+tests/root/robots.txt
+tests/root/subdir.po
+tests/root/svgimg.pdf
+tests/root/svgimg.svg
+tests/root/tabs.inc
+tests/root/templated.css_t
+tests/root/test.inc
+tests/root/wrongenc.inc
+tests/root/ziptheme.zip
+tests/root/_static/README
+tests/root/_static/excluded.css
+tests/root/_static/subdir/foo.css
+tests/root/_templates/contentssb.html
+tests/root/_templates/customsb.html
+tests/root/_templates/layout.html
+tests/root/special/api.h
+tests/root/special/code.py
+tests/root/subdir/excluded.txt
+tests/root/subdir/images.txt
+tests/root/subdir/img.png
+tests/root/subdir/include.inc
+tests/root/subdir/includes.txt
+tests/root/subdir/simg.png
+tests/root/testtheme/layout.html
+tests/root/testtheme/theme.conf
+tests/root/testtheme/static/staticimg.png
+tests/root/testtheme/static/statictmpl.html_t
+tests/root/versioning/added.txt
+tests/root/versioning/deleted.txt
+tests/root/versioning/deleted_end.txt
+tests/root/versioning/index.txt
+tests/root/versioning/insert.txt
+tests/root/versioning/insert_beginning.txt
+tests/root/versioning/insert_similar.txt
+tests/root/versioning/modified.txt
+tests/root/versioning/original.txt
+tests/roots/test-autosummary/conf.py
+tests/roots/test-autosummary/contents.rst
+tests/roots/test-autosummary/dummy_module.py
+tests/roots/test-docutilsconf/conf.py
+tests/roots/test-docutilsconf/contents.txt
+tests/roots/test-docutilsconf/docutils.conf
+tests/roots/test-intl/admonitions.po
+tests/roots/test-intl/admonitions.txt
+tests/roots/test-intl/bom.po
+tests/roots/test-intl/bom.txt
+tests/roots/test-intl/conf.py
+tests/roots/test-intl/contents.txt
+tests/roots/test-intl/definition_terms.po
+tests/roots/test-intl/definition_terms.txt
+tests/roots/test-intl/docfields.po
+tests/roots/test-intl/docfields.txt
+tests/roots/test-intl/external_links.po
+tests/roots/test-intl/external_links.txt
+tests/roots/test-intl/figure_caption.po
+tests/roots/test-intl/figure_caption.txt
+tests/roots/test-intl/footnote.po
+tests/roots/test-intl/footnote.txt
+tests/roots/test-intl/glossary_terms.po
+tests/roots/test-intl/glossary_terms.txt
+tests/roots/test-intl/glossary_terms_inconsistency.po
+tests/roots/test-intl/glossary_terms_inconsistency.txt
+tests/roots/test-intl/i18n.png
+tests/roots/test-intl/index_entries.po
+tests/roots/test-intl/index_entries.txt
+tests/roots/test-intl/label_target.po
+tests/roots/test-intl/label_target.txt
+tests/roots/test-intl/literalblock.po
+tests/roots/test-intl/literalblock.txt
+tests/roots/test-intl/refs_inconsistency.po
+tests/roots/test-intl/refs_inconsistency.txt
+tests/roots/test-intl/refs_python_domain.po
+tests/roots/test-intl/refs_python_domain.txt
+tests/roots/test-intl/role_xref.po
+tests/roots/test-intl/role_xref.txt
+tests/roots/test-intl/rubric.po
+tests/roots/test-intl/rubric.txt
+tests/roots/test-intl/seealso.po
+tests/roots/test-intl/seealso.txt
+tests/roots/test-intl/sphinx.po
+tests/roots/test-intl/versionchange.po
+tests/roots/test-intl/versionchange.txt
+tests/roots/test-intl/warnings.po
+tests/roots/test-intl/warnings.txt
+tests/roots/test-intl/_templates/index.html
+tests/roots/test-intl/subdir/contents.txt
+tests/roots/test-only-directive/conf.py
+tests/roots/test-only-directive/contents.rst
+tests/roots/test-only-directive/only.rst
+tests/roots/test-setup/setup.cfg
+tests/roots/test-setup/setup.py
+tests/roots/test-setup/doc/conf.py
+tests/roots/test-setup/doc/contents.txt
+tests/roots/test-templating/autosummary_templating.txt
+tests/roots/test-templating/conf.py
+tests/roots/test-templating/contents.txt
+tests/roots/test-templating/_templates/layout.html
+tests/roots/test-templating/_templates/autosummary/class.rst
+utils/check_sources.py
+utils/convert.py
+utils/pylintrc
+utils/reindent.py
+utils/release-checklist
\ No newline at end of file
diff --git a/Sphinx.egg-info/dependency_links.txt b/Sphinx.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Sphinx.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/Sphinx.egg-info/entry_points.txt b/Sphinx.egg-info/entry_points.txt
new file mode 100644
index 0000000..28f61f9
--- /dev/null
+++ b/Sphinx.egg-info/entry_points.txt
@@ -0,0 +1,9 @@
+[console_scripts]
+sphinx-apidoc = sphinx.apidoc:main
+sphinx-autogen = sphinx.ext.autosummary.generate:main
+sphinx-build = sphinx:main
+sphinx-quickstart = sphinx.quickstart:main
+
+[distutils.commands]
+build_sphinx = sphinx.setup_command:BuildDoc
+
diff --git a/Sphinx.egg-info/not-zip-safe b/Sphinx.egg-info/not-zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Sphinx.egg-info/not-zip-safe
@@ -0,0 +1 @@
+
diff --git a/Sphinx.egg-info/requires.txt b/Sphinx.egg-info/requires.txt
new file mode 100644
index 0000000..04ebdd5
--- /dev/null
+++ b/Sphinx.egg-info/requires.txt
@@ -0,0 +1,3 @@
+Pygments>=1.2
+docutils>=0.7
+Jinja2>=2.3
diff --git a/Sphinx.egg-info/top_level.txt b/Sphinx.egg-info/top_level.txt
new file mode 100644
index 0000000..6966869
--- /dev/null
+++ b/Sphinx.egg-info/top_level.txt
@@ -0,0 +1 @@
+sphinx
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..c22f12e
--- /dev/null
+++ b/TODO
@@ -0,0 +1,5 @@
+Sphinx TODO
+===========
+
+All todo items are now tracked as issues in the Sphinx issue tracker at
+<http://www.bitbucket.org/birkenfeld/sphinx/issues/>.
diff --git a/babel.cfg b/babel.cfg
new file mode 100644
index 0000000..4c1e718
--- /dev/null
+++ b/babel.cfg
@@ -0,0 +1,21 @@
+# How setup this file
+# http://babel.edgewall.org/wiki/Documentation/setup.html
+# this file description:
+# http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration
+
+# Extraction from Python source files
+[python: **.py]
+encoding = utf-8
+
+# Extraction from Jinja2 HTML templates
+[jinja2: **/themes/**.html]
+encoding = utf-8
+ignore_tags = script,style
+include_attrs = alt title summary
+
+# Extraction from Jinja2 XML templates
+[jinja2: **/themes/**.xml]
+
+# Extraction from JavaScript files
+[javascript: **.js]
+[javascript: **.js_t]
diff --git a/custom_fixers/__init__.py b/custom_fixers/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/custom_fixers/fix_alt_unicode.py b/custom_fixers/fix_alt_unicode.py
new file mode 100644
index 0000000..55175e9
--- /dev/null
+++ b/custom_fixers/fix_alt_unicode.py
@@ -0,0 +1,12 @@
+from lib2to3.fixer_base import BaseFix
+from lib2to3.fixer_util import Name
+
+class FixAltUnicode(BaseFix):
+ PATTERN = """
+ func=funcdef< 'def' name='__unicode__'
+ parameters< '(' NAME ')' > any+ >
+ """
+
+ def transform(self, node, results):
+ name = results['name']
+ name.replace(Name('__str__', prefix=name.prefix))
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..5590964
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,18 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = python ../sphinx-build.py
+SPHINXPROJ = sphinx
+SOURCEDIR = .
+BUILDDIR = _build
+
+# Has to be explicit, otherwise we don't get "make" without targets right.
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%:
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/doc/_static/bookcover.png b/doc/_static/bookcover.png
new file mode 100644
index 0000000..1c91f91
Binary files /dev/null and b/doc/_static/bookcover.png differ
diff --git a/doc/_static/pocoo.png b/doc/_static/pocoo.png
new file mode 100644
index 0000000..eeb18ea
Binary files /dev/null and b/doc/_static/pocoo.png differ
diff --git a/doc/_static/sphinx.png b/doc/_static/sphinx.png
new file mode 100644
index 0000000..a4a3e1a
Binary files /dev/null and b/doc/_static/sphinx.png differ
diff --git a/doc/_templates/index.html b/doc/_templates/index.html
new file mode 100644
index 0000000..e6ef917
--- /dev/null
+++ b/doc/_templates/index.html
@@ -0,0 +1,100 @@
+{% extends "layout.html" %}
+{% set title = _('Overview') %}
+{% block body %}
+ <h1>{{ _('Welcome') }}</h1>
+
+ <div class="quotebar">
+ <p><em>{%trans%}What users say:{%endtrans%}</em></p>
+ <p>{%trans%}“Cheers for a great tool that actually makes programmers <b>want</b>
+ to write documentation!”{%endtrans%}</p>
+ </div>
+
+ <p>{%trans%}
+ Sphinx is a tool that makes it easy to create intelligent and beautiful
+ documentation, written by Georg Brandl and licensed under the BSD license.{%endtrans%}</p>
+ <p>{%trans%}It was originally created for <a href="http://docs.python.org/">the
+ new Python documentation</a>, and it has excellent facilities for the
+ documentation of Python projects, but C/C++ is already supported as well,
+ and it is planned to add special support for other languages as well. Of
+ course, this site is also created from reStructuredText sources using
+ Sphinx! The following features should be highlighted:{%endtrans%}
+ </p>
+ <ul>
+ <li>{%trans%}<b>Output formats:</b> HTML (including Windows HTML Help), LaTeX (for
+ printable PDF versions), ePub, Texinfo, manual pages, plain text{%endtrans%}</li>
+ <li>{%trans%}<b>Extensive cross-references:</b> semantic markup and automatic links
+ for functions, classes, citations, glossary terms and similar pieces of
+ information{%endtrans%}</li>
+ <li>{%trans%}<b>Hierarchical structure:</b> easy definition of a document tree, with
+ automatic links to siblings, parents and children{%endtrans%}</li>
+ <li>{%trans%}<b>Automatic indices:</b> general index as well as a language-specific
+ module indices{%endtrans%}</li>
+ <li>{%trans%}<b>Code handling:</b> automatic highlighting using the <a
+ href="http://pygments.org">Pygments</a> highlighter{%endtrans%}</li>
+ <li>{%trans path=pathto('extensions')%}<b>Extensions:</b> automatic testing of code snippets, inclusion of
+ docstrings from Python modules (API docs), and
+ <a href="{{ path }}#builtin-sphinx-extensions">more</a>{%endtrans%}</li>
+ </ul>
+ <p>{%trans%}
+ Sphinx uses <a href="http://docutils.sf.net/rst.html">reStructuredText</a>
+ as its markup language, and many of its strengths come from the power and
+ straightforwardness of reStructuredText and its parsing and translating
+ suite, the <a href="http://docutils.sf.net/">Docutils</a>.{%endtrans%}
+ </p>
+
+ <h2 style="margin-bottom: 0">{%trans%}Documentation{%endtrans%}</h2>
+
+ <table class="contentstable" align="center" style="margin-left: 30px"><tr>
+ <td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("tutorial") }}">{%trans%}First steps with Sphinx{%endtrans%}</a><br/>
+ <span class="linkdescr">{%trans%}overview of basic tasks{%endtrans%}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">{%trans%}Contents{%endtrans%}</a><br/>
+ <span class="linkdescr">{%trans%}for a complete overview{%endtrans%}</span></p>
+ </td><td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">{%trans%}Search page{%endtrans%}</a><br/>
+ <span class="linkdescr">{%trans%}search the documentation{%endtrans%}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">{%trans%}General Index{%endtrans%}</a><br/>
+ <span class="linkdescr">{%trans%}all functions, classes, terms{%endtrans%}</span></p>
+ </td></tr>
+ </table>
+
+ <p>{%trans%}
+ You can also download PDF versions of the Sphinx documentation:
+ a <a href="http://sphinx-doc.org/sphinx.pdf">version</a> generated from
+ the LaTeX Sphinx produces, and
+ a <a href="http://sphinx-doc.org/sphinx-rst2pdf.pdf">version</a> generated
+ by rst2pdf.{%endtrans%}
+ </p>
+
+ <h2>{%trans%}Examples{%endtrans%}</h2>
+ <p>{%trans path=pathto("examples")%}Links to documentation generated with Sphinx can be found on the
+ <a href="{{ path }}">Projects using Sphinx</a> page.{%endtrans%}
+ </p>
+ <p>{%trans%}
+ For examples of how Sphinx source files look, use the “Show
+ source” links on all pages of the documentation apart from this
+ welcome page.{%endtrans%}
+ </p>
+
+ <p>{%trans%}You may also be interested in the very nice
+ <a href="http://matplotlib.sourceforge.net/sampledoc/">tutorial</a> on how to
+ create a customized documentation using Sphinx written by the matplotlib
+ developers.{%endtrans%}</p>
+
+ <p>{%trans%}There is a <a href="http://docs.sphinx-users.jp/">Japanese translation</a>
+ of this documentation, thanks to the Japanese Sphinx user group.{%endtrans%}</p>
+ <p>{%trans%}A Japanese book about Sphinx has been published by O'Reilly:
+ <a href="http://www.oreilly.co.jp/books/9784873116488/">Sphinxをはじめよう /
+ Learning Sphinx</a>.{%endtrans%}</p>
+ <!-- <p><img src="{{ pathto("_static/bookcover.png", 1) }}"/></p> -->
+
+
+ <h2>{%trans%}Hosting{%endtrans%}</h2>
+
+ <p>{%trans%}Need a place to host your Sphinx docs?
+ <a href="http://readthedocs.org">readthedocs.org</a> hosts a lot of Sphinx docs
+ already, and integrates well with projects' source control. It also features a
+ powerful built-in search that exceeds the possibilities of Sphinx' JavaScript-based
+ offline search.{%endtrans%}</p>
+
+{% endblock %}
diff --git a/doc/_templates/indexsidebar.html b/doc/_templates/indexsidebar.html
new file mode 100644
index 0000000..4a350ae
--- /dev/null
+++ b/doc/_templates/indexsidebar.html
@@ -0,0 +1,33 @@
+<p class="logo">A <a href="http://pocoo.org/">
+ <img src="{{ pathto("_static/pocoo.png", 1) }}" alt="Pocoo" /></a>
+ {%trans%}project{%endtrans%}</p>
+
+<h3>Download</h3>
+{% if version.endswith('(hg)') %}
+<p>{%trans%}This documentation is for version <b>{{ version }}</b>, which is
+ not released yet.{%endtrans%}</p>
+<p>{%trans%}You can use it from the
+ <a href="http://bitbucket.org/birkenfeld/sphinx/">Mercurial repo</a> or look for
+ released versions in the <a href="http://pypi.python.org/pypi/Sphinx">Python
+ Package Index</a>.{%endtrans%}</p>
+{% else %}
+<p>{%trans%}Current version: <b>{{ version }}</b>{%endtrans%}</p>
+<p>{%trans%}Get Sphinx from the <a href="http://pypi.python.org/pypi/Sphinx">Python Package
+Index</a>, or install it with:{%endtrans%}</p>
+<pre>easy_install -U Sphinx</pre>
+<p>{%trans%}Latest <a href="http://sphinx-doc.org/latest/">development version docs</a>
+are also available.{%endtrans%}</p>
+{% endif %}
+
+<h3>{%trans%}Questions? Suggestions?{%endtrans%}</h3>
+
+<p>{%trans%}Join the <a href="http://groups.google.com/group/sphinx-users">Google group</a>:{%endtrans%}</p>
+<form action="http://groups.google.com/group/sphinx-users/boxsubscribe"
+ style="padding-left: 0.5em">
+ <input type="text" name="email" value="your at email" style="font-size: 90%; width: 120px"
+ onfocus="$(this).val('');"/>
+ <input type="submit" name="sub" value="Subscribe" style="font-size: 90%; width: 70px"/>
+</form>
+<p>{%trans%}or come to the <tt>#sphinx-doc</tt> channel on FreeNode.{%endtrans%}</p>
+<p>{%trans%}You can also open an issue at the
+ <a href="http://www.bitbucket.org/birkenfeld/sphinx/issues/">tracker</a>.{%endtrans%}</p>
diff --git a/doc/_themes/sphinx13/layout.html b/doc/_themes/sphinx13/layout.html
new file mode 100644
index 0000000..57378c1
--- /dev/null
+++ b/doc/_themes/sphinx13/layout.html
@@ -0,0 +1,78 @@
+{#
+ sphinxdoc/layout.html
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the sphinxdoc theme.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "basic/layout.html" %}
+
+{# put the sidebar before the body #}
+{% block sidebar1 %}{{ sidebar() }}{% endblock %}
+{% block sidebar2 %}{% endblock %}
+
+{% block extrahead %}
+ <link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,700'
+ rel='stylesheet' type='text/css' />
+{{ super() }}
+{%- if not embedded %}
+ <style type="text/css">
+ table.right { float: right; margin-left: 20px; }
+ table.right td { border: 1px solid #ccc; }
+ {% if pagename == 'index' %}
+ .related { display: none; }
+ {% endif %}
+ </style>
+ <script type="text/javascript">
+ // intelligent scrolling of the sidebar content
+ $(window).scroll(function() {
+ var sb = $('.sphinxsidebarwrapper');
+ var win = $(window);
+ var sbh = sb.height();
+ var offset = $('.sphinxsidebar').position()['top'];
+ var wintop = win.scrollTop();
+ var winbot = wintop + win.innerHeight();
+ var curtop = sb.position()['top'];
+ var curbot = curtop + sbh;
+ // does sidebar fit in window?
+ if (sbh < win.innerHeight()) {
+ // yes: easy case -- always keep at the top
+ sb.css('top', $u.min([$u.max([0, wintop - offset - 10]),
+ $(document).height() - sbh - 200]));
+ } else {
+ // no: only scroll if top/bottom edge of sidebar is at
+ // top/bottom edge of window
+ if (curtop > wintop && curbot > winbot) {
+ sb.css('top', $u.max([wintop - offset - 10, 0]));
+ } else if (curtop < wintop && curbot < winbot) {
+ sb.css('top', $u.min([winbot - sbh - offset - 20,
+ $(document).height() - sbh - 200]));
+ }
+ }
+ });
+ </script>
+{%- endif %}
+{% endblock %}
+
+{% block rootrellink %}
+ <li><a href="{{ pathto('index') }}">Sphinx home</a> |</li>
+ <li><a href="{{ pathto('contents') }}">Documentation</a> »</li>
+{% endblock %}
+
+{% block header %}
+<div class="pageheader">
+ <ul>
+ <li><a href="{{ pathto('index') }}">Home</a></li>
+ <li><a href="{{ pathto('install') }}">Get it</a></li>
+ <li><a href="{{ pathto('contents') }}">Docs</a></li>
+ <li><a href="{{ pathto('develop') }}">Extend/Develop</a></li>
+ </ul>
+ <div>
+ <a href="{{ pathto('index') }}">
+ <img src="{{ pathto('_static/sphinxheader.png', 1) }}" alt="SPHINX" />
+ </a>
+ </div>
+</div>
+{% endblock %}
diff --git a/doc/_themes/sphinx13/static/bodybg.png b/doc/_themes/sphinx13/static/bodybg.png
new file mode 100644
index 0000000..506b6f9
Binary files /dev/null and b/doc/_themes/sphinx13/static/bodybg.png differ
diff --git a/doc/_themes/sphinx13/static/footerbg.png b/doc/_themes/sphinx13/static/footerbg.png
new file mode 100644
index 0000000..d1922b4
Binary files /dev/null and b/doc/_themes/sphinx13/static/footerbg.png differ
diff --git a/doc/_themes/sphinx13/static/headerbg.png b/doc/_themes/sphinx13/static/headerbg.png
new file mode 100644
index 0000000..6d3e1d5
Binary files /dev/null and b/doc/_themes/sphinx13/static/headerbg.png differ
diff --git a/doc/_themes/sphinx13/static/listitem.png b/doc/_themes/sphinx13/static/listitem.png
new file mode 100644
index 0000000..e45715f
Binary files /dev/null and b/doc/_themes/sphinx13/static/listitem.png differ
diff --git a/doc/_themes/sphinx13/static/relbg.png b/doc/_themes/sphinx13/static/relbg.png
new file mode 100644
index 0000000..4722585
Binary files /dev/null and b/doc/_themes/sphinx13/static/relbg.png differ
diff --git a/doc/_themes/sphinx13/static/sphinx13.css b/doc/_themes/sphinx13/static/sphinx13.css
new file mode 100644
index 0000000..0b31c6b
--- /dev/null
+++ b/doc/_themes/sphinx13/static/sphinx13.css
@@ -0,0 +1,396 @@
+/*
+ * sphinx13.css
+ * ~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- sphinx13 theme.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+ at import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+ 'Verdana', sans-serif;
+ font-size: 14px;
+ text-align: center;
+ background-image: url(bodybg.png);
+ color: black;
+ padding: 0;
+ border-right: 1px solid #0a507a;
+ border-left: 1px solid #0a507a;
+
+ margin: 0 auto;
+ min-width: 780px;
+ max-width: 1080px;
+}
+
+.pageheader {
+ background-image: url(headerbg.png);
+ text-align: left;
+ padding: 10px 15px;
+}
+
+.pageheader ul {
+ float: right;
+ color: white;
+ list-style-type: none;
+ padding-left: 0;
+ margin-top: 30px;
+ margin-right: 10px;
+}
+
+.pageheader li {
+ float: left;
+ margin: 0 0 0 10px;
+}
+
+.pageheader li a {
+ border-radius: 1px;
+ padding: 8px 12px;
+ color: #f9f9f0;
+ text-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
+}
+
+.pageheader li a:hover {
+ background-color: #f9f9f0;
+ color: #0a507a;
+ text-shadow: none;
+}
+
+div.document {
+ background-color: white;
+ text-align: left;
+}
+
+div.bodywrapper {
+ margin: 0 240px 0 0;
+ border-right: 1px solid #0a507a;
+}
+
+div.body {
+ margin: 0;
+ padding: 0.5em 20px 20px 20px;
+}
+
+div.related {
+ font-size: 1em;
+ color: white;
+}
+
+div.related ul {
+ background-image: url(relbg.png);
+ height: 1.9em;
+ border-top: 1px solid #002e50;
+ border-bottom: 1px solid #002e50;
+}
+
+div.related ul li {
+ margin: 0 5px 0 0;
+ padding: 0;
+ float: left;
+}
+
+div.related ul li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+div.related ul li a {
+ margin: 0;
+ padding: 0 5px 0 5px;
+ line-height: 1.75em;
+ color: #f9f9f0;
+ text-shadow: 0px 0px 1px rgba(0, 0, 0, 0.5);
+}
+
+div.related ul li a:hover {
+ color: white;
+ /*text-decoration: underline;*/
+ text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.5);
+}
+
+div.sphinxsidebarwrapper {
+ position: relative;
+ top: 0px;
+ padding: 0;
+}
+
+div.sphinxsidebar {
+ margin: 0;
+ padding: 0 15px 15px 0;
+ width: 210px;
+ float: right;
+ font-size: 1em;
+ text-align: left;
+}
+
+div.sphinxsidebar .logo {
+ font-size: 1.8em;
+ color: #0A507A;
+ font-weight: 300;
+ text-align: center;
+}
+
+div.sphinxsidebar .logo img {
+ vertical-align: middle;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #aaa;
+ font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+ 'Verdana', sans-serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar h3 {
+ font-size: 1.5em;
+ border-top: 1px solid #0a507a;
+ margin-top: 1em;
+ margin-bottom: 0.5em;
+ padding-top: 0.5em;
+}
+
+div.sphinxsidebar h4 {
+ font-size: 1.2em;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar h3, div.sphinxsidebar h4 {
+ margin-right: -15px;
+ margin-left: -15px;
+ padding-right: 14px;
+ padding-left: 14px;
+ color: #333;
+ font-weight: 300;
+ /*text-shadow: 0px 0px 0.5px rgba(0, 0, 0, 0.4);*/
+}
+
+div.sphinxsidebarwrapper > h3:first-child {
+ margin-top: 0.5em;
+ border: none;
+}
+
+div.sphinxsidebar h3 a {
+ color: #333;
+}
+
+div.sphinxsidebar ul {
+ color: #444;
+ margin-top: 7px;
+ padding: 0;
+ line-height: 130%;
+}
+
+div.sphinxsidebar ul ul {
+ margin-left: 20px;
+ list-style-image: url(listitem.png);
+}
+
+div.footer {
+ background-image: url(footerbg.png);
+ color: #ccc;
+ text-shadow: 0 0 .2px rgba(255, 255, 255, 0.8);
+ padding: 3px 8px 3px 0;
+ clear: both;
+ font-size: 0.8em;
+ text-align: right;
+}
+
+/* no need to make a visible link to Sphinx on the Sphinx page */
+div.footer a {
+ color: #ccc;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+p {
+ margin: 0.8em 0 0.5em 0;
+}
+
+a {
+ color: #A2881D;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #E1C13F;
+}
+
+div.body a {
+ text-decoration: underline;
+}
+
+h1 {
+ margin: 10px 0 0 0;
+ font-size: 2.4em;
+ color: #0A507A;
+ font-weight: 300;
+}
+
+h2 {
+ margin: 1.em 0 0.2em 0;
+ font-size: 1.5em;
+ font-weight: 300;
+ padding: 0;
+ color: #174967;
+}
+
+h3 {
+ margin: 1em 0 -0.3em 0;
+ font-size: 1.3em;
+ font-weight: 300;
+}
+
+div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
+ text-decoration: none;
+}
+
+div.body h1 a tt, div.body h2 a tt, div.body h3 a tt, div.body h4 a tt, div.body h5 a tt, div.body h6 a tt {
+ color: #0A507A !important;
+ font-size: inherit !important;
+}
+
+a.headerlink {
+ color: #0A507A !important;
+ font-size: 12px;
+ margin-left: 6px;
+ padding: 0 4px 0 4px;
+ text-decoration: none !important;
+ float: right;
+}
+
+a.headerlink:hover {
+ background-color: #ccc;
+ color: white!important;
+}
+
+cite, code, tt {
+ font-family: 'Consolas', 'DejaVu Sans Mono',
+ 'Bitstream Vera Sans Mono', monospace;
+ font-size: 14px;
+ letter-spacing: -0.02em;
+}
+
+tt {
+ background-color: #f2f2f2;
+ border: 1px solid #ddd;
+ border-radius: 2px;
+ color: #333;
+ padding: 1px;
+}
+
+tt.descname, tt.descclassname, tt.xref {
+ border: 0;
+}
+
+hr {
+ border: 1px solid #abc;
+ margin: 2em;
+}
+
+a tt {
+ border: 0;
+ color: #a2881d;
+}
+
+a tt:hover {
+ color: #e1c13f;
+}
+
+pre {
+ font-family: 'Consolas', 'DejaVu Sans Mono',
+ 'Bitstream Vera Sans Mono', monospace;
+ font-size: 13px;
+ letter-spacing: 0.015em;
+ line-height: 120%;
+ padding: 0.5em;
+ border: 1px solid #ccc;
+ border-radius: 2px;
+ background-color: #f8f8f8;
+}
+
+pre a {
+ color: inherit;
+ text-decoration: underline;
+}
+
+td.linenos pre {
+ padding: 0.5em 0;
+}
+
+div.quotebar {
+ background-color: #f8f8f8;
+ max-width: 250px;
+ float: right;
+ padding: 0px 7px;
+ border: 1px solid #ccc;
+ margin-left: 1em;
+}
+
+div.topic {
+ background-color: #f8f8f8;
+}
+
+table {
+ border-collapse: collapse;
+ margin: 0 -0.5em 0 -0.5em;
+}
+
+table td, table th {
+ padding: 0.2em 0.5em 0.2em 0.5em;
+}
+
+div.admonition, div.warning {
+ font-size: 0.9em;
+ margin: 1em 0 1em 0;
+ border: 1px solid #86989B;
+ border-radius: 2px;
+ background-color: #f7f7f7;
+ padding: 0;
+}
+
+div.admonition p, div.warning p {
+ margin: 0.5em 1em 0.5em 1em;
+ padding: 0;
+}
+
+div.admonition pre, div.warning pre {
+ margin: 0.4em 1em 0.4em 1em;
+}
+
+div.admonition p.admonition-title,
+div.warning p.admonition-title {
+ margin-top: 1em;
+ padding-top: 0.5em;
+ font-weight: bold;
+}
+
+div.warning {
+ border: 1px solid #940000;
+/* background-color: #FFCCCF;*/
+}
+
+div.warning p.admonition-title {
+}
+
+div.admonition ul, div.admonition ol,
+div.warning ul, div.warning ol {
+ margin: 0.1em 0.5em 0.5em 3em;
+ padding: 0;
+}
+
+.viewcode-back {
+ font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+ 'Verdana', sans-serif;
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+}
diff --git a/doc/_themes/sphinx13/static/sphinxheader.png b/doc/_themes/sphinx13/static/sphinxheader.png
new file mode 100644
index 0000000..2b33f09
Binary files /dev/null and b/doc/_themes/sphinx13/static/sphinxheader.png differ
diff --git a/doc/_themes/sphinx13/theme.conf b/doc/_themes/sphinx13/theme.conf
new file mode 100644
index 0000000..876b198
--- /dev/null
+++ b/doc/_themes/sphinx13/theme.conf
@@ -0,0 +1,4 @@
+[theme]
+inherit = basic
+stylesheet = sphinx13.css
+pygments_style = trac
diff --git a/doc/builders.rst b/doc/builders.rst
new file mode 100644
index 0000000..333750e
--- /dev/null
+++ b/doc/builders.rst
@@ -0,0 +1,419 @@
+.. _builders:
+
+Available builders
+==================
+
+.. module:: sphinx.builders
+ :synopsis: Available built-in builder classes.
+
+These are the built-in Sphinx builders. More builders can be added by
+:ref:`extensions <extensions>`.
+
+The builder's "name" must be given to the **-b** command-line option of
+:program:`sphinx-build` to select a builder.
+
+
+.. module:: sphinx.builders.html
+.. class:: StandaloneHTMLBuilder
+
+ This is the standard HTML builder. Its output is a directory with HTML
+ files, complete with style sheets and optionally the reST sources. There are
+ quite a few configuration values that customize the output of this builder,
+ see the chapter :ref:`html-options` for details.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+.. class:: DirectoryHTMLBuilder
+
+ This is a subclass of the standard HTML builder. Its output is a directory
+ with HTML files, where each file is called ``index.html`` and placed in a
+ subdirectory named like its page name. For example, the document
+ ``markup/rest.rst`` will not result in an output file ``markup/rest.html``,
+ but ``markup/rest/index.html``. When generating links between pages, the
+ ``index.html`` is omitted, so that the URL would look like ``markup/rest/``.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ .. versionadded:: 0.6
+
+.. class:: SingleFileHTMLBuilder
+
+ This is an HTML builder that combines the whole project in one output file.
+ (Obviously this only works with smaller projects.) The file is named like
+ the master document. No indices will be generated.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ .. versionadded:: 1.0
+
+.. module:: sphinx.builders.htmlhelp
+.. class:: HTMLHelpBuilder
+
+ This builder produces the same output as the standalone HTML builder, but
+ also generates HTML Help support files that allow the Microsoft HTML Help
+ Workshop to compile them into a CHM file.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+.. module:: sphinx.builders.qthelp
+.. class:: QtHelpBuilder
+
+ This builder produces the same output as the standalone HTML builder, but
+ also generates `Qt help`_ collection support files that allow
+ the Qt collection generator to compile them.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ .. _Qt help: http://qt-project.org/doc/qt-4.8/qthelp-framework.html
+
+.. module:: sphinx.builders.devhelp
+.. class:: DevhelpBuilder
+
+ This builder produces the same output as the standalone HTML builder, but
+ also generates `GNOME Devhelp <https://wiki.gnome.org/Apps/Devhelp>`__
+ support file that allows the GNOME Devhelp reader to view them.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+.. module:: sphinx.builders.epub
+.. class:: EpubBuilder
+
+ This builder produces the same output as the standalone HTML builder, but
+ also generates an *epub* file for ebook readers. See :ref:`epub-faq` for
+ details about it. For definition of the epub format, have a look at
+ `<http://idpf.org/epub>`_ or `<http://en.wikipedia.org/wiki/EPUB>`_.
+ The builder creates *EPUB 2* files.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+.. module:: sphinx.builders.latex
+.. class:: LaTeXBuilder
+
+ This builder produces a bunch of LaTeX files in the output directory. You
+ have to specify which documents are to be included in which LaTeX files via
+ the :confval:`latex_documents` configuration value. There are a few
+ configuration values that customize the output of this builder, see the
+ chapter :ref:`latex-options` for details.
+
+ .. note::
+
+ The produced LaTeX file uses several LaTeX packages that may not be
+ present in a "minimal" TeX distribution installation. For TeXLive,
+ the following packages need to be installed:
+
+ * latex-recommended
+ * latex-extra
+ * fonts-recommended
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+Note that a direct PDF builder using ReportLab is available in `rst2pdf
+<http://rst2pdf.googlecode.com>`_ version 0.12 or greater. You need to add
+``'rst2pdf.pdfbuilder'`` to your :confval:`extensions` to enable it, its name is
+``pdf``. Refer to the `rst2pdf manual <http://ralsina.me/static/manual.pdf>`_
+for details.
+
+.. module:: sphinx.builders.text
+.. class:: TextBuilder
+
+ This builder produces a text file for each reST file -- this is almost the
+ same as the reST source, but with much of the markup stripped for better
+ readability.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ .. versionadded:: 0.4
+
+.. module:: sphinx.builders.manpage
+.. class:: ManualPageBuilder
+
+ This builder produces manual pages in the groff format. You have to specify
+ which documents are to be included in which manual pages via the
+ :confval:`man_pages` configuration value.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ .. note::
+
+ This builder requires the docutils manual page writer, which is only
+ available as of docutils 0.6.
+
+ .. versionadded:: 1.0
+
+
+.. module:: sphinx.builders.texinfo
+.. class:: TexinfoBuilder
+
+ This builder produces Texinfo files that can be processed into Info files by
+ the :program:`makeinfo` program. You have to specify which documents are to
+ be included in which Texinfo files via the :confval:`texinfo_documents`
+ configuration value.
+
+ The Info format is the basis of the on-line help system used by GNU Emacs and
+ the terminal-based program :program:`info`. See :ref:`texinfo-faq` for more
+ details. The Texinfo format is the official documentation system used by the
+ GNU project. More information on Texinfo can be found at
+ `<http://www.gnu.org/software/texinfo/>`_.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ .. versionadded:: 1.1
+
+
+.. currentmodule:: sphinx.builders.html
+.. class:: SerializingHTMLBuilder
+
+ This builder uses a module that implements the Python serialization API
+ (`pickle`, `simplejson`, `phpserialize`, and others) to dump the generated
+ HTML documentation. The pickle builder is a subclass of it.
+
+ A concrete subclass of this builder serializing to the `PHP serialization`_
+ format could look like this::
+
+ import phpserialize
+
+ class PHPSerializedBuilder(SerializingHTMLBuilder):
+ name = 'phpserialized'
+ implementation = phpserialize
+ out_suffix = '.file.phpdump'
+ globalcontext_filename = 'globalcontext.phpdump'
+ searchindex_filename = 'searchindex.phpdump'
+
+ .. _PHP serialization: https://pypi.python.org/pypi/phpserialize
+
+ .. attribute:: implementation
+
+ A module that implements `dump()`, `load()`, `dumps()` and `loads()`
+ functions that conform to the functions with the same names from the
+ pickle module. Known modules implementing this interface are
+ `simplejson` (or `json` in Python 2.6), `phpserialize`, `plistlib`,
+ and others.
+
+ .. attribute:: out_suffix
+
+ The suffix for all regular files.
+
+ .. attribute:: globalcontext_filename
+
+ The filename for the file that contains the "global context". This
+ is a dict with some general configuration values such as the name
+ of the project.
+
+ .. attribute:: searchindex_filename
+
+ The filename for the search index Sphinx generates.
+
+
+ See :ref:`serialization-details` for details about the output format.
+
+ .. versionadded:: 0.5
+
+.. class:: PickleHTMLBuilder
+
+ This builder produces a directory with pickle files containing mostly HTML
+ fragments and TOC information, for use of a web application (or custom
+ postprocessing tool) that doesn't use the standard HTML templates.
+
+ See :ref:`serialization-details` for details about the output format.
+
+ .. autoattribute:: name
+
+ The old name ``web`` still works as well.
+
+ .. autoattribute:: supported_image_types
+
+ The file suffix is ``.fpickle``. The global context is called
+ ``globalcontext.pickle``, the search index ``searchindex.pickle``.
+
+.. class:: JSONHTMLBuilder
+
+ This builder produces a directory with JSON files containing mostly HTML
+ fragments and TOC information, for use of a web application (or custom
+ postprocessing tool) that doesn't use the standard HTML templates.
+
+ See :ref:`serialization-details` for details about the output format.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ The file suffix is ``.fjson``. The global context is called
+ ``globalcontext.json``, the search index ``searchindex.json``.
+
+ .. versionadded:: 0.5
+
+.. module:: sphinx.builders.gettext
+.. class:: MessageCatalogBuilder
+
+ This builder produces gettext-style message catalogs. Each top-level file or
+ subdirectory grows a single ``.pot`` catalog template.
+
+ See the documentation on :ref:`intl` for further reference.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ .. versionadded:: 1.1
+
+.. module:: sphinx.builders.changes
+.. class:: ChangesBuilder
+
+ This builder produces an HTML overview of all :rst:dir:`versionadded`,
+ :rst:dir:`versionchanged` and :rst:dir:`deprecated` directives for the current
+ :confval:`version`. This is useful to generate a ChangeLog file, for
+ example.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+.. module:: sphinx.builders.linkcheck
+.. class:: CheckExternalLinksBuilder
+
+ This builder scans all documents for external links, tries to open them with
+ :mod:`urllib2`, and writes an overview which ones are broken and redirected
+ to standard output and to :file:`output.txt` in the output directory.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+.. module:: sphinx.builders.xml
+.. class:: XMLBuilder
+
+ This builder produces Docutils-native XML files. The output can be
+ transformed with standard XML tools such as XSLT processors into arbitrary
+ final forms.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ .. versionadded:: 1.2
+
+.. class:: PseudoXMLBuilder
+
+ This builder is used for debugging the Sphinx/Docutils "Reader to Transform
+ to Writer" pipeline. It produces compact pretty-printed "pseudo-XML", files
+ where nesting is indicated by indentation (no end-tags). External
+ attributes for all elements are output, and internal attributes for any
+ leftover "pending" elements are also given.
+
+ .. autoattribute:: name
+
+ .. autoattribute:: supported_image_types
+
+ .. versionadded:: 1.2
+
+
+Built-in Sphinx extensions that offer more builders are:
+
+* :mod:`~sphinx.ext.doctest`
+* :mod:`~sphinx.ext.coverage`
+
+
+.. _serialization-details:
+
+Serialization builder details
+-----------------------------
+
+All serialization builders outputs one file per source file and a few special
+files. They also copy the reST source files in the directory ``_sources``
+under the output directory.
+
+The :class:`.PickleHTMLBuilder` is a builtin subclass that implements the pickle
+serialization interface.
+
+The files per source file have the extensions of
+:attr:`~.SerializingHTMLBuilder.out_suffix`, and are arranged in directories
+just as the source files are. They unserialize to a dictionary (or dictionary
+like structure) with these keys:
+
+``body``
+ The HTML "body" (that is, the HTML rendering of the source file), as rendered
+ by the HTML translator.
+
+``title``
+ The title of the document, as HTML (may contain markup).
+
+``toc``
+ The table of contents for the file, rendered as an HTML ``<ul>``.
+
+``display_toc``
+ A boolean that is ``True`` if the ``toc`` contains more than one entry.
+
+``current_page_name``
+ The document name of the current file.
+
+``parents``, ``prev`` and ``next``
+ Information about related chapters in the TOC tree. Each relation is a
+ dictionary with the keys ``link`` (HREF for the relation) and ``title``
+ (title of the related document, as HTML). ``parents`` is a list of
+ relations, while ``prev`` and ``next`` are a single relation.
+
+``sourcename``
+ The name of the source file under ``_sources``.
+
+The special files are located in the root output directory. They are:
+
+:attr:`.SerializingHTMLBuilder.globalcontext_filename`
+ A pickled dict with these keys:
+
+ ``project``, ``copyright``, ``release``, ``version``
+ The same values as given in the configuration file.
+
+ ``style``
+ :confval:`html_style`.
+
+ ``last_updated``
+ Date of last build.
+
+ ``builder``
+ Name of the used builder, in the case of pickles this is always
+ ``'pickle'``.
+
+ ``titles``
+ A dictionary of all documents' titles, as HTML strings.
+
+:attr:`.SerializingHTMLBuilder.searchindex_filename`
+ An index that can be used for searching the documentation. It is a pickled
+ list with these entries:
+
+ * A list of indexed docnames.
+ * A list of document titles, as HTML strings, in the same order as the first
+ list.
+ * A dict mapping word roots (processed by an English-language stemmer) to a
+ list of integers, which are indices into the first list.
+
+``environment.pickle``
+ The build environment. This is always a pickle file, independent of the
+ builder and a copy of the environment that was used when the builder was
+ started.
+
+ .. todo:: Document common members.
+
+ Unlike the other pickle files this pickle file requires that the ``sphinx``
+ package is available on unpickling.
diff --git a/doc/changes.rst b/doc/changes.rst
new file mode 100644
index 0000000..d5927a7
--- /dev/null
+++ b/doc/changes.rst
@@ -0,0 +1,8 @@
+:tocdepth: 2
+
+.. _changes:
+
+Changes in Sphinx
+*****************
+
+.. include:: ../CHANGES
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 0000000..9640e2e
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,124 @@
+# -*- coding: utf-8 -*-
+#
+# Sphinx documentation build configuration file
+
+import re
+import sphinx
+
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
+ 'sphinx.ext.autosummary', 'sphinx.ext.extlinks']
+
+master_doc = 'contents'
+templates_path = ['_templates']
+exclude_patterns = ['_build']
+
+project = 'Sphinx'
+copyright = '2007-2014, Georg Brandl and the Sphinx team'
+version = sphinx.__released__
+release = version
+show_authors = True
+
+html_theme = 'sphinx13'
+html_theme_path = ['_themes']
+modindex_common_prefix = ['sphinx.']
+html_static_path = ['_static']
+html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']}
+html_additional_pages = {'index': 'index.html'}
+html_use_opensearch = 'http://sphinx-doc.org'
+
+htmlhelp_basename = 'Sphinxdoc'
+
+epub_theme = 'epub'
+epub_basename = 'sphinx'
+epub_author = 'Georg Brandl'
+epub_publisher = 'http://sphinx-doc.org/'
+epub_scheme = 'url'
+epub_identifier = epub_publisher
+epub_pre_files = [('index.html', 'Welcome')]
+epub_post_files = [('install.html', 'Installing Sphinx'),
+ ('develop.html', 'Sphinx development')]
+epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js',
+ '_static/jquery.js', '_static/searchtools.js', '_static/underscore.js',
+ '_static/basic.css', 'search.html', '_static/websupport.js']
+epub_fix_images = False
+epub_max_image_width = 0
+epub_show_urls = 'inline'
+epub_use_index = False
+epub_guide = (('toc', 'contents.html', u'Table of Contents'),)
+
+latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',
+ 'Georg Brandl', 'manual', 1)]
+latex_logo = '_static/sphinx.png'
+latex_elements = {
+ 'fontpkg': '\\usepackage{palatino}',
+}
+latex_show_urls = 'footnote'
+
+autodoc_member_order = 'groupwise'
+todo_include_todos = True
+extlinks = {'duref': ('http://docutils.sourceforge.net/docs/ref/rst/'
+ 'restructuredtext.html#%s', ''),
+ 'durole': ('http://docutils.sourceforge.net/docs/ref/rst/'
+ 'roles.html#%s', ''),
+ 'dudir': ('http://docutils.sourceforge.net/docs/ref/rst/'
+ 'directives.html#%s', '')}
+
+man_pages = [
+ ('contents', 'sphinx-all', 'Sphinx documentation generator system manual',
+ 'Georg Brandl', 1),
+ ('man/sphinx-build', 'sphinx-build', 'Sphinx documentation generator tool',
+ '', 1),
+ ('man/sphinx-quickstart', 'sphinx-quickstart', 'Sphinx documentation '
+ 'template generator', '', 1),
+ ('man/sphinx-apidoc', 'sphinx-apidoc', 'Sphinx API doc generator tool',
+ '', 1),
+]
+
+texinfo_documents = [
+ ('contents', 'sphinx', 'Sphinx Documentation', 'Georg Brandl',
+ 'Sphinx', 'The Sphinx documentation builder.', 'Documentation tools',
+ 1),
+]
+
+# We're not using intersphinx right now, but if we did, this would be part of
+# the mapping:
+intersphinx_mapping = {'python': ('http://docs.python.org/dev', None)}
+
+# Sphinx document translation with sphinx gettext feature uses these settings:
+locale_dirs = ['locale/']
+gettext_compact = False
+
+
+# -- Extension interface -------------------------------------------------------
+
+from sphinx import addnodes
+
+
+event_sig_re = re.compile(r'([a-zA-Z-]+)\s*\((.*)\)')
+
+def parse_event(env, sig, signode):
+ m = event_sig_re.match(sig)
+ if not m:
+ signode += addnodes.desc_name(sig, sig)
+ return sig
+ name, args = m.groups()
+ signode += addnodes.desc_name(name, name)
+ plist = addnodes.desc_parameterlist()
+ for arg in args.split(','):
+ arg = arg.strip()
+ plist += addnodes.desc_parameter(arg, arg)
+ signode += plist
+ return name
+
+
+def setup(app):
+ from sphinx.ext.autodoc import cut_lines
+ from sphinx.util.docfields import GroupedField
+ app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
+ app.add_object_type('confval', 'confval',
+ objname='configuration value',
+ indextemplate='pair: %s; configuration value')
+ fdesc = GroupedField('parameter', label='Parameters',
+ names=['param'], can_collapse=True)
+ app.add_object_type('event', 'event', 'pair: %s; event', parse_event,
+ doc_field_types=[fdesc])
diff --git a/doc/config.rst b/doc/config.rst
new file mode 100644
index 0000000..26079e6
--- /dev/null
+++ b/doc/config.rst
@@ -0,0 +1,1459 @@
+.. highlightlang:: python
+
+.. _build-config:
+
+The build configuration file
+============================
+
+.. module:: conf
+ :synopsis: Build configuration file.
+
+The :term:`configuration directory` must contain a file named :file:`conf.py`.
+This file (containing Python code) is called the "build configuration file" and
+contains all configuration needed to customize Sphinx input and output behavior.
+
+The configuration file is executed as Python code at build time (using
+:func:`execfile`, and with the current directory set to its containing
+directory), and therefore can execute arbitrarily complex code. Sphinx then
+reads simple names from the file's namespace as its configuration.
+
+Important points to note:
+
+* If not otherwise documented, values must be strings, and their default is the
+ empty string.
+
+* The term "fully-qualified name" refers to a string that names an importable
+ Python object inside a module; for example, the FQN
+ ``"sphinx.builders.Builder"`` means the ``Builder`` class in the
+ ``sphinx.builders`` module.
+
+* Remember that document names use ``/`` as the path separator and don't contain
+ the file name extension.
+
+* Since :file:`conf.py` is read as a Python file, the usual rules apply for
+ encodings and Unicode support: declare the encoding using an encoding cookie
+ (a comment like ``# -*- coding: utf-8 -*-``) and use Unicode string literals
+ when you include non-ASCII characters in configuration values.
+
+* The contents of the config namespace are pickled (so that Sphinx can find out
+ when configuration changes), so it may not contain unpickleable values --
+ delete them from the namespace with ``del`` if appropriate. Modules are
+ removed automatically, so you don't need to ``del`` your imports after use.
+
+.. _conf-tags:
+
+* There is a special object named ``tags`` available in the config file.
+ It can be used to query and change the tags (see :ref:`tags`). Use
+ ``tags.has('tag')`` to query, ``tags.add('tag')`` and ``tags.remove('tag')``
+ to change.
+ Note that the current builder tag is not available in ``conf.py``, as it is
+ created *after* the builder is initialized.
+
+
+General configuration
+---------------------
+
+.. confval:: extensions
+
+ A list of strings that are module names of Sphinx extensions. These can be
+ extensions coming with Sphinx (named ``sphinx.ext.*``) or custom ones.
+
+ Note that you can extend :data:`sys.path` within the conf file if your
+ extensions live in another directory -- but make sure you use absolute paths.
+ If your extension path is relative to the :term:`configuration directory`,
+ use :func:`os.path.abspath` like so::
+
+ import sys, os
+
+ sys.path.append(os.path.abspath('sphinxext'))
+
+ extensions = ['extname']
+
+ That way, you can load an extension called ``extname`` from the subdirectory
+ ``sphinxext``.
+
+ The configuration file itself can be an extension; for that, you only need to
+ provide a :func:`setup` function in it.
+
+.. confval:: source_suffix
+
+ The file name extension of source files. Only files with this suffix will be
+ read as sources. Default is ``'.rst'``.
+
+.. confval:: source_encoding
+
+ The encoding of all reST source files. The recommended encoding, and the
+ default value, is ``'utf-8-sig'``.
+
+ .. versionadded:: 0.5
+ Previously, Sphinx accepted only UTF-8 encoded sources.
+
+.. confval:: master_doc
+
+ The document name of the "master" document, that is, the document that
+ contains the root :rst:dir:`toctree` directive. Default is ``'contents'``.
+
+.. confval:: exclude_patterns
+
+ A list of glob-style patterns that should be excluded when looking for source
+ files. [1]_ They are matched against the source file names relative to the
+ source directory, using slashes as directory separators on all platforms.
+
+ Example patterns:
+
+ - ``'library/xml.rst'`` -- ignores the ``library/xml.rst`` file (replaces
+ entry in :confval:`unused_docs`)
+ - ``'library/xml'`` -- ignores the ``library/xml`` directory (replaces entry
+ in :confval:`exclude_trees`)
+ - ``'library/xml*'`` -- ignores all files and directories starting with
+ ``library/xml``
+ - ``'**/.svn'`` -- ignores all ``.svn`` directories (replaces entry in
+ :confval:`exclude_dirnames`)
+
+ :confval:`exclude_patterns` is also consulted when looking for static files
+ in :confval:`html_static_path`.
+
+ .. versionadded:: 1.0
+
+.. confval:: unused_docs
+
+ A list of document names that are present, but not currently included in the
+ toctree. Use this setting to suppress the warning that is normally emitted
+ in that case.
+
+ .. deprecated:: 1.0
+ Use :confval:`exclude_patterns` instead.
+
+.. confval:: exclude_trees
+
+ A list of directory paths, relative to the source directory, that are to be
+ recursively excluded from the search for source files, that is, their
+ subdirectories won't be searched too. The default is ``[]``.
+
+ .. versionadded:: 0.4
+
+ .. deprecated:: 1.0
+ Use :confval:`exclude_patterns` instead.
+
+.. confval:: exclude_dirnames
+
+ A list of directory names that are to be excluded from any recursive
+ operation Sphinx performs (e.g. searching for source files or copying static
+ files). This is useful, for example, to exclude version-control-specific
+ directories like ``'CVS'``. The default is ``[]``.
+
+ .. versionadded:: 0.5
+
+ .. deprecated:: 1.0
+ Use :confval:`exclude_patterns` instead.
+
+.. confval:: templates_path
+
+ A list of paths that contain extra templates (or templates that overwrite
+ builtin/theme-specific templates). Relative paths are taken as relative to
+ the configuration directory.
+
+.. confval:: template_bridge
+
+ A string with the fully-qualified name of a callable (or simply a class) that
+ returns an instance of :class:`~sphinx.application.TemplateBridge`. This
+ instance is then used to render HTML documents, and possibly the output of
+ other builders (currently the changes builder). (Note that the template
+ bridge must be made theme-aware if HTML themes are to be used.)
+
+.. confval:: rst_epilog
+
+ .. index:: pair: global; substitutions
+
+ A string of reStructuredText that will be included at the end of every source
+ file that is read. This is the right place to add substitutions that should
+ be available in every file. An example::
+
+ rst_epilog = """
+ .. |psf| replace:: Python Software Foundation
+ """
+
+ .. versionadded:: 0.6
+
+.. confval:: rst_prolog
+
+ A string of reStructuredText that will be included at the beginning of every
+ source file that is read.
+
+ .. versionadded:: 1.0
+
+.. confval:: primary_domain
+
+ .. index:: default; domain
+ primary; domain
+
+ The name of the default :ref:`domain <domains>`. Can also be ``None`` to
+ disable a default domain. The default is ``'py'``. Those objects in other
+ domains (whether the domain name is given explicitly, or selected by a
+ :rst:dir:`default-domain` directive) will have the domain name explicitly
+ prepended when named (e.g., when the default domain is C, Python functions
+ will be named "Python function", not just "function").
+
+ .. versionadded:: 1.0
+
+.. confval:: default_role
+
+ .. index:: default; role
+
+ The name of a reST role (builtin or Sphinx extension) to use as the default
+ role, that is, for text marked up ```like this```. This can be set to
+ ``'py:obj'`` to make ```filter``` a cross-reference to the Python function
+ "filter". The default is ``None``, which doesn't reassign the default role.
+
+ The default role can always be set within individual documents using the
+ standard reST :rst:dir:`default-role` directive.
+
+ .. versionadded:: 0.4
+
+.. confval:: keep_warnings
+
+ If true, keep warnings as "system message" paragraphs in the built documents.
+ Regardless of this setting, warnings are always written to the standard error
+ stream when ``sphinx-build`` is run.
+
+ The default is ``False``, the pre-0.5 behavior was to always keep them.
+
+ .. versionadded:: 0.5
+
+.. confval:: needs_sphinx
+
+ If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
+ compare it with its version and refuse to build if it is too old. Default is
+ no requirement.
+
+ .. versionadded:: 1.0
+
+.. confval:: nitpicky
+
+ If true, Sphinx will warn about *all* references where the target cannot be
+ found. Default is ``False``. You can activate this mode temporarily using
+ the :option:`-n` command-line switch.
+
+ .. versionadded:: 1.0
+
+.. confval:: nitpick_ignore
+
+ A list of ``(type, target)`` tuples (by default empty) that should be ignored
+ when generating warnings in "nitpicky mode". Note that ``type`` should
+ include the domain name if present. Example entries would be ``('py:func',
+ 'int')`` or ``('envvar', 'LD_LIBRARY_PATH')``.
+
+ .. versionadded:: 1.1
+
+
+Project information
+-------------------
+
+.. confval:: project
+
+ The documented project's name.
+
+.. confval:: copyright
+
+ A copyright statement in the style ``'2008, Author Name'``.
+
+.. confval:: version
+
+ The major project version, used as the replacement for ``|version|``. For
+ example, for the Python documentation, this may be something like ``2.6``.
+
+.. confval:: release
+
+ The full project version, used as the replacement for ``|release|`` and
+ e.g. in the HTML templates. For example, for the Python documentation, this
+ may be something like ``2.6.0rc1``.
+
+ If you don't need the separation provided between :confval:`version` and
+ :confval:`release`, just set them both to the same value.
+
+.. confval:: today
+ today_fmt
+
+ These values determine how to format the current date, used as the
+ replacement for ``|today|``.
+
+ * If you set :confval:`today` to a non-empty value, it is used.
+ * Otherwise, the current time is formatted using :func:`time.strftime` and
+ the format given in :confval:`today_fmt`.
+
+ The default is no :confval:`today` and a :confval:`today_fmt` of ``'%B %d,
+ %Y'`` (or, if translation is enabled with :confval:`language`, an equivalent
+ %format for the selected locale).
+
+.. confval:: highlight_language
+
+ The default language to highlight source code in. The default is
+ ``'python'``. The value should be a valid Pygments lexer name, see
+ :ref:`code-examples` for more details.
+
+ .. versionadded:: 0.5
+
+.. confval:: pygments_style
+
+ The style name to use for Pygments highlighting of source code. The default
+ style is selected by the theme for HTML output, and ``'sphinx'`` otherwise.
+
+ .. versionchanged:: 0.3
+ If the value is a fully-qualified name of a custom Pygments style class,
+ this is then used as custom style.
+
+.. confval:: add_function_parentheses
+
+ A boolean that decides whether parentheses are appended to function and
+ method role text (e.g. the content of ``:func:`input```) to signify that the
+ name is callable. Default is ``True``.
+
+.. confval:: add_module_names
+
+ A boolean that decides whether module names are prepended to all
+ :term:`object` names (for object types where a "module" of some kind is
+ defined), e.g. for :rst:dir:`py:function` directives. Default is ``True``.
+
+.. confval:: show_authors
+
+ A boolean that decides whether :rst:dir:`codeauthor` and
+ :rst:dir:`sectionauthor` directives produce any output in the built files.
+
+.. confval:: modindex_common_prefix
+
+ A list of prefixes that are ignored for sorting the Python module index
+ (e.g., if this is set to ``['foo.']``, then ``foo.bar`` is shown under ``B``,
+ not ``F``). This can be handy if you document a project that consists of a
+ single package. Works only for the HTML builder currently. Default is
+ ``[]``.
+
+ .. versionadded:: 0.6
+
+.. confval:: trim_footnote_reference_space
+
+ Trim spaces before footnote references that are necessary for the reST parser
+ to recognize the footnote, but do not look too nice in the output.
+
+ .. versionadded:: 0.6
+
+.. confval:: trim_doctest_flags
+
+ If true, doctest flags (comments looking like ``# doctest: FLAG, ...``) at
+ the ends of lines and ``<BLANKLINE>`` markers are removed for all code
+ blocks showing interactive Python sessions (i.e. doctests). Default is
+ true. See the extension :mod:`~sphinx.ext.doctest` for more possibilities
+ of including doctests.
+
+ .. versionadded:: 1.0
+ .. versionchanged:: 1.1
+ Now also removes ``<BLANKLINE>``.
+
+
+.. _intl-options:
+
+Options for internationalization
+--------------------------------
+
+These options influence Sphinx' *Native Language Support*. See the
+documentation on :ref:`intl` for details.
+
+.. confval:: language
+
+ The code for the language the docs are written in. Any text automatically
+ generated by Sphinx will be in that language. Also, Sphinx will try to
+ substitute individual paragraphs from your documents with the translation
+ sets obtained from :confval:`locale_dirs`. In the LaTeX builder, a suitable
+ language will be selected as an option for the *Babel* package. Default is
+ ``None``, which means that no translation will be done.
+
+ .. versionadded:: 0.5
+
+ Currently supported languages by Sphinx are:
+
+ * ``bn`` -- Bengali
+ * ``ca`` -- Catalan
+ * ``cs`` -- Czech
+ * ``da`` -- Danish
+ * ``de`` -- German
+ * ``en`` -- English
+ * ``es`` -- Spanish
+ * ``et`` -- Estonian
+ * ``eu`` -- Basque
+ * ``fa`` -- Iranian
+ * ``fi`` -- Finnish
+ * ``fr`` -- French
+ * ``he`` -- Hebrew
+ * ``hr`` -- Croatian
+ * ``hu`` -- Hungarian
+ * ``id`` -- Indonesian
+ * ``it`` -- Italian
+ * ``ja`` -- Japanese
+ * ``ko`` -- Korean
+ * ``lt`` -- Lithuanian
+ * ``lv`` -- Latvian
+ * ``mk`` -- Macedonian
+ * ``nb_NO`` -- Norwegian Bokmal
+ * ``ne`` -- Nepali
+ * ``nl`` -- Dutch
+ * ``pl`` -- Polish
+ * ``pt_BR`` -- Brazilian Portuguese
+ * ``pt_PT`` -- European Portuguese
+ * ``ru`` -- Russian
+ * ``si`` -- Sinhala
+ * ``sk`` -- Slovak
+ * ``sl`` -- Slovenian
+ * ``sv`` -- Swedish
+ * ``tr`` -- Turkish
+ * ``uk_UA`` -- Ukrainian
+ * ``vi`` -- Vietnamese
+ * ``zh_CN`` -- Simplified Chinese
+ * ``zh_TW`` -- Traditional Chinese
+
+.. confval:: locale_dirs
+
+ .. versionadded:: 0.5
+
+ Directories in which to search for additional message catalogs (see
+ :confval:`language`), relative to the source directory. The directories on
+ this path are searched by the standard :mod:`gettext` module.
+
+ Internal messages are fetched from a text domain of ``sphinx``; so if you
+ add the directory :file:`./locale` to this settting, the message catalogs
+ (compiled from ``.po`` format using :program:`msgfmt`) must be in
+ :file:`./locale/{language}/LC_MESSAGES/sphinx.mo`. The text domain of
+ individual documents depends on :confval:`gettext_compact`.
+
+ The default is ``[]``.
+
+.. confval:: gettext_compact
+
+ .. versionadded:: 1.1
+
+ If true, a document's text domain is its docname if it is a top-level
+ project file and its very base directory otherwise.
+
+ By default, the document ``markup/code.rst`` ends up in the ``markup`` text
+ domain. With this option set to ``False``, it is ``markup/code``.
+
+
+.. _html-options:
+
+Options for HTML output
+-----------------------
+
+These options influence HTML as well as HTML Help output, and other builders
+that use Sphinx' HTMLWriter class.
+
+.. confval:: html_theme
+
+ The "theme" that the HTML output should use. See the :doc:`section about
+ theming <theming>`. The default is ``'default'``.
+
+ .. versionadded:: 0.6
+
+.. confval:: html_theme_options
+
+ A dictionary of options that influence the look and feel of the selected
+ theme. These are theme-specific. For the options understood by the builtin
+ themes, see :ref:`this section <builtin-themes>`.
+
+ .. versionadded:: 0.6
+
+.. confval:: html_theme_path
+
+ A list of paths that contain custom themes, either as subdirectories or as
+ zip files. Relative paths are taken as relative to the configuration
+ directory.
+
+ .. versionadded:: 0.6
+
+.. confval:: html_style
+
+ The style sheet to use for HTML pages. A file of that name must exist either
+ in Sphinx' :file:`static/` path, or in one of the custom paths given in
+ :confval:`html_static_path`. Default is the stylesheet given by the selected
+ theme. If you only want to add or override a few things compared to the
+ theme's stylesheet, use CSS ``@import`` to import the theme's stylesheet.
+
+.. confval:: html_title
+
+ The "title" for HTML documentation generated with Sphinx' own templates.
+ This is appended to the ``<title>`` tag of individual pages, and used in the
+ navigation bar as the "topmost" element. It defaults to :samp:`'{<project>}
+ v{<revision>} documentation'` (with the values coming from the config
+ values).
+
+.. confval:: html_short_title
+
+ A shorter "title" for the HTML docs. This is used in for links in the header
+ and in the HTML Help docs. If not given, it defaults to the value of
+ :confval:`html_title`.
+
+ .. versionadded:: 0.4
+
+.. confval:: html_context
+
+ A dictionary of values to pass into the template engine's context for all
+ pages. Single values can also be put in this dictionary using the
+ :option:`-A` command-line option of ``sphinx-build``.
+
+ .. versionadded:: 0.5
+
+.. confval:: html_logo
+
+ If given, this must be the name of an image file (path relative to the
+ :term:`configuration directory`) that is the logo of the docs. It is placed
+ at the top of the sidebar; its width should therefore not exceed 200 pixels.
+ Default: ``None``.
+
+ .. versionadded:: 0.4.1
+ The image file will be copied to the ``_static`` directory of the output
+ HTML, but only if the file does not already exist there.
+
+.. confval:: html_favicon
+
+ If given, this must be the name of an image file (path relative to the
+ :term:`configuration directory`) that is the favicon of the docs. Modern browsers use this
+ as icon for tabs, windows and bookmarks. It should be a Windows-style icon
+ file (``.ico``), which is 16x16 or 32x32 pixels large. Default: ``None``.
+
+ .. versionadded:: 0.4
+ The image file will be copied to the ``_static`` directory of the output
+ HTML, but only if the file does not already exist there.
+
+.. confval:: html_static_path
+
+ A list of paths that contain custom static files (such as style
+ sheets or script files). Relative paths are taken as relative to
+ the configuration directory. They are copied to the output's
+ :file:`_static` directory after the theme's static files, so a file
+ named :file:`default.css` will overwrite the theme's
+ :file:`default.css`.
+
+ .. versionchanged:: 0.4
+ The paths in :confval:`html_static_path` can now contain subdirectories.
+
+ .. versionchanged:: 1.0
+ The entries in :confval:`html_static_path` can now be single files.
+
+.. confval:: html_extra_path
+
+ A list of paths that contain extra files not directly related to
+ the documentation, such as :file:`robots.txt` or :file:`.htaccess`.
+ Relative paths are taken as relative to the configuration
+ directory. They are copied to the output directory. They will
+ overwrite any existing file of the same name.
+
+ As these files are not meant to be built, they are automatically added to
+ :confval:`exclude_patterns`.
+
+ .. versionadded:: 1.2
+
+.. confval:: html_last_updated_fmt
+
+ If this is not the empty string, a 'Last updated on:' timestamp is inserted
+ at every page bottom, using the given :func:`strftime` format. Default is
+ ``'%b %d, %Y'`` (or a locale-dependent equivalent).
+
+.. confval:: html_use_smartypants
+
+ If true, *SmartyPants* will be used to convert quotes and dashes to
+ typographically correct entities. Default: ``True``.
+
+.. confval:: html_add_permalinks
+
+ Sphinx will add "permalinks" for each heading and description environment as
+ paragraph signs that become visible when the mouse hovers over them.
+
+ This value determines the text for the permalink; it defaults to ``"¶"``.
+ Set it to ``None`` or the empty string to disable permalinks.
+
+ .. versionadded:: 0.6
+ Previously, this was always activated.
+
+ .. versionchanged:: 1.1
+ This can now be a string to select the actual text of the link.
+ Previously, only boolean values were accepted.
+
+.. confval:: html_sidebars
+
+ Custom sidebar templates, must be a dictionary that maps document names to
+ template names.
+
+ The keys can contain glob-style patterns [1]_, in which case all matching
+ documents will get the specified sidebars. (A warning is emitted when a
+ more than one glob-style pattern matches for any document.)
+
+ The values can be either lists or single strings.
+
+ * If a value is a list, it specifies the complete list of sidebar templates
+ to include. If all or some of the default sidebars are to be included,
+ they must be put into this list as well.
+
+ The default sidebars (for documents that don't match any pattern) are:
+ ``['localtoc.html', 'relations.html', 'sourcelink.html',
+ 'searchbox.html']``.
+
+ * If a value is a single string, it specifies a custom sidebar to be added
+ between the ``'sourcelink.html'`` and ``'searchbox.html'`` entries. This
+ is for compatibility with Sphinx versions before 1.0.
+
+ Builtin sidebar templates that can be rendered are:
+
+ * **localtoc.html** -- a fine-grained table of contents of the current document
+ * **globaltoc.html** -- a coarse-grained table of contents for the whole
+ documentation set, collapsed
+ * **relations.html** -- two links to the previous and next documents
+ * **sourcelink.html** -- a link to the source of the current document, if
+ enabled in :confval:`html_show_sourcelink`
+ * **searchbox.html** -- the "quick search" box
+
+ Example::
+
+ html_sidebars = {
+ '**': ['globaltoc.html', 'sourcelink.html', 'searchbox.html'],
+ 'using/windows': ['windowssidebar.html', 'searchbox.html'],
+ }
+
+ This will render the custom template ``windowssidebar.html`` and the quick
+ search box within the sidebar of the given document, and render the default
+ sidebars for all other pages (except that the local TOC is replaced by the
+ global TOC).
+
+ .. versionadded:: 1.0
+ The ability to use globbing keys and to specify multiple sidebars.
+
+ Note that this value only has no effect if the chosen theme does not possess
+ a sidebar, like the builtin **scrolls** and **haiku** themes.
+
+.. confval:: html_additional_pages
+
+ Additional templates that should be rendered to HTML pages, must be a
+ dictionary that maps document names to template names.
+
+ Example::
+
+ html_additional_pages = {
+ 'download': 'customdownload.html',
+ }
+
+ This will render the template ``customdownload.html`` as the page
+ ``download.html``.
+
+.. confval:: html_domain_indices
+
+ If true, generate domain-specific indices in addition to the general index.
+ For e.g. the Python domain, this is the global module index. Default is
+ ``True``.
+
+ This value can be a bool or a list of index names that should be generated.
+ To find out the index name for a specific index, look at the HTML file name.
+ For example, the Python module index has the name ``'py-modindex'``.
+
+ .. versionadded:: 1.0
+
+.. confval:: html_use_modindex
+
+ If true, add a module index to the HTML documents. Default is ``True``.
+
+ .. deprecated:: 1.0
+ Use :confval:`html_domain_indices`.
+
+.. confval:: html_use_index
+
+ If true, add an index to the HTML documents. Default is ``True``.
+
+ .. versionadded:: 0.4
+
+.. confval:: html_split_index
+
+ If true, the index is generated twice: once as a single page with all the
+ entries, and once as one page per starting letter. Default is ``False``.
+
+ .. versionadded:: 0.4
+
+.. confval:: html_copy_source
+
+ If true, the reST sources are included in the HTML build as
+ :file:`_sources/{name}`. The default is ``True``.
+
+ .. warning::
+
+ If this config value is set to ``False``, the JavaScript search function
+ will only display the titles of matching documents, and no excerpt from
+ the matching contents.
+
+.. confval:: html_show_sourcelink
+
+ If true (and :confval:`html_copy_source` is true as well), links to the
+ reST sources will be added to the sidebar. The default is ``True``.
+
+ .. versionadded:: 0.6
+
+.. confval:: html_use_opensearch
+
+ If nonempty, an `OpenSearch <http://opensearch.org>` description file will be
+ output, and all pages will contain a ``<link>`` tag referring to it. Since
+ OpenSearch doesn't support relative URLs for its search page location, the
+ value of this option must be the base URL from which these documents are
+ served (without trailing slash), e.g. ``"http://docs.python.org"``. The
+ default is ``''``.
+
+.. confval:: html_file_suffix
+
+ This is the file name suffix for generated HTML files. The default is
+ ``".html"``.
+
+ .. versionadded:: 0.4
+
+.. confval:: html_link_suffix
+
+ Suffix for generated links to HTML files. The default is whatever
+ :confval:`html_file_suffix` is set to; it can be set differently (e.g. to
+ support different web server setups).
+
+ .. versionadded:: 0.6
+
+.. confval:: html_translator_class
+
+ A string with the fully-qualified name of a HTML Translator class, that is, a
+ subclass of Sphinx' :class:`~sphinx.writers.html.HTMLTranslator`, that is used
+ to translate document trees to HTML. Default is ``None`` (use the builtin
+ translator).
+
+.. confval:: html_show_copyright
+
+ If true, "(C) Copyright ..." is shown in the HTML footer. Default is ``True``.
+
+ .. versionadded:: 1.0
+
+.. confval:: html_show_sphinx
+
+ If true, "Created using Sphinx" is shown in the HTML footer. Default is
+ ``True``.
+
+ .. versionadded:: 0.4
+
+.. confval:: html_output_encoding
+
+ Encoding of HTML output files. Default is ``'utf-8'``. Note that this
+ encoding name must both be a valid Python encoding name and a valid HTML
+ ``charset`` value.
+
+ .. versionadded:: 1.0
+
+.. confval:: html_compact_lists
+
+ If true, list items containing only a single paragraph will not be rendered
+ with a ``<p>`` element. This is standard docutils behavior. Default:
+ ``True``.
+
+ .. versionadded:: 1.0
+
+.. confval:: html_secnumber_suffix
+
+ Suffix for section numbers. Default: ``". "``. Set to ``" "`` to suppress
+ the final dot on section numbers.
+
+ .. versionadded:: 1.0
+
+.. confval:: html_search_language
+
+ Language to be used for generating the HTML full-text search index. This
+ defaults to the global language selected with :confval:`language`. If there
+ is no support for this language, ``"en"`` is used which selects the English
+ language.
+
+ Support is present for these languages:
+
+ * ``en`` -- English
+ * ``ja`` -- Japanese
+
+ .. versionadded:: 1.1
+
+.. confval:: html_search_options
+
+ A dictionary with options for the search language support, empty by default.
+ The meaning of these options depends on the language selected.
+
+ The English support has no options.
+
+ The Japanese support has these options:
+
+ * ``type`` -- ``'mecab'`` or ``'default'`` (selects either MeCab or
+ TinySegmenter word splitter algorithm)
+ * ``dic_enc`` -- the encoding for the MeCab algorithm
+ * ``dict`` -- the dictionary to use for the MeCab algorithm
+ * ``lib`` -- the library name for finding the MeCab library via ctypes if the
+ Python binding is not installed
+
+ .. versionadded:: 1.1
+
+.. confval:: html_search_scorer
+
+ The name of a javascript file (relative to the configuration directory) that
+ implements a search results scorer. If empty, the default will be used.
+
+ .. XXX describe interface for scorer here
+
+ .. versionadded:: 1.2
+
+.. confval:: htmlhelp_basename
+
+ Output file base name for HTML help builder. Default is ``'pydoc'``.
+
+
+.. _epub-options:
+
+Options for epub output
+-----------------------
+
+These options influence the epub output. As this builder derives from the HTML
+builder, the HTML options also apply where appropriate. The actual values for
+some of the options is not really important, they just have to be entered into
+the `Dublin Core metadata <http://dublincore.org/>`_.
+
+.. confval:: epub_basename
+
+ The basename for the epub file. It defaults to the :confval:`project` name.
+
+.. confval:: epub_theme
+
+ The HTML theme for the epub output. Since the default themes are not
+ optimized for small screen space, using the same theme for HTML and epub
+ output is usually not wise. This defaults to ``'epub'``, a theme designed to
+ save visual space.
+
+.. confval:: epub_theme_options
+
+ A dictionary of options that influence the look and feel of the selected
+ theme. These are theme-specific. For the options understood by the builtin
+ themes, see :ref:`this section <builtin-themes>`.
+
+ .. versionadded:: 1.2
+
+.. confval:: epub_title
+
+ The title of the document. It defaults to the :confval:`html_title` option
+ but can be set independently for epub creation.
+
+.. confval:: epub_author
+
+ The author of the document. This is put in the Dublin Core metadata. The
+ default value is ``'unknown'``.
+
+.. confval:: epub_language
+
+ The language of the document. This is put in the Dublin Core metadata. The
+ default is the :confval:`language` option or ``'en'`` if unset.
+
+.. confval:: epub_publisher
+
+ The publisher of the document. This is put in the Dublin Core metadata. You
+ may use any sensible string, e.g. the project homepage. The default value is
+ ``'unknown'``.
+
+.. confval:: epub_copyright
+
+ The copyright of the document. It defaults to the :confval:`copyright`
+ option but can be set independently for epub creation.
+
+.. confval:: epub_identifier
+
+ An identifier for the document. This is put in the Dublin Core metadata.
+ For published documents this is the ISBN number, but you can also use an
+ alternative scheme, e.g. the project homepage. The default value is
+ ``'unknown'``.
+
+.. confval:: epub_scheme
+
+ The publication scheme for the :confval:`epub_identifier`. This is put in
+ the Dublin Core metadata. For published books the scheme is ``'ISBN'``. If
+ you use the project homepage, ``'URL'`` seems reasonable. The default value
+ is ``'unknown'``.
+
+.. confval:: epub_uid
+
+ A unique identifier for the document. This is put in the Dublin Core
+ metadata. You may use a random string. The default value is ``'unknown'``.
+
+.. confval:: epub_cover
+
+ The cover page information. This is a tuple containing the filenames of
+ the cover image and the html template. The rendered html cover page is
+ inserted as the first item in the spine in :file:`content.opf`. If the
+ template filename is empty, no html cover page is created. No cover at all
+ is created if the tuple is empty. Examples::
+
+ epub_cover = ('_static/cover.png', 'epub-cover.html')
+ epub_cover = ('_static/cover.png', '')
+ epub_cover = ()
+
+ The default value is ``()``.
+
+ .. versionadded:: 1.1
+
+.. confval:: epub_guide
+
+ Meta data for the guide element of :file:`content.opf`. This is a
+ sequence of tuples containing the *type*, the *uri* and the *title* of
+ the optional guide information. See the OPF documentation
+ at `<http://idpf.org/epub>`_ for details. If possible, default entries
+ for the *cover* and *toc* types are automatically inserted. However,
+ the types can be explicitely overwritten if the default entries are not
+ appropriate. Example::
+
+ epub_guide = (('cover', 'cover.html', u'Cover Page'),)
+
+ The default value is ``()``.
+
+.. confval:: epub_pre_files
+
+ Additional files that should be inserted before the text generated by
+ Sphinx. It is a list of tuples containing the file name and the title.
+ If the title is empty, no entry is added to :file:`toc.ncx`. Example::
+
+ epub_pre_files = [
+ ('index.html', 'Welcome'),
+ ]
+
+ The default value is ``[]``.
+
+.. confval:: epub_post_files
+
+ Additional files that should be inserted after the text generated by Sphinx.
+ It is a list of tuples containing the file name and the title. This option
+ can be used to add an appendix. If the title is empty, no entry is added
+ to :file:`toc.ncx`. The default value is ``[]``.
+
+.. confval:: epub_exclude_files
+
+ A list of files that are generated/copied in the build directory but should
+ not be included in the epub file. The default value is ``[]``.
+
+.. confval:: epub_tocdepth
+
+ The depth of the table of contents in the file :file:`toc.ncx`. It should
+ be an integer greater than zero. The default value is 3. Note: A deeply
+ nested table of contents may be difficult to navigate.
+
+.. confval:: epub_tocdup
+
+ This flag determines if a toc entry is inserted again at the beginning of
+ it's nested toc listing. This allows easier navitation to the top of
+ a chapter, but can be confusing because it mixes entries of differnet
+ depth in one list. The default value is ``True``.
+
+.. confval:: epub_tocscope
+
+ This setting control the scope of the epub table of contents. The setting
+ can have the following values:
+
+ * ``'default'`` -- include all toc entries that are not hidden (default)
+ * ``'includehidden'`` -- include all toc entries
+
+ .. versionadded:: 1.2
+
+.. confval:: epub_fix_images
+
+ This flag determines if sphinx should try to fix image formats that are not
+ supported by some epub readers. At the moment palette images with a small
+ color table are upgraded. You need the Python Image Library (PIL) installed
+ to use this option. The default value is ``False`` because the automatic
+ conversion may lose information.
+
+ .. versionadded:: 1.2
+
+.. confval:: epub_max_image_width
+
+ This option specifies the maximum width of images. If it is set to a value
+ greater than zero, images with a width larger than the given value are
+ scaled accordingly. If it is zero, no scaling is performed. The default
+ value is ``0``. You need the Python Image Library (PIL) installed to use
+ this option.
+
+ .. versionadded:: 1.2
+
+.. confval:: epub_show_urls
+
+ Control whether to display URL addresses. This is very useful for
+ readers that have no other means to display the linked URL. The
+ settings can have the following values:
+
+ * ``'inline'`` -- display URLs inline in parentheses (default)
+ * ``'footnote'`` -- display URLs in footnotes
+ * ``'no'`` -- do not display URLs
+
+ The display of inline URLs can be customized by adding CSS rules for the
+ class ``link-target``.
+
+ .. versionadded:: 1.2
+
+.. confval:: epub_use_index
+
+ If true, add an index to the epub document. It defaults to the
+ :confval:`html_use_index` option but can be set independently for epub
+ creation.
+
+ .. versionadded:: 1.2
+
+.. _latex-options:
+
+Options for LaTeX output
+------------------------
+
+These options influence LaTeX output.
+
+.. confval:: latex_documents
+
+ This value determines how to group the document tree into LaTeX source files.
+ It must be a list of tuples ``(startdocname, targetname, title, author,
+ documentclass, toctree_only)``, where the items are:
+
+ * *startdocname*: document name that is the "root" of the LaTeX file. All
+ documents referenced by it in TOC trees will be included in the LaTeX file
+ too. (If you want only one LaTeX file, use your :confval:`master_doc`
+ here.)
+ * *targetname*: file name of the LaTeX file in the output directory.
+ * *title*: LaTeX document title. Can be empty to use the title of the
+ *startdoc*. This is inserted as LaTeX markup, so special characters like a
+ backslash or ampersand must be represented by the proper LaTeX commands if
+ they are to be inserted literally.
+ * *author*: Author for the LaTeX document. The same LaTeX markup caveat as
+ for *title* applies. Use ``\and`` to separate multiple authors, as in:
+ ``'John \and Sarah'``.
+ * *documentclass*: Normally, one of ``'manual'`` or ``'howto'`` (provided by
+ Sphinx). Other document classes can be given, but they must include the
+ "sphinx" package in order to define Sphinx' custom LaTeX commands.
+ "howto" documents will not get appendices. Also, howtos will have a simpler
+ title page.
+
+ * *toctree_only*: Must be ``True`` or ``False``. If ``True``, the *startdoc*
+ document itself is not included in the output, only the documents
+ referenced by it via TOC trees. With this option, you can put extra stuff
+ in the master document that shows up in the HTML, but not the LaTeX output.
+
+ .. versionadded:: 1.2
+ In the past including your own document class required you to prepend the
+ document class name with the string "sphinx". This is not necessary
+ anymore.
+
+ .. versionadded:: 0.3
+ The 6th item ``toctree_only``. Tuples with 5 items are still accepted.
+
+.. confval:: latex_logo
+
+ If given, this must be the name of an image file (relative to the
+ configuration directory) that is the logo of the docs. It is placed at the
+ top of the title page. Default: ``None``.
+
+.. confval:: latex_use_parts
+
+ If true, the topmost sectioning unit is parts, else it is chapters. Default:
+ ``False``.
+
+ .. versionadded:: 0.3
+
+.. confval:: latex_appendices
+
+ A list of document names to append as an appendix to all manuals.
+
+.. confval:: latex_domain_indices
+
+ If true, generate domain-specific indices in addition to the general index.
+ For e.g. the Python domain, this is the global module index. Default is
+ ``True``.
+
+ This value can be a bool or a list of index names that should be generated,
+ like for :confval:`html_domain_indices`.
+
+ .. versionadded:: 1.0
+
+.. confval:: latex_use_modindex
+
+ If true, add a module index to LaTeX documents. Default is ``True``.
+
+ .. deprecated:: 1.0
+ Use :confval:`latex_domain_indices`.
+
+.. confval:: latex_show_pagerefs
+
+ If true, add page references after internal references. This is very useful
+ for printed copies of the manual. Default is ``False``.
+
+ .. versionadded:: 1.0
+
+.. confval:: latex_show_urls
+
+ Control whether to display URL addresses. This is very useful for printed
+ copies of the manual. The setting can have the following values:
+
+ * ``'no'`` -- do not display URLs (default)
+ * ``'footnote'`` -- display URLs in footnotes
+ * ``'inline'`` -- display URLs inline in parentheses
+
+ .. versionadded:: 1.0
+ .. versionchanged:: 1.1
+ This value is now a string; previously it was a boolean value, and a true
+ value selected the ``'inline'`` display. For backwards compatibility,
+ ``True`` is still accepted.
+
+.. confval:: latex_elements
+
+ .. versionadded:: 0.5
+
+ A dictionary that contains LaTeX snippets that override those Sphinx usually
+ puts into the generated ``.tex`` files.
+
+ Keep in mind that backslashes must be doubled in Python string literals to
+ avoid interpretation as escape sequences.
+
+ * Keys that you may want to override include:
+
+ ``'papersize'``
+ Paper size option of the document class (``'a4paper'`` or
+ ``'letterpaper'``), default ``'letterpaper'``.
+ ``'pointsize'``
+ Point size option of the document class (``'10pt'``, ``'11pt'`` or
+ ``'12pt'``), default ``'10pt'``.
+ ``'babel'``
+ "babel" package inclusion, default ``'\\usepackage{babel}'``.
+ ``'fontpkg'``
+ Font package inclusion, default ``'\\usepackage{times}'`` (which uses
+ Times and Helvetica). You can set this to ``''`` to use the Computer
+ Modern fonts.
+
+ .. versionchanged:: 1.2
+ Defaults to ``''`` when the :confval:`language` uses the Cyrillic
+ script.
+ ``'fncychap'``
+ Inclusion of the "fncychap" package (which makes fancy chapter titles),
+ default ``'\\usepackage[Bjarne]{fncychap}'`` for English documentation,
+ ``'\\usepackage[Sonny]{fncychap}'`` for internationalized docs (because
+ the "Bjarne" style uses numbers spelled out in English). Other
+ "fncychap" styles you can try include "Lenny", "Glenn", "Conny" and
+ "Rejne". You can also set this to ``''`` to disable fncychap.
+ ``'preamble'``
+ Additional preamble content, default empty.
+ ``'footer'``
+ Additional footer content (before the indices), default empty.
+
+ * Keys that don't need be overridden unless in special cases are:
+
+ ``'inputenc'``
+ "inputenc" package inclusion, default
+ ``'\\usepackage[utf8]{inputenc}'``.
+ ``'cmappkg'``
+ "cmap" package inclusion, default ``'\\usepackage{cmap}'``.
+
+ .. versionadded:: 1.2
+ ``'fontenc'``
+ "fontenc" package inclusion, default ``'\\usepackage[T1]{fontenc}'``.
+ ``'maketitle'``
+ "maketitle" call, default ``'\\maketitle'``. Override if you want to
+ generate a differently-styled title page.
+ ``'tableofcontents'``
+ "tableofcontents" call, default ``'\\tableofcontents'``. Override if
+ you want to generate a different table of contents or put content
+ between the title page and the TOC.
+ ``'transition'``
+ Commands used to display transitions, default
+ ``'\n\n\\bigskip\\hrule{}\\bigskip\n\n'``. Override if you want to
+ display transitions differently.
+
+ .. versionadded:: 1.2
+ ``'printindex'``
+ "printindex" call, the last thing in the file, default
+ ``'\\printindex'``. Override if you want to generate the index
+ differently or append some content after the index.
+
+ * Keys that are set by other options and therefore should not be overridden are:
+
+ ``'docclass'``
+ ``'classoptions'``
+ ``'title'``
+ ``'date'``
+ ``'release'``
+ ``'author'``
+ ``'logo'``
+ ``'releasename'``
+ ``'makeindex'``
+ ``'shorthandoff'``
+
+.. confval:: latex_docclass
+
+ A dictionary mapping ``'howto'`` and ``'manual'`` to names of real document
+ classes that will be used as the base for the two Sphinx classes. Default
+ is to use ``'article'`` for ``'howto'`` and ``'report'`` for ``'manual'``.
+
+ .. versionadded:: 1.0
+
+.. confval:: latex_additional_files
+
+ A list of file names, relative to the configuration directory, to copy to the
+ build directory when building LaTeX output. This is useful to copy files
+ that Sphinx doesn't copy automatically, e.g. if they are referenced in custom
+ LaTeX added in ``latex_elements``. Image files that are referenced in source
+ files (e.g. via ``.. image::``) are copied automatically.
+
+ You have to make sure yourself that the filenames don't collide with those of
+ any automatically copied files.
+
+ .. versionadded:: 0.6
+
+ .. versionchanged:: 1.2
+ This overrides the files which is provided from Sphinx such as sphinx.sty.
+
+.. confval:: latex_preamble
+
+ Additional LaTeX markup for the preamble.
+
+ .. deprecated:: 0.5
+ Use the ``'preamble'`` key in the :confval:`latex_elements` value.
+
+.. confval:: latex_paper_size
+
+ The output paper size (``'letter'`` or ``'a4'``). Default is ``'letter'``.
+
+ .. deprecated:: 0.5
+ Use the ``'papersize'`` key in the :confval:`latex_elements` value.
+
+.. confval:: latex_font_size
+
+ The font size ('10pt', '11pt' or '12pt'). Default is ``'10pt'``.
+
+ .. deprecated:: 0.5
+ Use the ``'pointsize'`` key in the :confval:`latex_elements` value.
+
+
+.. _text-options:
+
+Options for text output
+-----------------------
+
+These options influence text output.
+
+.. confval:: text_newlines
+
+ Determines which end-of-line character(s) are used in text output.
+
+ * ``'unix'``: use Unix-style line endings (``\n``)
+ * ``'windows'``: use Windows-style line endings (``\r\n``)
+ * ``'native'``: use the line ending style of the platform the documentation
+ is built on
+
+ Default: ``'unix'``.
+
+ .. versionadded:: 1.1
+
+.. confval:: text_sectionchars
+
+ A string of 7 characters that should be used for underlining sections.
+ The first character is used for first-level headings, the second for
+ second-level headings and so on.
+
+ The default is ``'*=-~"+`'``.
+
+ .. versionadded:: 1.1
+
+
+.. _man-options:
+
+Options for manual page output
+------------------------------
+
+These options influence manual page output.
+
+.. confval:: man_pages
+
+ This value determines how to group the document tree into manual pages. It
+ must be a list of tuples ``(startdocname, name, description, authors,
+ section)``, where the items are:
+
+ * *startdocname*: document name that is the "root" of the manual page. All
+ documents referenced by it in TOC trees will be included in the manual file
+ too. (If you want one master manual page, use your :confval:`master_doc`
+ here.)
+ * *name*: name of the manual page. This should be a short string without
+ spaces or special characters. It is used to determine the file name as
+ well as the name of the manual page (in the NAME section).
+ * *description*: description of the manual page. This is used in the NAME
+ section.
+ * *authors*: A list of strings with authors, or a single string. Can be an
+ empty string or list if you do not want to automatically generate an
+ AUTHORS section in the manual page.
+ * *section*: The manual page section. Used for the output file name as well
+ as in the manual page header.
+
+ .. versionadded:: 1.0
+
+.. confval:: man_show_urls
+
+ If true, add URL addresses after links. Default is ``False``.
+
+ .. versionadded:: 1.1
+
+
+.. _texinfo-options:
+
+Options for Texinfo output
+--------------------------
+
+These options influence Texinfo output.
+
+.. confval:: texinfo_documents
+
+ This value determines how to group the document tree into Texinfo source
+ files. It must be a list of tuples ``(startdocname, targetname, title,
+ author, dir_entry, description, category, toctree_only)``, where the items
+ are:
+
+ * *startdocname*: document name that is the "root" of the Texinfo file. All
+ documents referenced by it in TOC trees will be included in the Texinfo
+ file too. (If you want only one Texinfo file, use your
+ :confval:`master_doc` here.)
+ * *targetname*: file name (no extension) of the Texinfo file in the output
+ directory.
+ * *title*: Texinfo document title. Can be empty to use the title of the
+ *startdoc*. Inserted as Texinfo markup, so special characters like @ and
+ {} will need to be escaped to be inserted literally.
+ * *author*: Author for the Texinfo document. Inserted as Texinfo markup.
+ Use ``@*`` to separate multiple authors, as in: ``'John@*Sarah'``.
+ * *dir_entry*: The name that will appear in the top-level ``DIR`` menu file.
+ * *description*: Descriptive text to appear in the top-level ``DIR`` menu
+ file.
+ * *category*: Specifies the section which this entry will appear in the
+ top-level ``DIR`` menu file.
+ * *toctree_only*: Must be ``True`` or ``False``. If ``True``, the *startdoc*
+ document itself is not included in the output, only the documents
+ referenced by it via TOC trees. With this option, you can put extra stuff
+ in the master document that shows up in the HTML, but not the Texinfo
+ output.
+
+ .. versionadded:: 1.1
+
+.. confval:: texinfo_appendices
+
+ A list of document names to append as an appendix to all manuals.
+
+ .. versionadded:: 1.1
+
+.. confval:: texinfo_domain_indices
+
+ If true, generate domain-specific indices in addition to the general index.
+ For e.g. the Python domain, this is the global module index. Default is
+ ``True``.
+
+ This value can be a bool or a list of index names that should be generated,
+ like for :confval:`html_domain_indices`.
+
+ .. versionadded:: 1.1
+
+.. confval:: texinfo_show_urls
+
+ Control how to display URL addresses.
+
+ * ``'footnote'`` -- display URLs in footnotes (default)
+ * ``'no'`` -- do not display URLs
+ * ``'inline'`` -- display URLs inline in parentheses
+
+ .. versionadded:: 1.1
+
+.. confval:: texinfo_no_detailmenu
+
+ If true, do not generate a ``@detailmenu`` in the "Top" node's menu
+ containing entries for each sub-node in the document. Default is ``False``.
+
+ .. versionadded:: 1.2
+
+.. confval:: texinfo_elements
+
+ A dictionary that contains Texinfo snippets that override those Sphinx
+ usually puts into the generated ``.texi`` files.
+
+ * Keys that you may want to override include:
+
+ ``'paragraphindent'``
+ Number of spaces to indent the first line of each paragraph, default
+ ``2``. Specify ``0`` for no indentation.
+
+ ``'exampleindent'``
+ Number of spaces to indent the lines for examples or literal blocks,
+ default ``4``. Specify ``0`` for no indentation.
+
+ ``'preamble'``
+ Texinfo markup inserted near the beginning of the file.
+
+ ``'copying'``
+ Texinfo markup inserted within the ``@copying`` block and displayed
+ after the title. The default value consists of a simple title page
+ identifying the project.
+
+ * Keys that are set by other options and therefore should not be overridden
+ are:
+
+ ``'author'``
+ ``'body'``
+ ``'date'``
+ ``'direntry'``
+ ``'filename'``
+ ``'project'``
+ ``'release'``
+ ``'title'``
+ ``'direntry'``
+
+ .. versionadded:: 1.1
+
+
+Options for the linkcheck builder
+---------------------------------
+
+.. confval:: linkcheck_ignore
+
+ A list of regular expressions that match URIs that should not be checked
+ when doing a ``linkcheck`` build. Example::
+
+ linkcheck_ignore = [r'http://localhost:\d+/']
+
+ .. versionadded:: 1.1
+
+.. confval:: linkcheck_timeout
+
+ A timeout value, in seconds, for the linkcheck builder. **Only works in
+ Python 2.6 and higher.** The default is to use Python's global socket
+ timeout.
+
+ .. versionadded:: 1.1
+
+.. confval:: linkcheck_workers
+
+ The number of worker threads to use when checking links. Default is 5
+ threads.
+
+ .. versionadded:: 1.1
+
+.. confval:: linkcheck_anchors
+
+ True or false, whether to check the validity of ``#anchor``\ s in links.
+ Since this requires downloading the whole document, it's considerably slower
+ when enabled. Default is ``True``.
+
+ .. versionadded:: 1.2
+
+
+Options for the XML builder
+---------------------------
+
+.. confval:: xml_pretty
+
+ If True, pretty-print the XML. Default is ``True``.
+
+ .. versionadded:: 1.2
+
+
+.. rubric:: Footnotes
+
+.. [1] A note on available globbing syntax: you can use the standard shell
+ constructs ``*``, ``?``, ``[...]`` and ``[!...]`` with the feature that
+ these all don't match slashes. A double star ``**`` can be used to match
+ any sequence of characters *including* slashes.
diff --git a/doc/contents.rst b/doc/contents.rst
new file mode 100644
index 0000000..d3fd3c8
--- /dev/null
+++ b/doc/contents.rst
@@ -0,0 +1,37 @@
+.. _contents:
+
+Sphinx documentation contents
+=============================
+
+.. toctree::
+ :maxdepth: 2
+
+ intro
+ tutorial
+ invocation
+ rest
+ markup/index
+ domains
+ builders
+ config
+ intl
+ theming
+ templating
+ extensions
+ extdev/index
+ websupport
+
+ faq
+ glossary
+ devguide
+ changes
+ examples
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+* :ref:`glossary`
diff --git a/doc/develop.rst b/doc/develop.rst
new file mode 100644
index 0000000..aad3ff1
--- /dev/null
+++ b/doc/develop.rst
@@ -0,0 +1,133 @@
+:orphan:
+
+Sphinx development
+==================
+
+Sphinx is a maintained by a group of volunteers. We value every contribution!
+
+* The code can be found in a Mercurial repository, at
+ https://bitbucket.org/birkenfeld/sphinx/.
+* Issues and feature requests should be raised in the `tracker
+ <https://bitbucket.org/birkenfeld/sphinx/issues/>`_.
+* The mailing list for development is at `Google Groups
+ <https://groups.google.com/group/sphinx-dev/>`_.
+* There is also the #sphinx-doc IRC channel on `freenode
+ <http://freenode.net/>`_.
+
+For more about our development process and methods, see the :doc:`devguide`.
+
+Extensions
+==========
+
+To learn how to write your own extension, see :ref:`dev-extensions`.
+
+The `sphinx-contrib <http://bitbucket.org/birkenfeld/sphinx-contrib/>`_
+repository contains many contributed extensions. Some of them have their own
+releases on PyPI, others you can install from a checkout.
+
+This is the current list of contributed extensions in that repository:
+
+- aafig: render embedded ASCII art as nice images using aafigure_.
+- actdiag: embed activity diagrams by using actdiag_
+- adadomain: an extension for Ada support (Sphinx 1.0 needed)
+- ansi: parse ANSI color sequences inside documents
+- autorun: Execute code in a ``runblock`` directive.
+- blockdiag: embed block diagrams by using blockdiag_
+- cheeseshop: easily link to PyPI packages
+- clearquest: create tables from ClearQuest_ queries.
+- cmakedomain_: a domain for CMake_
+- coffeedomain: a domain for (auto)documenting CoffeeScript source code.
+- context: a builder for ConTeXt.
+- doxylink: Link to external Doxygen-generated HTML documentation
+- domaintools_: A tool for easy domain creation.
+- email: obfuscate email addresses
+- erlangdomain: an extension for Erlang support (Sphinx 1.0 needed)
+- exceltable: embed Excel spreadsheets into documents using exceltable_
+- feed: an extension for creating syndication feeds and time-based overviews
+ from your site content
+- findanything_: an extension to add Sublime Text 2-like findanything panels
+ to your documentation to find pages, sections and index entries while typing
+- gnuplot: produces images using gnuplot_ language.
+- googleanalytics: track web visitor statistics by using `Google Analytics`_
+- googlechart: embed charts by using `Google Chart`_
+- googlemaps: embed maps by using `Google Maps`_
+- httpdomain: a domain for documenting RESTful HTTP APIs.
+- hyphenator: client-side hyphenation of HTML using hyphenator_
+- inlinesyntaxhighlight_: inline syntax highlighting
+- lassodomain: a domain for documenting Lasso_ source code
+- lilypond: an extension inserting music scripts from Lilypond_ in PNG format.
+- makedomain_: a domain for `GNU Make`_
+- matlabdomain: document MATLAB_ code.
+- mockautodoc: mock imports.
+- mscgen: embed mscgen-formatted MSC (Message Sequence Chart)s.
+- napoleon: supports `Google style`_ and `NumPy style`_ docstrings.
+- nicoviceo: embed videos from nicovideo
+- nwdiag: embed network diagrams by using nwdiag_
+- omegat: support tools to collaborate with OmegaT_ (Sphinx 1.1 needed)
+- osaka: convert standard Japanese doc to Osaka dialect (it is joke extension)
+- paverutils: an alternate integration of Sphinx with Paver_.
+- phpdomain: an extension for PHP support
+- plantuml: embed UML diagram by using PlantUML_
+- py_directive: Execute python code in a ``py`` directive and return a math node.
+- rawfiles: copy raw files, like a CNAME.
+- requirements: declare requirements wherever you need (e.g. in test
+ docstrings), mark statuses and collect them in a single list
+- restbuilder: a builder for reST (reStructuredText) files.
+- rubydomain: an extension for Ruby support (Sphinx 1.0 needed)
+- sadisplay: display SqlAlchemy model sadisplay_
+- sdedit: an extension inserting sequence diagram by using Quick Sequence
+ Diagram Editor (sdedit_)
+- seqdiag: embed sequence diagrams by using seqdiag_
+- slide: embed presentation slides on slideshare_ and other sites.
+- swf_: embed flash files
+- sword: an extension inserting Bible verses from Sword_.
+- tikz: draw pictures with the `TikZ/PGF LaTeX package`_.
+- traclinks: create TracLinks_ to a Trac_ instance from within Sphinx
+- whooshindex: whoosh indexer extension
+- youtube: embed videos from YouTube_
+- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_.
+
+
+See the :ref:`extension tutorial <exttut>` on getting started with writing your
+own extensions.
+
+
+.. _aafigure: https://launchpad.net/aafigure
+.. _gnuplot: http://www.gnuplot.info/
+.. _paver: http://www.blueskyonmars.com/projects/paver/
+.. _Sword: http://www.crosswire.org/sword/
+.. _Lilypond: http://lilypond.org/
+.. _sdedit: http://sdedit.sourceforge.net/
+.. _Trac: http://trac.edgewall.org
+.. _TracLinks: http://trac.edgewall.org/wiki/TracLinks
+.. _OmegaT: http://www.omegat.org/
+.. _PlantUML: http://plantuml.sourceforge.net/
+.. _PyEnchant: http://www.rfk.id.au/software/pyenchant/
+.. _sadisplay: https://bitbucket.org/estin/sadisplay/wiki/Home
+.. _blockdiag: http://blockdiag.com/en/
+.. _seqdiag: http://blockdiag.com/en/
+.. _actdiag: http://blockdiag.com/en/
+.. _nwdiag: http://blockdiag.com/en/
+.. _Google Analytics: http://www.google.com/analytics/
+.. _Google Chart: https://developers.google.com/chart/
+.. _Google Maps: https://maps.google.com/
+.. _Google style: http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
+.. _NumPy style: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
+.. _hyphenator: http://code.google.com/p/hyphenator/
+.. _exceltable: http://pythonhosted.org/sphinxcontrib-exceltable/
+.. _YouTube: http://www.youtube.com/
+.. _ClearQuest: http://www-03.ibm.com/software/products/en/clearquest
+.. _Zope interfaces: http://docs.zope.org/zope.interface/README.html
+.. _slideshare: http://www.slideshare.net/
+.. _TikZ/PGF LaTeX package: http://sourceforge.net/projects/pgf/
+.. _MATLAB: http://www.mathworks.com/products/matlab/
+.. _swf: http://bitbucket.org/klorenz/sphinxcontrib-swf
+.. _findanything: http://bitbucket.org/klorenz/sphinxcontrib-findanything
+.. _cmakedomain: http://bitbucket.org/klorenz/sphinxcontrib-cmakedomain
+.. _GNU Make: http://www.gnu.org/software/make/
+.. _makedomain: http://bitbucket.org/klorenz/sphinxcontrib-makedomain
+.. _inlinesyntaxhighlight: http://sphinxcontrib-inlinesyntaxhighlight.readthedocs.org
+.. _CMake: http://cmake.org
+.. _domaintools: http://bitbucket.org/klorenz/sphinxcontrib-domaintools
+.. _restbuilder: https://pypi.python.org/pypi/sphinxcontrib-restbuilder
+.. _Lasso: http://www.lassosoft.com/
diff --git a/doc/devguide.rst b/doc/devguide.rst
new file mode 100644
index 0000000..fccdd3f
--- /dev/null
+++ b/doc/devguide.rst
@@ -0,0 +1,245 @@
+Sphinx Developer's Guide
+========================
+
+.. topic:: Abstract
+
+ This document describes the development process of Sphinx, a documentation
+ system used by developers to document systems used by other developers to
+ develop other systems that may also be documented using Sphinx.
+
+The Sphinx source code is managed using `Mercurial`_ and is hosted on
+`BitBucket`_.
+
+ hg clone https://bitbucket.org/birkenfeld/sphinx
+
+.. rubric:: Community
+
+sphinx-users <sphinx-users at googlegroups.com>
+ Mailing list for user support.
+
+sphinx-dev <sphinx-dev at googlegroups.com>
+ Mailing list for development related discussions.
+
+#sphinx-doc on irc.freenode.net
+ IRC channel for development questions and user support.
+
+.. _`BitBucket`: https://bitbucket.org/
+.. _`Mercurial`: http://mercurial.selenic.com/
+
+
+Bug Reports and Feature Requests
+--------------------------------
+
+If you have encountered a problem with Sphinx or have an idea for a new
+feature, please submit it to the `issue tracker`_ on BitBucket or discuss it
+on the sphinx-dev mailing list.
+
+For bug reports, please include the output produced during the build process
+and also the log file Sphinx creates after it encounters an un-handled
+exception. The location of this file should be shown towards the end of the
+error message.
+
+Including or providing a link to the source files involved may help us fix the
+issue. If possible, try to create a minimal project that produces the error
+and post that instead.
+
+.. _`issue tracker`: https://bitbucket.org/birkenfeld/sphinx/issues
+
+
+Contributing to Sphinx
+----------------------
+
+The recommended way for new contributors to submit code to Sphinx is to fork
+the Mercurial repository on BitBucket and then submit a pull request after
+committing the changes. The pull request will then need to be approved by one
+of the core developers before it is merged into the main repository.
+
+
+Getting Started
+~~~~~~~~~~~~~~~
+
+These are the basic steps needed to start developing on Sphinx.
+
+#. Create an account on BitBucket.
+
+#. Fork the main Sphinx repository (`birkenfeld/sphinx
+ <https://bitbucket.org/birkenfeld/sphinx>`_) using the BitBucket interface.
+
+#. Clone the forked repository to your machine. ::
+
+ hg clone https://bitbucket.org/USERNAME/sphinx-fork
+ cd sphinx-fork
+
+#. Checkout the appropriate branch.
+
+ For changes that should be included in the next minor release (namely bug
+ fixes), use the ``stable`` branch. ::
+
+ hg checkout stable
+
+ For new features or other substantial changes that should wait until the
+ next major release, use the ``default`` branch.
+
+#. Optional: setup a virtual environment. ::
+
+ virtualenv ~/sphinxenv
+ . ~/sphinxenv/bin/activate
+ pip install -e .
+
+#. Hack, hack, hack.
+
+ For tips on working with the code, see the `Coding Guide`_.
+
+#. Test, test, test. Possible steps:
+
+ * Run the unit tests::
+
+ pip install nose mock
+ make test
+
+ * Build the documentation and check the output for different builders::
+
+ cd doc
+ make clean html latexpdf
+
+ * Run the unit tests under different Python environments using
+ :program:`tox`::
+
+ pip install tox
+ tox -v
+
+ * Add a new unit test in the ``tests`` directory if you can.
+
+ * For bug fixes, first add a test that fails without your changes and passes
+ after they are applied.
+
+#. Please add a bullet point to :file:`CHANGES` if the fix or feature is not trivial
+ (small doc updates, typo fixes). Then commit::
+
+ hg commit -m '#42: Add useful new feature that does this.'
+
+ BitBucket recognizes `certain phrases`__ that can be used to automatically
+ update the issue tracker.
+
+ For example::
+
+ hg commit -m 'Closes #42: Fix invalid markup in docstring of Foo.bar.'
+
+ would close issue #42.
+
+ __ https://confluence.atlassian.com/display/BITBUCKET/Resolve+issues+automatically+when+users+push+code
+
+#. Push changes to your forked repository on BitBucket. ::
+
+ hg push
+
+#. Submit a pull request from your repository to ``birkenfeld/sphinx`` using
+ the BitBucket interface.
+
+#. Wait for a core developer to review your changes.
+
+
+Core Developers
+~~~~~~~~~~~~~~~
+
+The core developers of Sphinx have write access to the main repository. They
+can commit changes, accept/reject pull requests, and manage items on the issue
+tracker.
+
+You do not need to be a core developer or have write access to be involved in
+the development of Sphinx. You can submit patches or create pull requests
+from forked repositories and have a core developer add the changes for you.
+
+The following are some general guidelines for core developers:
+
+* Questionable or extensive changes should be submitted as a pull request
+ instead of being committed directly to the main repository. The pull
+ request should be reviewed by another core developer before it is merged.
+
+* Trivial changes can be committed directly but be sure to keep the repository
+ in a good working state and that all tests pass before pushing your changes.
+
+* When committing code written by someone else, please attribute the original
+ author in the commit message and any relevant :file:`CHANGES` entry.
+
+* Using Mercurial named branches other than ``default`` and ``stable`` is not
+ encouraged.
+
+
+Locale updates
+~~~~~~~~~~~~~~
+
+The parts of messages in Sphinx that go into builds are translated into several
+locales. The translations are kept as gettext ``.po`` files translated from the
+master template ``sphinx/locale/sphinx.pot``.
+
+Sphinx uses `Babel <http://babel.edgewall.org>`_ to extract messages and
+maintain the catalog files. It is integrated in ``setup.py``:
+
+* Use ``python setup.py extract_messages`` to update the ``.pot`` template.
+* Use ``python setup.py update_catalog`` to update all existing language
+ catalogs in ``sphinx/locale/*/LC_MESSAGES`` with the current messages in the
+ template file.
+* Use ``python setup.py compile_catalog`` to compile the ``.po`` files to binary
+ ``.mo`` files and ``.js`` files.
+
+When an updated ``.po`` file is submitted, run compile_catalog to commit both
+the source and the compiled catalogs.
+
+When a new locale is submitted, add a new directory with the ISO 639-1 language
+identifier and put ``sphinx.po`` in there. Don't forget to update the possible
+values for :confval:`language` in ``doc/config.rst``.
+
+The Sphinx core messages can also be translated on `Transifex
+<https://www.transifex.com/>`_. There exists a client tool named ``tx`` in the Python
+package "transifex_client", which can be used to pull translations in ``.po``
+format from Transifex. To do this, go to ``sphinx/locale`` and then run
+``tx pull -f -l LANG`` where LANG is an existing language identifier. It is
+good practice to run ``python setup.py update_catalog`` afterwards to make sure
+the ``.po`` file has the canonical Babel formatting.
+
+
+Coding Guide
+------------
+
+* Try to use the same code style as used in the rest of the project. See the
+ `Pocoo Styleguide`__ for more information.
+
+ __ http://flask.pocoo.org/docs/styleguide/
+
+* For non-trivial changes, please update the :file:`CHANGES` file. If your
+ changes alter existing behavior, please document this.
+
+* New features should be documented. Include examples and use cases where
+ appropriate. If possible, include a sample that is displayed in the
+ generated output.
+
+* When adding a new configuration variable, be sure to document it and update
+ :file:`sphinx/quickstart.py` if it's important enough.
+
+* Use the included :program:`utils/check_sources.py` script to check for
+ common formatting issues (trailing whitespace, lengthy lines, etc).
+
+* Add appropriate unit tests.
+
+
+Debugging Tips
+~~~~~~~~~~~~~~
+
+* Delete the build cache before building documents if you make changes in the
+ code by running the command ``make clean`` or using the
+ :option:`sphinx-build -E` option.
+
+* Use the :option:`sphinx-build -P` option to run Pdb on exceptions.
+
+* Use ``node.pformat()`` and ``node.asdom().toxml()`` to generate a printable
+ representation of the document structure.
+
+* Set the configuration variable :confval:`keep_warnings` to True so warnings
+ will be displayed in the generated output.
+
+* Set the configuration variable :confval:`nitpicky` to True so that Sphinx
+ will complain about references without a known target.
+
+* Set the debugging options in the `Docutils configuration file
+ <http://docutils.sourceforge.net/docs/user/config.html>`_.
diff --git a/doc/domains.rst b/doc/domains.rst
new file mode 100644
index 0000000..4b5a903
--- /dev/null
+++ b/doc/domains.rst
@@ -0,0 +1,848 @@
+.. highlight:: rst
+
+.. _domains:
+
+Sphinx Domains
+==============
+
+.. versionadded:: 1.0
+
+What is a Domain?
+-----------------
+
+Originally, Sphinx was conceived for a single project, the documentation of the
+Python language. Shortly afterwards, it was made available for everyone as a
+documentation tool, but the documentation of Python modules remained deeply
+built in -- the most fundamental directives, like ``function``, were designed
+for Python objects. Since Sphinx has become somewhat popular, interest
+developed in using it for many different purposes: C/C++ projects, JavaScript,
+or even reStructuredText markup (like in this documentation).
+
+While this was always possible, it is now much easier to easily support
+documentation of projects using different programming languages or even ones not
+supported by the main Sphinx distribution, by providing a **domain** for every
+such purpose.
+
+A domain is a collection of markup (reStructuredText :term:`directive`\ s and
+:term:`role`\ s) to describe and link to :term:`object`\ s belonging together,
+e.g. elements of a programming language. Directive and role names in a domain
+have names like ``domain:name``, e.g. ``py:function``. Domains can also provide
+custom indices (like the Python Module Index).
+
+Having domains means that there are no naming problems when one set of
+documentation wants to refer to e.g. C++ and Python classes. It also means that
+extensions that support the documentation of whole new languages are much easier
+to write.
+
+This section describes what the domains that come with Sphinx provide. The
+domain API is documented as well, in the section :ref:`domain-api`.
+
+
+.. _basic-domain-markup:
+
+Basic Markup
+------------
+
+Most domains provide a number of :dfn:`object description directives`, used to
+describe specific objects provided by modules. Each directive requires one or
+more signatures to provide basic information about what is being described, and
+the content should be the description. The basic version makes entries in the
+general index; if no index entry is desired, you can give the directive option
+flag ``:noindex:``. An example using a Python domain directive::
+
+ .. py:function:: spam(eggs)
+ ham(eggs)
+
+ Spam or ham the foo.
+
+This describes the two Python functions ``spam`` and ``ham``. (Note that when
+signatures become too long, you can break them if you add a backslash to lines
+that are continued in the next line. Example::
+
+ .. py:function:: filterwarnings(action, message='', category=Warning, \
+ module='', lineno=0, append=False)
+ :noindex:
+
+(This example also shows how to use the ``:noindex:`` flag.)
+
+The domains also provide roles that link back to these object descriptions. For
+example, to link to one of the functions described in the example above, you
+could say ::
+
+ The function :py:func:`spam` does a similar thing.
+
+As you can see, both directive and role names contain the domain name and the
+directive name.
+
+.. rubric:: Default Domain
+
+To avoid having to writing the domain name all the time when you e.g. only
+describe Python objects, a default domain can be selected with either the config
+value :confval:`primary_domain` or this directive:
+
+.. rst:directive:: .. default-domain:: name
+
+ Select a new default domain. While the :confval:`primary_domain` selects a
+ global default, this only has an effect within the same file.
+
+If no other default is selected, the Python domain (named ``py``) is the default
+one, mostly for compatibility with documentation written for older versions of
+Sphinx.
+
+Directives and roles that belong to the default domain can be mentioned without
+giving the domain name, i.e. ::
+
+ .. function:: pyfunc()
+
+ Describes a Python function.
+
+ Reference to :func:`pyfunc`.
+
+
+Cross-referencing syntax
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+For cross-reference roles provided by domains, the same facilities exist as for
+general cross-references. See :ref:`xref-syntax`.
+
+In short:
+
+* You may supply an explicit title and reference target: ``:role:`title
+ <target>``` will refer to *target*, but the link text will be *title*.
+
+* If you prefix the content with ``!``, no reference/hyperlink will be created.
+
+* If you prefix the content with ``~``, the link text will only be the last
+ component of the target. For example, ``:py:meth:`~Queue.Queue.get``` will
+ refer to ``Queue.Queue.get`` but only display ``get`` as the link text.
+
+
+The Python Domain
+-----------------
+
+The Python domain (name **py**) provides the following directives for module
+declarations:
+
+.. rst:directive:: .. py:module:: name
+
+ This directive marks the beginning of the description of a module (or package
+ submodule, in which case the name should be fully qualified, including the
+ package name). It does not create content (like e.g. :rst:dir:`py:class` does).
+
+ This directive will also cause an entry in the global module index.
+
+ The ``platform`` option, if present, is a comma-separated list of the
+ platforms on which the module is available (if it is available on all
+ platforms, the option should be omitted). The keys are short identifiers;
+ examples that are in use include "IRIX", "Mac", "Windows", and "Unix". It is
+ important to use a key which has already been used when applicable.
+
+ The ``synopsis`` option should consist of one sentence describing the
+ module's purpose -- it is currently only used in the Global Module Index.
+
+ The ``deprecated`` option can be given (with no value) to mark a module as
+ deprecated; it will be designated as such in various locations then.
+
+
+.. rst:directive:: .. py:currentmodule:: name
+
+ This directive tells Sphinx that the classes, functions etc. documented from
+ here are in the given module (like :rst:dir:`py:module`), but it will not
+ create index entries, an entry in the Global Module Index, or a link target
+ for :rst:role:`py:mod`. This is helpful in situations where documentation
+ for things in a module is spread over multiple files or sections -- one
+ location has the :rst:dir:`py:module` directive, the others only
+ :rst:dir:`py:currentmodule`.
+
+
+The following directives are provided for module and class contents:
+
+.. rst:directive:: .. py:data:: name
+
+ Describes global data in a module, including both variables and values used
+ as "defined constants." Class and object attributes are not documented
+ using this environment.
+
+.. rst:directive:: .. py:exception:: name
+
+ Describes an exception class. The signature can, but need not include
+ parentheses with constructor arguments.
+
+.. rst:directive:: .. py:function:: name(parameters)
+
+ Describes a module-level function. The signature should include the
+ parameters as given in the Python function definition, see :ref:`signatures`.
+ For example::
+
+ .. py:function:: Timer.repeat(repeat=3, number=1000000)
+
+ For methods you should use :rst:dir:`py:method`.
+
+ The description should include information about the parameters required and
+ how they are used (especially whether mutable objects passed as parameters
+ are modified), side effects, and possible exceptions. This information can
+ optionally be given in a structured form, see :ref:`info-field-lists`. A
+ small example may be provided.
+
+.. rst:directive:: .. py:class:: name
+ .. py:class:: name(parameters)
+
+ Describes a class. The signature can optionally include parentheses with
+ parameters which will be shown as the constructor arguments. See also
+ :ref:`signatures`.
+
+ Methods and attributes belonging to the class should be placed in this
+ directive's body. If they are placed outside, the supplied name should
+ contain the class name so that cross-references still work. Example::
+
+ .. py:class:: Foo
+
+ .. py:method:: quux()
+
+ -- or --
+
+ .. py:class:: Bar
+
+ .. py:method:: Bar.quux()
+
+ The first way is the preferred one.
+
+.. rst:directive:: .. py:attribute:: name
+
+ Describes an object data attribute. The description should include
+ information about the type of the data to be expected and whether it may be
+ changed directly.
+
+.. rst:directive:: .. py:method:: name(parameters)
+
+ Describes an object method. The parameters should not include the ``self``
+ parameter. The description should include similar information to that
+ described for ``function``. See also :ref:`signatures` and
+ :ref:`info-field-lists`.
+
+.. rst:directive:: .. py:staticmethod:: name(parameters)
+
+ Like :rst:dir:`py:method`, but indicates that the method is a static method.
+
+ .. versionadded:: 0.4
+
+.. rst:directive:: .. py:classmethod:: name(parameters)
+
+ Like :rst:dir:`py:method`, but indicates that the method is a class method.
+
+ .. versionadded:: 0.6
+
+.. rst:directive:: .. py:decorator:: name
+ .. py:decorator:: name(parameters)
+
+ Describes a decorator function. The signature should represent the usage as
+ a decorator. For example, given the functions
+
+ .. code-block:: python
+
+ def removename(func):
+ func.__name__ = ''
+ return func
+
+ def setnewname(name):
+ def decorator(func):
+ func.__name__ = name
+ return func
+ return decorator
+
+ the descriptions should look like this::
+
+ .. py:decorator:: removename
+
+ Remove name of the decorated function.
+
+ .. py:decorator:: setnewname(name)
+
+ Set name of the decorated function to *name*.
+
+ (as opposed to ``.. py:decorator:: removename(func)``.)
+
+ There is no ``py:deco`` role to link to a decorator that is marked up with
+ this directive; rather, use the :rst:role:`py:func` role.
+
+.. rst:directive:: .. py:decoratormethod:: name
+ .. py:decoratormethod:: name(signature)
+
+ Same as :rst:dir:`py:decorator`, but for decorators that are methods.
+
+ Refer to a decorator method using the :rst:role:`py:meth` role.
+
+
+.. _signatures:
+
+Python Signatures
+~~~~~~~~~~~~~~~~~
+
+Signatures of functions, methods and class constructors can be given like they
+would be written in Python.
+
+Default values for optional arguments can be given (but if they contain commas,
+they will confuse the signature parser). Python 3-style argument annotations
+can also be given as well as return type annotations::
+
+ .. py:function:: compile(source : string, filename, symbol='file') -> ast object
+
+For functions with optional parameters that don't have default values (typically
+functions implemented in C extension modules without keyword argument support),
+you can use brackets to specify the optional parts:
+
+ .. py:function:: compile(source[, filename[, symbol]])
+
+It is customary to put the opening bracket before the comma.
+
+
+.. _info-field-lists:
+
+Info field lists
+~~~~~~~~~~~~~~~~
+
+.. versionadded:: 0.4
+
+Inside Python object description directives, reST field lists with these fields
+are recognized and formatted nicely:
+
+* ``param``, ``parameter``, ``arg``, ``argument``, ``key``, ``keyword``:
+ Description of a parameter.
+* ``type``: Type of a parameter.
+* ``raises``, ``raise``, ``except``, ``exception``: That (and when) a specific
+ exception is raised.
+* ``var``, ``ivar``, ``cvar``: Description of a variable.
+* ``returns``, ``return``: Description of the return value.
+* ``rtype``: Return type.
+
+The field names must consist of one of these keywords and an argument (except
+for ``returns`` and ``rtype``, which do not need an argument). This is best
+explained by an example::
+
+ .. py:function:: send_message(sender, recipient, message_body, [priority=1])
+
+ Send a message to a recipient
+
+ :param str sender: The person sending the message
+ :param str recipient: The recipient of the message
+ :param str message_body: The body of the message
+ :param priority: The priority of the message, can be a number 1-5
+ :type priority: integer or None
+ :return: the message id
+ :rtype: int
+ :raises ValueError: if the message_body exceeds 160 characters
+ :raises TypeError: if the message_body is not a basestring
+
+This will render like this:
+
+ .. py:function:: send_message(sender, recipient, message_body, [priority=1])
+ :noindex:
+
+ Send a message to a recipient
+
+ :param str sender: The person sending the message
+ :param str recipient: The recipient of the message
+ :param str message_body: The body of the message
+ :param priority: The priority of the message, can be a number 1-5
+ :type priority: integer or None
+ :return: the message id
+ :rtype: int
+ :raises ValueError: if the message_body exceeds 160 characters
+ :raises TypeError: if the message_body is not a basestring
+
+It is also possible to combine parameter type and description, if the type is a
+single word, like this::
+
+ :param int priority: The priority of the message, can be a number 1-5
+
+
+.. _python-roles:
+
+Cross-referencing Python objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following roles refer to objects in modules and are possibly hyperlinked if
+a matching identifier is found:
+
+.. rst:role:: py:mod
+
+ Reference a module; a dotted name may be used. This should also be used for
+ package names.
+
+.. rst:role:: py:func
+
+ Reference a Python function; dotted names may be used. The role text needs
+ not include trailing parentheses to enhance readability; they will be added
+ automatically by Sphinx if the :confval:`add_function_parentheses` config
+ value is true (the default).
+
+.. rst:role:: py:data
+
+ Reference a module-level variable.
+
+.. rst:role:: py:const
+
+ Reference a "defined" constant. This may be a Python variable that is not
+ intended to be changed.
+
+.. rst:role:: py:class
+
+ Reference a class; a dotted name may be used.
+
+.. rst:role:: py:meth
+
+ Reference a method of an object. The role text can include the type name and
+ the method name; if it occurs within the description of a type, the type name
+ can be omitted. A dotted name may be used.
+
+.. rst:role:: py:attr
+
+ Reference a data attribute of an object.
+
+.. rst:role:: py:exc
+
+ Reference an exception. A dotted name may be used.
+
+.. rst:role:: py:obj
+
+ Reference an object of unspecified type. Useful e.g. as the
+ :confval:`default_role`.
+
+ .. versionadded:: 0.4
+
+The name enclosed in this markup can include a module name and/or a class name.
+For example, ``:py:func:`filter``` could refer to a function named ``filter`` in
+the current module, or the built-in function of that name. In contrast,
+``:py:func:`foo.filter``` clearly refers to the ``filter`` function in the
+``foo`` module.
+
+Normally, names in these roles are searched first without any further
+qualification, then with the current module name prepended, then with the
+current module and class name (if any) prepended. If you prefix the name with a
+dot, this order is reversed. For example, in the documentation of Python's
+:mod:`codecs` module, ``:py:func:`open``` always refers to the built-in
+function, while ``:py:func:`.open``` refers to :func:`codecs.open`.
+
+A similar heuristic is used to determine whether the name is an attribute of the
+currently documented class.
+
+Also, if the name is prefixed with a dot, and no exact match is found, the
+target is taken as a suffix and all object names with that suffix are
+searched. For example, ``:py:meth:`.TarFile.close``` references the
+``tarfile.TarFile.close()`` function, even if the current module is not
+``tarfile``. Since this can get ambiguous, if there is more than one possible
+match, you will get a warning from Sphinx.
+
+Note that you can combine the ``~`` and ``.`` prefixes:
+``:py:meth:`~.TarFile.close``` will reference the ``tarfile.TarFile.close()``
+method, but the visible link caption will only be ``close()``.
+
+
+.. _c-domain:
+
+The C Domain
+------------
+
+The C domain (name **c**) is suited for documentation of C API.
+
+.. rst:directive:: .. c:function:: type name(signature)
+
+ Describes a C function. The signature should be given as in C, e.g.::
+
+ .. c:function:: PyObject* PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
+
+ This is also used to describe function-like preprocessor macros. The names
+ of the arguments should be given so they may be used in the description.
+
+ Note that you don't have to backslash-escape asterisks in the signature, as
+ it is not parsed by the reST inliner.
+
+.. rst:directive:: .. c:member:: type name
+
+ Describes a C struct member. Example signature::
+
+ .. c:member:: PyObject* PyTypeObject.tp_bases
+
+ The text of the description should include the range of values allowed, how
+ the value should be interpreted, and whether the value can be changed.
+ References to structure members in text should use the ``member`` role.
+
+.. rst:directive:: .. c:macro:: name
+
+ Describes a "simple" C macro. Simple macros are macros which are used for
+ code expansion, but which do not take arguments so cannot be described as
+ functions. This is a simple C-language ``#define``. Examples of its use in
+ the Python documentation include :c:macro:`PyObject_HEAD` and
+ :c:macro:`Py_BEGIN_ALLOW_THREADS`.
+
+.. rst:directive:: .. c:type:: name
+
+ Describes a C type (whether defined by a typedef or struct). The signature
+ should just be the type name.
+
+.. rst:directive:: .. c:var:: type name
+
+ Describes a global C variable. The signature should include the type, such
+ as::
+
+ .. c:var:: PyObject* PyClass_Type
+
+
+.. _c-roles:
+
+Cross-referencing C constructs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following roles create cross-references to C-language constructs if they are
+defined in the documentation:
+
+.. rst:role:: c:data
+
+ Reference a C-language variable.
+
+.. rst:role:: c:func
+
+ Reference a C-language function. Should include trailing parentheses.
+
+.. rst:role:: c:macro
+
+ Reference a "simple" C macro, as defined above.
+
+.. rst:role:: c:type
+
+ Reference a C-language type.
+
+
+The C++ Domain
+--------------
+
+The C++ domain (name **cpp**) supports documenting C++ projects.
+
+The following directives are available:
+
+.. rst:directive:: .. cpp:class:: signatures
+ .. cpp:function:: signatures
+ .. cpp:member:: signatures
+ .. cpp:type:: signatures
+
+ Describe a C++ object. Full signature specification is supported -- give the
+ signature as you would in the declaration. Here some examples::
+
+ .. cpp:function:: bool namespaced::theclass::method(int arg1, std::string arg2)
+
+ Describes a method with parameters and types.
+
+ .. cpp:function:: bool namespaced::theclass::method(arg1, arg2)
+
+ Describes a method without types.
+
+ .. cpp:function:: const T &array<T>::operator[]() const
+
+ Describes the constant indexing operator of a templated array.
+
+ .. cpp:function:: operator bool() const
+
+ Describe a casting operator here.
+
+ .. cpp:function:: constexpr void foo(std::string &bar[2]) noexcept
+
+ Describe a constexpr function here.
+
+ .. cpp:member:: std::string theclass::name
+
+ .. cpp:member:: std::string theclass::name[N][M]
+
+ .. cpp:type:: theclass::const_iterator
+
+ Will be rendered like this:
+
+ .. cpp:function:: bool namespaced::theclass::method(int arg1, std::string arg2)
+
+ Describes a method with parameters and types.
+
+ .. cpp:function:: bool namespaced::theclass::method(arg1, arg2)
+
+ Describes a method without types.
+
+ .. cpp:function:: const T &array<T>::operator[]() const
+
+ Describes the constant indexing operator of a templated array.
+
+ .. cpp:function:: operator bool() const
+
+ Describe a casting operator here.
+
+ .. cpp:function:: constexpr void foo(std::string &bar[2]) noexcept
+
+ Describe a constexpr function here.
+
+ .. cpp:member:: std::string theclass::name
+
+ .. cpp:member:: std::string theclass::name[N][M]
+
+ .. cpp:type:: theclass::const_iterator
+
+.. rst:directive:: .. cpp:namespace:: namespace
+
+ Select the current C++ namespace for the following objects.
+
+
+.. _cpp-roles:
+
+These roles link to the given object types:
+
+.. rst:role:: cpp:class
+ cpp:func
+ cpp:member
+ cpp:type
+
+ Reference a C++ object. You can give the full signature (and need to, for
+ overloaded functions.)
+
+ .. note::
+
+ Sphinx' syntax to give references a custom title can interfere with
+ linking to template classes, if nothing follows the closing angle
+ bracket, i.e. if the link looks like this: ``:cpp:class:`MyClass<T>```.
+ This is interpreted as a link to ``T`` with a title of ``MyClass``.
+ In this case, please escape the opening angle bracket with a backslash,
+ like this: ``:cpp:class:`MyClass\<T>```.
+
+.. admonition:: Note on References
+
+ It is currently impossible to link to a specific version of an
+ overloaded method. Currently the C++ domain is the first domain
+ that has basic support for overloaded methods and until there is more
+ data for comparison we don't want to select a bad syntax to reference a
+ specific overload. Currently Sphinx will link to the first overloaded
+ version of the method / function.
+
+
+The Standard Domain
+-------------------
+
+The so-called "standard" domain collects all markup that doesn't warrant a
+domain of its own. Its directives and roles are not prefixed with a domain
+name.
+
+The standard domain is also where custom object descriptions, added using the
+:func:`~sphinx.application.Sphinx.add_object_type` API, are placed.
+
+There is a set of directives allowing documenting command-line programs:
+
+.. rst:directive:: .. option:: name args, name args, ...
+
+ Describes a command line argument or switch. Option argument names should be
+ enclosed in angle brackets. Examples::
+
+ .. option:: dest_dir
+
+ Destination directory.
+
+ .. option:: -m <module>, --module <module>
+
+ Run a module as a script.
+
+ The directive will create cross-reference targets for the given options,
+ referencable by :rst:role:`option` (in the example case, you'd use something
+ like ``:option:`dest_dir```, ``:option:`-m```, or ``:option:`--module```).
+
+.. rst:directive:: .. envvar:: name
+
+ Describes an environment variable that the documented code or program uses or
+ defines. Referencable by :rst:role:`envvar`.
+
+.. rst:directive:: .. program:: name
+
+ Like :rst:dir:`py:currentmodule`, this directive produces no output. Instead, it
+ serves to notify Sphinx that all following :rst:dir:`option` directives
+ document options for the program called *name*.
+
+ If you use :rst:dir:`program`, you have to qualify the references in your
+ :rst:role:`option` roles by the program name, so if you have the following
+ situation ::
+
+ .. program:: rm
+
+ .. option:: -r
+
+ Work recursively.
+
+ .. program:: svn
+
+ .. option:: -r revision
+
+ Specify the revision to work upon.
+
+ then ``:option:`rm -r``` would refer to the first option, while
+ ``:option:`svn -r``` would refer to the second one.
+
+ The program name may contain spaces (in case you want to document subcommands
+ like ``svn add`` and ``svn commit`` separately).
+
+ .. versionadded:: 0.5
+
+
+There is also a very generic object description directive, which is not tied to
+any domain:
+
+.. rst:directive:: .. describe:: text
+ .. object:: text
+
+ This directive produces the same formatting as the specific ones provided by
+ domains, but does not create index entries or cross-referencing targets.
+ Example::
+
+ .. describe:: PAPER
+
+ You can set this variable to select a paper size.
+
+
+The JavaScript Domain
+---------------------
+
+The JavaScript domain (name **js**) provides the following directives:
+
+.. rst:directive:: .. js:function:: name(signature)
+
+ Describes a JavaScript function or method. If you want to describe
+ arguments as optional use square brackets as :ref:`documented
+ <signatures>` for Python signatures.
+
+ You can use fields to give more details about arguments and their expected
+ types, errors which may be thrown by the function, and the value being
+ returned::
+
+ .. js:function:: $.getJSON(href, callback[, errback])
+
+ :param string href: An URI to the location of the resource.
+ :param callback: Gets called with the object.
+ :param errback:
+ Gets called in case the request fails. And a lot of other
+ text so we need multiple lines.
+ :throws SomeError: For whatever reason in that case.
+ :returns: Something.
+
+ This is rendered as:
+
+ .. js:function:: $.getJSON(href, callback[, errback])
+
+ :param string href: An URI to the location of the resource.
+ :param callback: Gets called with the object.
+ :param errback:
+ Gets called in case the request fails. And a lot of other
+ text so we need multiple lines.
+ :throws SomeError: For whatever reason in that case.
+ :returns: Something.
+
+.. rst:directive:: .. js:class:: name
+
+ Describes a constructor that creates an object. This is basically like
+ a function but will show up with a `class` prefix::
+
+ .. js:class:: MyAnimal(name[, age])
+
+ :param string name: The name of the animal
+ :param number age: an optional age for the animal
+
+ This is rendered as:
+
+ .. js:class:: MyAnimal(name[, age])
+
+ :param string name: The name of the animal
+ :param number age: an optional age for the animal
+
+.. rst:directive:: .. js:data:: name
+
+ Describes a global variable or constant.
+
+.. rst:directive:: .. js:attribute:: object.name
+
+ Describes the attribute *name* of *object*.
+
+.. _js-roles:
+
+These roles are provided to refer to the described objects:
+
+.. rst:role:: js:func
+ js:class
+ js:data
+ js:attr
+
+
+The reStructuredText domain
+---------------------------
+
+The reStructuredText domain (name **rst**) provides the following directives:
+
+.. rst:directive:: .. rst:directive:: name
+
+ Describes a reST directive. The *name* can be a single directive name or
+ actual directive syntax (`..` prefix and `::` suffix) with arguments that
+ will be rendered differently. For example::
+
+ .. rst:directive:: foo
+
+ Foo description.
+
+ .. rst:directive:: .. bar:: baz
+
+ Bar description.
+
+ will be rendered as:
+
+ .. rst:directive:: foo
+
+ Foo description.
+
+ .. rst:directive:: .. bar:: baz
+
+ Bar description.
+
+.. rst:directive:: .. rst:role:: name
+
+ Describes a reST role. For example::
+
+ .. rst:role:: foo
+
+ Foo description.
+
+ will be rendered as:
+
+ .. rst:role:: foo
+
+ Foo description.
+
+.. _rst-roles:
+
+These roles are provided to refer to the described objects:
+
+.. rst:role:: rst:dir
+ rst:role
+
+
+More domains
+------------
+
+The sphinx-contrib_ repository contains more domains available as extensions;
+currently Ada_, CoffeeScript_, Erlang_, HTTP_, Lasso_, MATLAB_, PHP_, and Ruby_
+domains. Also available are domains for `Common Lisp`_, dqn_, Go_, Jinja_,
+Operation_, and Scala_.
+
+
+.. _sphinx-contrib: https://bitbucket.org/birkenfeld/sphinx-contrib/
+
+.. _Ada: https://pypi.python.org/pypi/sphinxcontrib-adadomain
+.. _CoffeeScript: https://pypi.python.org/pypi/sphinxcontrib-coffee
+.. _Common Lisp: https://pypi.python.org/pypi/sphinxcontrib-cldomain
+.. _dqn: https://pypi.python.org/pypi/sphinxcontrib-dqndomain
+.. _Erlang: https://pypi.python.org/pypi/sphinxcontrib-erlangdomain
+.. _Go: https://pypi.python.org/pypi/sphinxcontrib-golangdomain
+.. _HTTP: https://pypi.python.org/pypi/sphinxcontrib-httpdomain
+.. _Jinja: https://pypi.python.org/pypi/sphinxcontrib-jinjadomain
+.. _Lasso: https://pypi.python.org/pypi/sphinxcontrib-lassodomain
+.. _MATLAB: https://pypi.python.org/pypi/sphinxcontrib-matlabdomain
+.. _Operation: https://pypi.python.org/pypi/sphinxcontrib-operationdomain
+.. _PHP: https://pypi.python.org/pypi/sphinxcontrib-phpdomain
+.. _Ruby: https://bitbucket.org/birkenfeld/sphinx-contrib/src/default/rubydomain
+.. _Scala: https://pypi.python.org/pypi/sphinxcontrib-scaladomain
diff --git a/doc/examples.rst b/doc/examples.rst
new file mode 100644
index 0000000..c28364a
--- /dev/null
+++ b/doc/examples.rst
@@ -0,0 +1,5 @@
+:tocdepth: 2
+
+.. _examples:
+
+.. include:: ../EXAMPLES
diff --git a/doc/ext/autodoc.rst b/doc/ext/autodoc.rst
new file mode 100644
index 0000000..7f64698
--- /dev/null
+++ b/doc/ext/autodoc.rst
@@ -0,0 +1,429 @@
+.. highlight:: rest
+
+:mod:`sphinx.ext.autodoc` -- Include documentation from docstrings
+==================================================================
+
+.. module:: sphinx.ext.autodoc
+ :synopsis: Include documentation from docstrings.
+
+.. index:: pair: automatic; documentation
+ single: docstring
+
+This extension can import the modules you are documenting, and pull in
+documentation from docstrings in a semi-automatic way.
+
+.. note::
+
+ For Sphinx (actually, the Python interpreter that executes Sphinx) to find
+ your module, it must be importable. That means that the module or the
+ package must be in one of the directories on :data:`sys.path` -- adapt your
+ :data:`sys.path` in the configuration file accordingly.
+
+.. warning::
+
+ :mod:`~sphinx.ext.autodoc` **imports** the modules to be documented. If any
+ modules have side effects on import, these will be executed by ``autodoc``
+ when ``sphinx-build`` is run.
+
+ If you document scripts (as opposed to library modules), make sure their main
+ routine is protected by a ``if __name__ == '__main__'`` condition.
+
+For this to work, the docstrings must of course be written in correct
+reStructuredText. You can then use all of the usual Sphinx markup in the
+docstrings, and it will end up correctly in the documentation. Together with
+hand-written documentation, this technique eases the pain of having to maintain
+two locations for documentation, while at the same time avoiding
+auto-generated-looking pure API documentation.
+
+:mod:`autodoc` provides several directives that are versions of the usual
+:rst:dir:`py:module`, :rst:dir:`py:class` and so forth. On parsing time, they
+import the corresponding module and extract the docstring of the given objects,
+inserting them into the page source under a suitable :rst:dir:`py:module`,
+:rst:dir:`py:class` etc. directive.
+
+.. note::
+
+ Just as :rst:dir:`py:class` respects the current :rst:dir:`py:module`,
+ :rst:dir:`autoclass` will also do so. Likewise, :rst:dir:`automethod` will
+ respect the current :rst:dir:`py:class`.
+
+
+.. rst:directive:: automodule
+ autoclass
+ autoexception
+
+ Document a module, class or exception. All three directives will by default
+ only insert the docstring of the object itself::
+
+ .. autoclass:: Noodle
+
+ will produce source like this::
+
+ .. class:: Noodle
+
+ Noodle's docstring.
+
+ The "auto" directives can also contain content of their own, it will be
+ inserted into the resulting non-auto directive source after the docstring
+ (but before any automatic member documentation).
+
+ Therefore, you can also mix automatic and non-automatic member documentation,
+ like so::
+
+ .. autoclass:: Noodle
+ :members: eat, slurp
+
+ .. method:: boil(time=10)
+
+ Boil the noodle *time* minutes.
+
+ **Options and advanced usage**
+
+ * If you want to automatically document members, there's a ``members``
+ option::
+
+ .. automodule:: noodle
+ :members:
+
+ will document all module members (recursively), and ::
+
+ .. autoclass:: Noodle
+ :members:
+
+ will document all non-private member functions and properties (that is,
+ those whose name doesn't start with ``_``).
+
+ For modules, ``__all__`` will be respected when looking for members; the
+ order of the members will also be the order in ``__all__``.
+
+ You can also give an explicit list of members; only these will then be
+ documented::
+
+ .. autoclass:: Noodle
+ :members: eat, slurp
+
+ * If you want to make the ``members`` option (or other flag options described
+ below) the default, see :confval:`autodoc_default_flags`.
+
+ * Members without docstrings will be left out, unless you give the
+ ``undoc-members`` flag option::
+
+ .. automodule:: noodle
+ :members:
+ :undoc-members:
+
+ * "Private" members (that is, those named like ``_private`` or ``__private``)
+ will be included if the ``private-members`` flag option is given.
+
+ .. versionadded:: 1.1
+
+ * Python "special" members (that is, those named like ``__special__``) will
+ be included if the ``special-members`` flag option is given::
+
+ .. autoclass:: my.Class
+ :members:
+ :private-members:
+ :special-members:
+
+ would document both "private" and "special" members of the class.
+
+ .. versionadded:: 1.1
+
+ .. versionchanged:: 1.2
+ The option can now take arguments, i.e. the special members to document.
+
+ * For classes and exceptions, members inherited from base classes will be
+ left out when documenting all members, unless you give the
+ ``inherited-members`` flag option, in addition to ``members``::
+
+ .. autoclass:: Noodle
+ :members:
+ :inherited-members:
+
+ This can be combined with ``undoc-members`` to document *all* available
+ members of the class or module.
+
+ Note: this will lead to markup errors if the inherited members come from a
+ module whose docstrings are not reST formatted.
+
+ .. versionadded:: 0.3
+
+ * It's possible to override the signature for explicitly documented callable
+ objects (functions, methods, classes) with the regular syntax that will
+ override the signature gained from introspection::
+
+ .. autoclass:: Noodle(type)
+
+ .. automethod:: eat(persona)
+
+ This is useful if the signature from the method is hidden by a decorator.
+
+ .. versionadded:: 0.4
+
+ * The :rst:dir:`automodule`, :rst:dir:`autoclass` and
+ :rst:dir:`autoexception` directives also support a flag option called
+ ``show-inheritance``. When given, a list of base classes will be inserted
+ just below the class signature (when used with :rst:dir:`automodule`, this
+ will be inserted for every class that is documented in the module).
+
+ .. versionadded:: 0.4
+
+ * All autodoc directives support the ``noindex`` flag option that has the
+ same effect as for standard :rst:dir:`py:function` etc. directives: no
+ index entries are generated for the documented object (and all
+ autodocumented members).
+
+ .. versionadded:: 0.4
+
+ * :rst:dir:`automodule` also recognizes the ``synopsis``, ``platform`` and
+ ``deprecated`` options that the standard :rst:dir:`py:module` directive
+ supports.
+
+ .. versionadded:: 0.5
+
+ * :rst:dir:`automodule` and :rst:dir:`autoclass` also has an ``member-order``
+ option that can be used to override the global value of
+ :confval:`autodoc_member_order` for one directive.
+
+ .. versionadded:: 0.6
+
+ * The directives supporting member documentation also have a
+ ``exclude-members`` option that can be used to exclude single member names
+ from documentation, if all members are to be documented.
+
+ .. versionadded:: 0.6
+
+ * In an :rst:dir:`automodule` directive with the ``members`` option set, only
+ module members whose ``__module__`` attribute is equal to the module name
+ as given to ``automodule`` will be documented. This is to prevent
+ documentation of imported classes or functions. Set the
+ ``imported-members`` option if you want to prevent this behavior and
+ document all available members. Note that attributes from imported modules
+ will not be documented, because attribute documentation is discovered by
+ parsing the source file of the current module.
+
+ .. versionadded:: 1.2
+
+
+.. rst:directive:: autofunction
+ autodata
+ automethod
+ autoattribute
+
+ These work exactly like :rst:dir:`autoclass` etc.,
+ but do not offer the options used for automatic member documentation.
+
+ :rst:dir:`autodata` and :rst:dir:`autoattribute` support
+ the ``annotation`` option.
+ Without this option, the representation of the object
+ will be shown in the documentation.
+ When the option is given without arguments,
+ only the name of the object will be printed::
+
+ .. autodata:: CD_DRIVE
+ :annotation:
+
+ You can tell sphinx what should be printed after the name::
+
+ .. autodata:: CD_DRIVE
+ :annotation: = your CD device name
+
+ For module data members and class attributes, documentation can either be put
+ into a comment with special formatting (using a ``#:`` to start the comment
+ instead of just ``#``), or in a docstring *after* the definition. Comments
+ need to be either on a line of their own *before* the definition, or
+ immediately after the assignment *on the same line*. The latter form is
+ restricted to one line only.
+
+ This means that in the following class definition, all attributes can be
+ autodocumented::
+
+ class Foo:
+ """Docstring for class Foo."""
+
+ #: Doc comment for class attribute Foo.bar.
+ #: It can have multiple lines.
+ bar = 1
+
+ flox = 1.5 #: Doc comment for Foo.flox. One line only.
+
+ baz = 2
+ """Docstring for class attribute Foo.baz."""
+
+ def __init__(self):
+ #: Doc comment for instance attribute qux.
+ self.qux = 3
+
+ self.spam = 4
+ """Docstring for instance attribute spam."""
+
+ .. versionchanged:: 0.6
+ :rst:dir:`autodata` and :rst:dir:`autoattribute` can now extract docstrings.
+ .. versionchanged:: 1.1
+ Comment docs are now allowed on the same line after an assignment.
+
+ .. versionchanged:: 1.2
+ :rst:dir:`autodata` and :rst:dir:`autoattribute` have
+ an ``annotation`` option
+
+ .. note::
+
+ If you document decorated functions or methods, keep in mind that autodoc
+ retrieves its docstrings by importing the module and inspecting the
+ ``__doc__`` attribute of the given function or method. That means that if
+ a decorator replaces the decorated function with another, it must copy the
+ original ``__doc__`` to the new function.
+
+ From Python 2.5, :func:`functools.wraps` can be used to create
+ well-behaved decorating functions.
+
+
+There are also new config values that you can set:
+
+.. confval:: autoclass_content
+
+ This value selects what content will be inserted into the main body of an
+ :rst:dir:`autoclass` directive. The possible values are:
+
+ ``"class"``
+ Only the class' docstring is inserted. This is the default. You can
+ still document ``__init__`` as a separate method using
+ :rst:dir:`automethod` or the ``members`` option to :rst:dir:`autoclass`.
+ ``"both"``
+ Both the class' and the ``__init__`` method's docstring are concatenated
+ and inserted.
+ ``"init"``
+ Only the ``__init__`` method's docstring is inserted.
+
+ .. versionadded:: 0.3
+
+.. confval:: autodoc_member_order
+
+ This value selects if automatically documented members are sorted
+ alphabetical (value ``'alphabetical'``), by member type (value
+ ``'groupwise'``) or by source order (value ``'bysource'``). The default is
+ alphabetical.
+
+ Note that for source order, the module must be a Python module with the
+ source code available.
+
+ .. versionadded:: 0.6
+ .. versionchanged:: 1.0
+ Support for ``'bysource'``.
+
+.. confval:: autodoc_default_flags
+
+ This value is a list of autodoc directive flags that should be automatically
+ applied to all autodoc directives. The supported flags are ``'members'``,
+ ``'undoc-members'``, ``'private-members'``, ``'special-members'``,
+ ``'inherited-members'`` and ``'show-inheritance'``.
+
+ If you set one of these flags in this config value, you can use a negated
+ form, :samp:`'no-{flag}'`, in an autodoc directive, to disable it once.
+ For example, if ``autodoc_default_flags`` is set to ``['members',
+ 'undoc-members']``, and you write a directive like this::
+
+ .. automodule:: foo
+ :no-undoc-members:
+
+ the directive will be interpreted as if only ``:members:`` was given.
+
+ .. versionadded:: 1.0
+
+.. confval:: autodoc_docstring_signature
+
+ Functions imported from C modules cannot be introspected, and therefore the
+ signature for such functions cannot be automatically determined. However, it
+ is an often-used convention to put the signature into the first line of the
+ function's docstring.
+
+ If this boolean value is set to ``True`` (which is the default), autodoc will
+ look at the first line of the docstring for functions and methods, and if it
+ looks like a signature, use the line as the signature and remove it from the
+ docstring content.
+
+ .. versionadded:: 1.1
+
+
+Docstring preprocessing
+-----------------------
+
+autodoc provides the following additional events:
+
+.. event:: autodoc-process-docstring (app, what, name, obj, options, lines)
+
+ .. versionadded:: 0.4
+
+ Emitted when autodoc has read and processed a docstring. *lines* is a list
+ of strings -- the lines of the processed docstring -- that the event handler
+ can modify **in place** to change what Sphinx puts into the output.
+
+ :param app: the Sphinx application object
+ :param what: the type of the object which the docstring belongs to (one of
+ ``"module"``, ``"class"``, ``"exception"``, ``"function"``, ``"method"``,
+ ``"attribute"``)
+ :param name: the fully qualified name of the object
+ :param obj: the object itself
+ :param options: the options given to the directive: an object with attributes
+ ``inherited_members``, ``undoc_members``, ``show_inheritance`` and
+ ``noindex`` that are true if the flag option of same name was given to the
+ auto directive
+ :param lines: the lines of the docstring, see above
+
+.. event:: autodoc-process-signature (app, what, name, obj, options, signature, return_annotation)
+
+ .. versionadded:: 0.5
+
+ Emitted when autodoc has formatted a signature for an object. The event
+ handler can return a new tuple ``(signature, return_annotation)`` to change
+ what Sphinx puts into the output.
+
+ :param app: the Sphinx application object
+ :param what: the type of the object which the docstring belongs to (one of
+ ``"module"``, ``"class"``, ``"exception"``, ``"function"``, ``"method"``,
+ ``"attribute"``)
+ :param name: the fully qualified name of the object
+ :param obj: the object itself
+ :param options: the options given to the directive: an object with attributes
+ ``inherited_members``, ``undoc_members``, ``show_inheritance`` and
+ ``noindex`` that are true if the flag option of same name was given to the
+ auto directive
+ :param signature: function signature, as a string of the form
+ ``"(parameter_1, parameter_2)"``, or ``None`` if introspection didn't succeed
+ and signature wasn't specified in the directive.
+ :param return_annotation: function return annotation as a string of the form
+ ``" -> annotation"``, or ``None`` if there is no return annotation
+
+The :mod:`sphinx.ext.autodoc` module provides factory functions for commonly
+needed docstring processing in event :event:`autodoc-process-docstring`:
+
+.. autofunction:: cut_lines
+.. autofunction:: between
+
+
+Skipping members
+----------------
+
+autodoc allows the user to define a custom method for determining whether a
+member should be included in the documentation by using the following event:
+
+.. event:: autodoc-skip-member (app, what, name, obj, skip, options)
+
+ .. versionadded:: 0.5
+
+ Emitted when autodoc has to decide whether a member should be included in the
+ documentation. The member is excluded if a handler returns ``True``. It is
+ included if the handler returns ``False``.
+
+ :param app: the Sphinx application object
+ :param what: the type of the object which the docstring belongs to (one of
+ ``"module"``, ``"class"``, ``"exception"``, ``"function"``, ``"method"``,
+ ``"attribute"``)
+ :param name: the fully qualified name of the object
+ :param obj: the object itself
+ :param skip: a boolean indicating if autodoc will skip this member if the user
+ handler does not override the decision
+ :param options: the options given to the directive: an object with attributes
+ ``inherited_members``, ``undoc_members``, ``show_inheritance`` and
+ ``noindex`` that are true if the flag option of same name was given to the
+ auto directive
diff --git a/doc/ext/autosummary.rst b/doc/ext/autosummary.rst
new file mode 100644
index 0000000..e3de183
--- /dev/null
+++ b/doc/ext/autosummary.rst
@@ -0,0 +1,233 @@
+.. highlight:: rest
+
+:mod:`sphinx.ext.autosummary` -- Generate autodoc summaries
+===========================================================
+
+.. module:: sphinx.ext.autosummary
+ :synopsis: Generate autodoc summaries
+
+.. versionadded:: 0.6
+
+This extension generates function/method/attribute summary lists, similar to
+those output e.g. by Epydoc and other API doc generation tools. This is
+especially useful when your docstrings are long and detailed, and putting each
+one of them on a separate page makes them easier to read.
+
+The :mod:`sphinx.ext.autosummary` extension does this in two parts:
+
+1. There is an :rst:dir:`autosummary` directive for generating summary listings that
+ contain links to the documented items, and short summary blurbs extracted
+ from their docstrings.
+
+2. Optionally, the convenience script :program:`sphinx-autogen` or the new
+ :confval:`autosummary_generate` config value can be used to generate short
+ "stub" files for the entries listed in the :rst:dir:`autosummary` directives.
+ These files by default contain only the corresponding :mod:`sphinx.ext.autodoc`
+ directive, but can be customized with templates.
+
+
+.. rst:directive:: autosummary
+
+ Insert a table that contains links to documented items, and a short summary
+ blurb (the first sentence of the docstring) for each of them.
+
+ The :rst:dir:`autosummary` directive can also optionally serve as a
+ :rst:dir:`toctree` entry for the included items. Optionally, stub
+ ``.rst`` files for these items can also be automatically generated.
+
+ For example, ::
+
+ .. currentmodule:: sphinx
+
+ .. autosummary::
+
+ environment.BuildEnvironment
+ util.relative_uri
+
+ produces a table like this:
+
+ .. currentmodule:: sphinx
+
+ .. autosummary::
+
+ environment.BuildEnvironment
+ util.relative_uri
+
+ .. currentmodule:: sphinx.ext.autosummary
+
+ Autosummary preprocesses the docstrings and signatures with the same
+ :event:`autodoc-process-docstring` and :event:`autodoc-process-signature`
+ hooks as :mod:`~sphinx.ext.autodoc`.
+
+
+ **Options**
+
+ * If you want the :rst:dir:`autosummary` table to also serve as a :rst:dir:`toctree`
+ entry, use the ``toctree`` option, for example::
+
+ .. autosummary::
+ :toctree: DIRNAME
+
+ sphinx.environment.BuildEnvironment
+ sphinx.util.relative_uri
+
+ The ``toctree`` option also signals to the :program:`sphinx-autogen` script
+ that stub pages should be generated for the entries listed in this
+ directive. The option accepts a directory name as an argument;
+ :program:`sphinx-autogen` will by default place its output in this
+ directory. If no argument is given, output is placed in the same directory
+ as the file that contains the directive.
+
+ * If you don't want the :rst:dir:`autosummary` to show function signatures in the
+ listing, include the ``nosignatures`` option::
+
+ .. autosummary::
+ :nosignatures:
+
+ sphinx.environment.BuildEnvironment
+ sphinx.util.relative_uri
+
+ * You can specify a custom template with the ``template`` option.
+ For example, ::
+
+ .. autosummary::
+ :template: mytemplate.rst
+
+ sphinx.environment.BuildEnvironment
+
+ would use the template :file:`mytemplate.rst` in your
+ :confval:`templates_path` to generate the pages for all entries
+ listed. See `Customizing templates`_ below.
+
+ .. versionadded:: 1.0
+
+
+:program:`sphinx-autogen` -- generate autodoc stub pages
+--------------------------------------------------------
+
+The :program:`sphinx-autogen` script can be used to conveniently generate stub
+documentation pages for items included in :rst:dir:`autosummary` listings.
+
+For example, the command ::
+
+ $ sphinx-autogen -o generated *.rst
+
+will read all :rst:dir:`autosummary` tables in the :file:`*.rst` files that have the
+``:toctree:`` option set, and output corresponding stub pages in directory
+``generated`` for all documented items. The generated pages by default contain
+text of the form::
+
+ sphinx.util.relative_uri
+ ========================
+
+ .. autofunction:: sphinx.util.relative_uri
+
+If the ``-o`` option is not given, the script will place the output files in the
+directories specified in the ``:toctree:`` options.
+
+
+Generating stub pages automatically
+-----------------------------------
+
+If you do not want to create stub pages with :program:`sphinx-autogen`, you can
+also use this new config value:
+
+.. confval:: autosummary_generate
+
+ Boolean indicating whether to scan all found documents for autosummary
+ directives, and to generate stub pages for each.
+
+ Can also be a list of documents for which stub pages should be generated.
+
+ The new files will be placed in the directories specified in the
+ ``:toctree:`` options of the directives.
+
+
+Customizing templates
+---------------------
+
+.. versionadded:: 1.0
+
+You can customize the stub page templates, in a similar way as the HTML Jinja
+templates, see :ref:`templating`. (:class:`~sphinx.application.TemplateBridge`
+is not supported.)
+
+.. note::
+
+ If you find yourself spending much time tailoring the stub templates, this
+ may indicate that it's a better idea to write custom narrative documentation
+ instead.
+
+Autosummary uses the following template files:
+
+- :file:`autosummary/base.rst` -- fallback template
+- :file:`autosummary/module.rst` -- template for modules
+- :file:`autosummary/class.rst` -- template for classes
+- :file:`autosummary/function.rst` -- template for functions
+- :file:`autosummary/attribute.rst` -- template for class attributes
+- :file:`autosummary/method.rst` -- template for class methods
+
+The following variables available in the templates:
+
+.. currentmodule:: None
+
+.. data:: name
+
+ Name of the documented object, excluding the module and class parts.
+
+.. data:: objname
+
+ Name of the documented object, excluding the module parts.
+
+.. data:: fullname
+
+ Full name of the documented object, including module and class parts.
+
+.. data:: module
+
+ Name of the module the documented object belongs to.
+
+.. data:: class
+
+ Name of the class the documented object belongs to. Only available for
+ methods and attributes.
+
+.. data:: underline
+
+ A string containing ``len(full_name) * '='``.
+
+.. data:: members
+
+ List containing names of all members of the module or class. Only available
+ for modules and classes.
+
+.. data:: functions
+
+ List containing names of "public" functions in the module. Here, "public"
+ here means that the name does not start with an underscore. Only available
+ for modules.
+
+.. data:: classes
+
+ List containing names of "public" classes in the module. Only available for
+ modules.
+
+.. data:: exceptions
+
+ List containing names of "public" exceptions in the module. Only available
+ for modules.
+
+.. data:: methods
+
+ List containing names of "public" methods in the class. Only available for
+ classes.
+
+.. data:: attributes
+
+ List containing names of "public" attributes in the class. Only available
+ for classes.
+
+.. note::
+
+ You can use the :rst:dir:`autosummary` directive in the stub pages.
+ Stub pages are generated also based on these directives.
diff --git a/doc/ext/coverage.rst b/doc/ext/coverage.rst
new file mode 100644
index 0000000..839478f
--- /dev/null
+++ b/doc/ext/coverage.rst
@@ -0,0 +1,44 @@
+:mod:`sphinx.ext.coverage` -- Collect doc coverage stats
+========================================================
+
+.. module:: sphinx.ext.coverage
+ :synopsis: Check Python modules and C API for coverage in the documentation.
+
+
+This extension features one additional builder, the :class:`CoverageBuilder`.
+
+.. class:: CoverageBuilder
+
+ To use this builder, activate the coverage extension in your configuration
+ file and give ``-b coverage`` on the command line.
+
+.. todo:: Write this section.
+
+
+Several new configuration values can be used to specify what the builder
+should check:
+
+.. confval:: coverage_ignore_modules
+
+.. confval:: coverage_ignore_functions
+
+.. confval:: coverage_ignore_classes
+
+.. confval:: coverage_c_path
+
+.. confval:: coverage_c_regexes
+
+.. confval:: coverage_ignore_c_items
+
+.. confval:: coverage_write_headline
+
+ Set to ``False`` to not write headlines.
+
+ .. versionadded:: 1.1
+
+.. confval:: coverage_skip_undoc_in_source
+
+ Skip objects that are not documented in the source with a docstring.
+ ``False`` by default.
+
+ .. versionadded:: 1.1
diff --git a/doc/ext/doctest.rst b/doc/ext/doctest.rst
new file mode 100644
index 0000000..554987e
--- /dev/null
+++ b/doc/ext/doctest.rst
@@ -0,0 +1,240 @@
+.. highlight:: rest
+
+:mod:`sphinx.ext.doctest` -- Test snippets in the documentation
+===============================================================
+
+.. module:: sphinx.ext.doctest
+ :synopsis: Test snippets in the documentation.
+
+.. index:: pair: automatic; testing
+ single: doctest
+ pair: testing; snippets
+
+
+This extension allows you to test snippets in the documentation in a natural
+way. It works by collecting specially-marked up code blocks and running them as
+doctest tests.
+
+Within one document, test code is partitioned in *groups*, where each group
+consists of:
+
+* zero or more *setup code* blocks (e.g. importing the module to test)
+* one or more *test* blocks
+
+When building the docs with the ``doctest`` builder, groups are collected for
+each document and run one after the other, first executing setup code blocks,
+then the test blocks in the order they appear in the file.
+
+There are two kinds of test blocks:
+
+* *doctest-style* blocks mimic interactive sessions by interleaving Python code
+ (including the interpreter prompt) and output.
+
+* *code-output-style* blocks consist of an ordinary piece of Python code, and
+ optionally, a piece of output for that code.
+
+The doctest extension provides four directives. The *group* argument is
+interpreted as follows: if it is empty, the block is assigned to the group named
+``default``. If it is ``*``, the block is assigned to all groups (including the
+``default`` group). Otherwise, it must be a comma-separated list of group
+names.
+
+.. rst:directive:: .. testsetup:: [group]
+
+ A setup code block. This code is not shown in the output for other builders,
+ but executed before the doctests of the group(s) it belongs to.
+
+
+.. rst:directive:: .. testcleanup:: [group]
+
+ A cleanup code block. This code is not shown in the output for other
+ builders, but executed after the doctests of the group(s) it belongs to.
+
+ .. versionadded:: 1.1
+
+
+.. rst:directive:: .. doctest:: [group]
+
+ A doctest-style code block. You can use standard :mod:`doctest` flags for
+ controlling how actual output is compared with what you give as output. By
+ default, these options are enabled: ``ELLIPSIS`` (allowing you to put
+ ellipses in the expected output that match anything in the actual output),
+ ``IGNORE_EXCEPTION_DETAIL`` (not comparing tracebacks),
+ ``DONT_ACCEPT_TRUE_FOR_1`` (by default, doctest accepts "True" in the output
+ where "1" is given -- this is a relic of pre-Python 2.2 times).
+
+ This directive supports two options:
+
+ * ``hide``, a flag option, hides the doctest block in other builders. By
+ default it is shown as a highlighted doctest block.
+
+ * ``options``, a string option, can be used to give a comma-separated list of
+ doctest flags that apply to each example in the tests. (You still can give
+ explicit flags per example, with doctest comments, but they will show up in
+ other builders too.)
+
+ Note that like with standard doctests, you have to use ``<BLANKLINE>`` to
+ signal a blank line in the expected output. The ``<BLANKLINE>`` is removed
+ when building presentation output (HTML, LaTeX etc.).
+
+ Also, you can give inline doctest options, like in doctest::
+
+ >>> datetime.date.now() # doctest: +SKIP
+ datetime.date(2008, 1, 1)
+
+ They will be respected when the test is run, but stripped from presentation
+ output.
+
+
+.. rst:directive:: .. testcode:: [group]
+
+ A code block for a code-output-style test.
+
+ This directive supports one option:
+
+ * ``hide``, a flag option, hides the code block in other builders. By
+ default it is shown as a highlighted code block.
+
+ .. note::
+
+ Code in a ``testcode`` block is always executed all at once, no matter how
+ many statements it contains. Therefore, output will *not* be generated
+ for bare expressions -- use ``print``. Example::
+
+ .. testcode::
+
+ 1+1 # this will give no output!
+ print 2+2 # this will give output
+
+ .. testoutput::
+
+ 4
+
+ Also, please be aware that since the doctest module does not support
+ mixing regular output and an exception message in the same snippet, this
+ applies to testcode/testoutput as well.
+
+
+.. rst:directive:: .. testoutput:: [group]
+
+ The corresponding output, or the exception message, for the last
+ :rst:dir:`testcode` block.
+
+ This directive supports two options:
+
+ * ``hide``, a flag option, hides the output block in other builders. By
+ default it is shown as a literal block without highlighting.
+
+ * ``options``, a string option, can be used to give doctest flags
+ (comma-separated) just like in normal doctest blocks.
+
+ Example::
+
+ .. testcode::
+
+ print 'Output text.'
+
+ .. testoutput::
+ :hide:
+ :options: -ELLIPSIS, +NORMALIZE_WHITESPACE
+
+ Output text.
+
+
+The following is an example for the usage of the directives. The test via
+:rst:dir:`doctest` and the test via :rst:dir:`testcode` and :rst:dir:`testoutput` are
+equivalent. ::
+
+ The parrot module
+ =================
+
+ .. testsetup:: *
+
+ import parrot
+
+ The parrot module is a module about parrots.
+
+ Doctest example:
+
+ .. doctest::
+
+ >>> parrot.voom(3000)
+ This parrot wouldn't voom if you put 3000 volts through it!
+
+ Test-Output example:
+
+ .. testcode::
+
+ parrot.voom(3000)
+
+ This would output:
+
+ .. testoutput::
+
+ This parrot wouldn't voom if you put 3000 volts through it!
+
+
+There are also these config values for customizing the doctest extension:
+
+.. confval:: doctest_path
+
+ A list of directories that will be added to :data:`sys.path` when the doctest
+ builder is used. (Make sure it contains absolute paths.)
+
+.. confval:: doctest_global_setup
+
+ Python code that is treated like it were put in a ``testsetup`` directive for
+ *every* file that is tested, and for every group. You can use this to
+ e.g. import modules you will always need in your doctests.
+
+ .. versionadded:: 0.6
+
+.. confval:: doctest_global_cleanup
+
+ Python code that is treated like it were put in a ``testcleanup`` directive
+ for *every* file that is tested, and for every group. You can use this to
+ e.g. remove any temporary files that the tests leave behind.
+
+ .. versionadded:: 1.1
+
+.. confval:: doctest_test_doctest_blocks
+
+ If this is a nonempty string (the default is ``'default'``), standard reST
+ doctest blocks will be tested too. They will be assigned to the group name
+ given.
+
+ reST doctest blocks are simply doctests put into a paragraph of their own,
+ like so::
+
+ Some documentation text.
+
+ >>> print 1
+ 1
+
+ Some more documentation text.
+
+ (Note that no special ``::`` is used to introduce a doctest block; docutils
+ recognizes them from the leading ``>>>``. Also, no additional indentation is
+ used, though it doesn't hurt.)
+
+ If this value is left at its default value, the above snippet is interpreted
+ by the doctest builder exactly like the following::
+
+ Some documentation text.
+
+ .. doctest::
+
+ >>> print 1
+ 1
+
+ Some more documentation text.
+
+ This feature makes it easy for you to test doctests in docstrings included
+ with the :mod:`~sphinx.ext.autodoc` extension without marking them up with a
+ special directive.
+
+ Note though that you can't have blank lines in reST doctest blocks. They
+ will be interpreted as one block ending and another one starting. Also,
+ removal of ``<BLANKLINE>`` and ``# doctest:`` options only works in
+ :rst:dir:`doctest` blocks, though you may set :confval:`trim_doctest_flags` to
+ achieve that in all code blocks with Python console content.
diff --git a/doc/ext/extlinks.rst b/doc/ext/extlinks.rst
new file mode 100644
index 0000000..d8bcaa5
--- /dev/null
+++ b/doc/ext/extlinks.rst
@@ -0,0 +1,54 @@
+:mod:`sphinx.ext.extlinks` -- Markup to shorten external links
+==============================================================
+
+.. module:: sphinx.ext.extlinks
+ :synopsis: Allow inserting external links with common base URLs easily.
+.. moduleauthor:: Georg Brandl
+
+.. versionadded:: 1.0
+
+
+This extension is meant to help with the common pattern of having many external
+links that point to URLs on one and the same site, e.g. links to bug trackers,
+version control web interfaces, or simply subpages in other websites. It does
+so by providing aliases to base URLs, so that you only need to give the subpage
+name when creating a link.
+
+Let's assume that you want to include many links to issues at the Sphinx
+tracker, at :samp:`http://bitbucket.org/birkenfeld/sphinx/issue/{num}`. Typing
+this URL again and again is tedious, so you can use :mod:`~sphinx.ext.extlinks`
+to avoid repeating yourself.
+
+The extension adds one new config value:
+
+.. confval:: extlinks
+
+ This config value must be a dictionary of external sites, mapping unique
+ short alias names to a base URL and a *prefix*. For example, to create an
+ alias for the above mentioned issues, you would add ::
+
+ extlinks = {'issue': ('https://bitbucket.org/birkenfeld/sphinx/issue/%s',
+ 'issue ')}
+
+ Now, you can use the alias name as a new role, e.g. ``:issue:`123```. This
+ then inserts a link to https://bitbucket.org/birkenfeld/sphinx/issue/123.
+ As you can see, the target given in the role is substituted in the base URL
+ in the place of ``%s``.
+
+ The link *caption* depends on the second item in the tuple, the *prefix*:
+
+ - If the prefix is ``None``, the link caption is the full URL.
+ - If the prefix is the empty string, the link caption is the partial URL
+ given in the role content (``123`` in this case.)
+ - If the prefix is a non-empty string, the link caption is the partial URL,
+ prepended by the prefix -- in the above example, the link caption would be
+ ``issue 123``.
+
+ You can also use the usual "explicit title" syntax supported by other roles
+ that generate links, i.e. ``:issue:`this issue <123>```. In this case, the
+ *prefix* is not relevant.
+
+.. note::
+
+ Since links are generated from the role in the reading stage, they appear as
+ ordinary links to e.g. the ``linkcheck`` builder.
diff --git a/doc/ext/graphviz.rst b/doc/ext/graphviz.rst
new file mode 100644
index 0000000..9b34b48
--- /dev/null
+++ b/doc/ext/graphviz.rst
@@ -0,0 +1,113 @@
+.. highlight:: rest
+
+:mod:`sphinx.ext.graphviz` -- Add Graphviz graphs
+=================================================
+
+.. module:: sphinx.ext.graphviz
+ :synopsis: Support for Graphviz graphs.
+
+.. versionadded:: 0.6
+
+This extension allows you to embed `Graphviz <http://graphviz.org/>`_ graphs in
+your documents.
+
+It adds these directives:
+
+
+.. rst:directive:: graphviz
+
+ Directive to embed graphviz code. The input code for ``dot`` is given as the
+ content. For example::
+
+ .. graphviz::
+
+ digraph foo {
+ "bar" -> "baz";
+ }
+
+ In HTML output, the code will be rendered to a PNG or SVG image (see
+ :confval:`graphviz_output_format`). In LaTeX output, the code will be
+ rendered to an embeddable PDF file.
+
+ You can also embed external dot files, by giving the file name as an
+ argument to :rst:dir:`graphviz` and no additional content::
+
+ .. graphviz:: external.dot
+
+ As for all file references in Sphinx, if the filename is absolute, it is
+ taken as relative to the source directory.
+
+ .. versionchanged:: 1.1
+ Added support for external files.
+
+
+.. rst:directive:: graph
+
+ Directive for embedding a single undirected graph. The name is given as a
+ directive argument, the contents of the graph are the directive content.
+ This is a convenience directive to generate ``graph <name> { <content> }``.
+
+ For example::
+
+ .. graph:: foo
+
+ "bar" -- "baz";
+
+
+.. rst:directive:: digraph
+
+ Directive for embedding a single directed graph. The name is given as a
+ directive argument, the contents of the graph are the directive content.
+ This is a convenience directive to generate ``digraph <name> { <content> }``.
+
+ For example::
+
+ .. digraph:: foo
+
+ "bar" -> "baz" -> "quux";
+
+
+.. versionadded:: 1.0
+ All three directives support an ``alt`` option that determines the image's
+ alternate text for HTML output. If not given, the alternate text defaults to
+ the graphviz code.
+
+.. versionadded:: 1.1
+ All three directives support an ``inline`` flag that controls paragraph
+ breaks in the output. When set, the graph is inserted into the current
+ paragraph. If the flag is not given, paragraph breaks are introduced before
+ and after the image (the default).
+
+.. versionadded:: 1.1
+ All three directives support a ``caption`` option that can be used to give a
+ caption to the diagram. Naturally, diagrams marked as "inline" cannot have a
+ caption.
+
+There are also these new config values:
+
+.. confval:: graphviz_dot
+
+ The command name with which to invoke ``dot``. The default is ``'dot'``; you
+ may need to set this to a full path if ``dot`` is not in the executable
+ search path.
+
+ Since this setting is not portable from system to system, it is normally not
+ useful to set it in ``conf.py``; rather, giving it on the
+ :program:`sphinx-build` command line via the :option:`-D` option should be
+ preferable, like this::
+
+ sphinx-build -b html -D graphviz_dot=C:\graphviz\bin\dot.exe . _build/html
+
+.. confval:: graphviz_dot_args
+
+ Additional command-line arguments to give to dot, as a list. The default is
+ an empty list. This is the right place to set global graph, node or edge
+ attributes via dot's ``-G``, ``-N`` and ``-E`` options.
+
+.. confval:: graphviz_output_format
+
+ The output format for Graphviz when building HTML files. This must be either
+ ``'png'`` or ``'svg'``; the default is ``'png'``.
+
+ .. versionadded:: 1.0
+ Previously, output always was PNG.
diff --git a/doc/ext/ifconfig.rst b/doc/ext/ifconfig.rst
new file mode 100644
index 0000000..a11e307
--- /dev/null
+++ b/doc/ext/ifconfig.rst
@@ -0,0 +1,33 @@
+.. highlight:: rest
+
+:mod:`sphinx.ext.ifconfig` -- Include content based on configuration
+====================================================================
+
+.. module:: sphinx.ext.ifconfig
+ :synopsis: Include documentation content based on configuration values.
+
+This extension is quite simple, and features only one directive:
+
+.. rst:directive:: ifconfig
+
+ Include content of the directive only if the Python expression given as an
+ argument is ``True``, evaluated in the namespace of the project's
+ configuration (that is, all registered variables from :file:`conf.py` are
+ available).
+
+ For example, one could write ::
+
+ .. ifconfig:: releaselevel in ('alpha', 'beta', 'rc')
+
+ This stuff is only included in the built docs for unstable versions.
+
+ To make a custom config value known to Sphinx, use
+ :func:`~sphinx.application.Sphinx.add_config_value` in the setup function in
+ :file:`conf.py`, e.g.::
+
+ def setup(app):
+ app.add_config_value('releaselevel', '', True)
+
+ The second argument is the default value, the third should always be ``True``
+ for such values (it selects if Sphinx re-reads the documents if the value
+ changes).
diff --git a/doc/ext/inheritance.rst b/doc/ext/inheritance.rst
new file mode 100644
index 0000000..5e0a76f
--- /dev/null
+++ b/doc/ext/inheritance.rst
@@ -0,0 +1,63 @@
+.. highlight:: rest
+
+:mod:`sphinx.ext.inheritance_diagram` -- Include inheritance diagrams
+=====================================================================
+
+.. module:: sphinx.ext.inheritance_diagram
+ :synopsis: Support for displaying inheritance diagrams via graphviz.
+
+.. versionadded:: 0.6
+
+This extension allows you to include inheritance diagrams, rendered via the
+:mod:`Graphviz extension <sphinx.ext.graphviz>`.
+
+It adds this directive:
+
+.. rst:directive:: inheritance-diagram
+
+ This directive has one or more arguments, each giving a module or class
+ name. Class names can be unqualified; in that case they are taken to exist
+ in the currently described module (see :rst:dir:`py:module`).
+
+ For each given class, and each class in each given module, the base classes
+ are determined. Then, from all classes and their base classes, a graph is
+ generated which is then rendered via the graphviz extension to a directed
+ graph.
+
+ This directive supports an option called ``parts`` that, if given, must be an
+ integer, advising the directive to remove that many parts of module names
+ from the displayed names. (For example, if all your class names start with
+ ``lib.``, you can give ``:parts: 1`` to remove that prefix from the displayed
+ node names.)
+
+ It also supports a ``private-bases`` flag option; if given, private base
+ classes (those whose name starts with ``_``) will be included.
+
+ .. versionchanged:: 1.1
+ Added ``private-bases`` option; previously, all bases were always
+ included.
+
+
+New config values are:
+
+.. confval:: inheritance_graph_attrs
+
+ A dictionary of graphviz graph attributes for inheritance diagrams.
+
+ For example::
+
+ inheritance_graph_attrs = dict(rankdir="LR", size='"6.0, 8.0"',
+ fontsize=14, ratio='compress')
+
+.. confval:: inheritance_node_attrs
+
+ A dictionary of graphviz node attributes for inheritance diagrams.
+
+ For example::
+
+ inheritance_node_attrs = dict(shape='ellipse', fontsize=14, height=0.75,
+ color='dodgerblue1', style='filled')
+
+.. confval:: inheritance_edge_attrs
+
+ A dictionary of graphviz edge attributes for inheritance diagrams.
diff --git a/doc/ext/intersphinx.rst b/doc/ext/intersphinx.rst
new file mode 100644
index 0000000..7997472
--- /dev/null
+++ b/doc/ext/intersphinx.rst
@@ -0,0 +1,109 @@
+:mod:`sphinx.ext.intersphinx` -- Link to other projects' documentation
+======================================================================
+
+.. module:: sphinx.ext.intersphinx
+ :synopsis: Link to other Sphinx documentation.
+
+.. index:: pair: automatic; linking
+
+.. versionadded:: 0.5
+
+This extension can generate automatic links to the documentation of objects in
+other projects.
+
+Usage is simple: whenever Sphinx encounters a cross-reference that has no
+matching target in the current documentation set, it looks for targets in the
+documentation sets configured in :confval:`intersphinx_mapping`. A reference
+like ``:py:class:`zipfile.ZipFile``` can then link to the Python documentation
+for the ZipFile class, without you having to specify where it is located
+exactly.
+
+When using the "new" format (see below), you can even force lookup in a foreign
+set by prefixing the link target appropriately. A link like ``:ref:`comparison
+manual <python:comparisons>``` will then link to the label "comparisons" in the
+doc set "python", if it exists.
+
+Behind the scenes, this works as follows:
+
+* Each Sphinx HTML build creates a file named :file:`objects.inv` that contains
+ a mapping from object names to URIs relative to the HTML set's root.
+
+* Projects using the Intersphinx extension can specify the location of such
+ mapping files in the :confval:`intersphinx_mapping` config value. The mapping
+ will then be used to resolve otherwise missing references to objects into
+ links to the other documentation.
+
+* By default, the mapping file is assumed to be at the same location as the rest
+ of the documentation; however, the location of the mapping file can also be
+ specified individually, e.g. if the docs should be buildable without Internet
+ access.
+
+To use intersphinx linking, add ``'sphinx.ext.intersphinx'`` to your
+:confval:`extensions` config value, and use these new config values to activate
+linking:
+
+.. confval:: intersphinx_mapping
+
+ This config value contains the locations and names of other projects that
+ should be linked to in this documentation.
+
+ Relative local paths for target locations are taken as relative to the base
+ of the built documentation, while relative local paths for inventory
+ locations are taken as relative to the source directory.
+
+ When fetching remote inventory files, proxy settings will be read from
+ the ``$HTTP_PROXY`` environment variable.
+
+ **Old format for this config value**
+
+ This is the format used before Sphinx 1.0. It is still recognized.
+
+ A dictionary mapping URIs to either ``None`` or an URI. The keys are the
+ base URI of the foreign Sphinx documentation sets and can be local paths or
+ HTTP URIs. The values indicate where the inventory file can be found: they
+ can be ``None`` (at the same location as the base URI) or another local or
+ HTTP URI.
+
+ **New format for this config value**
+
+ .. versionadded:: 1.0
+
+ A dictionary mapping unique identifiers to a tuple ``(target, inventory)``.
+ Each ``target`` is the base URI of a foreign Sphinx documentation set and can
+ be a local path or an HTTP URI. The ``inventory`` indicates where the
+ inventory file can be found: it can be ``None`` (at the same location as
+ the base URI) or another local or HTTP URI.
+
+ The unique identifier can be used to prefix cross-reference targets, so that
+ it is clear which intersphinx set the target belongs to. A link like
+ ``:ref:`comparison manual <python:comparisons>``` will link to the label
+ "comparisons" in the doc set "python", if it exists.
+
+ **Example**
+
+ To add links to modules and objects in the Python standard library
+ documentation, use::
+
+ intersphinx_mapping = {'python': ('http://docs.python.org/3.2', None)}
+
+ This will download the corresponding :file:`objects.inv` file from the
+ Internet and generate links to the pages under the given URI. The downloaded
+ inventory is cached in the Sphinx environment, so it must be redownloaded
+ whenever you do a full rebuild.
+
+ A second example, showing the meaning of a non-``None`` value of the second
+ tuple item::
+
+ intersphinx_mapping = {'python': ('http://docs.python.org/3.2',
+ 'python-inv.txt')}
+
+ This will read the inventory from :file:`python-inv.txt` in the source
+ directory, but still generate links to the pages under
+ ``http://docs.python.org/3.2``. It is up to you to update the inventory file as
+ new objects are added to the Python documentation.
+
+.. confval:: intersphinx_cache_limit
+
+ The maximum number of days to cache remote inventories. The default is
+ ``5``, meaning five days. Set this to a negative value to cache inventories
+ for unlimited time.
diff --git a/doc/ext/linkcode.rst b/doc/ext/linkcode.rst
new file mode 100644
index 0000000..a69a5b1
--- /dev/null
+++ b/doc/ext/linkcode.rst
@@ -0,0 +1,46 @@
+:mod:`sphinx.ext.linkcode` -- Add external links to source code
+===============================================================
+
+.. module:: sphinx.ext.linkcode
+ :synopsis: Add external links to source code.
+.. moduleauthor:: Pauli Virtanen
+
+.. versionadded:: 1.2
+
+This extension looks at your object descriptions (``.. class::``,
+``.. function::`` etc.) and adds external links to code hosted
+somewhere on the web. The intent is similar to the
+``sphinx.ext.viewcode`` extension, but assumes the source code can be
+found somewhere on the Internet.
+
+In your configuration, you need to specify a :confval:`linkcode_resolve`
+function that returns an URL based on the object.
+
+.. confval:: linkcode_resolve
+
+ This is a function ``linkcode_resolve(domain, info)``,
+ which should return the URL to source code corresponding to
+ the object in given domain with given information.
+
+ The function should return ``None`` if no link is to be added.
+
+ The argument ``domain`` specifies the language domain the object is
+ in. ``info`` is a dictionary with the following keys guaranteed to
+ be present (dependent on the domain):
+
+ - ``py``: ``module`` (name of the module), ``fullname`` (name of the object)
+ - ``c``: ``names`` (list of names for the object)
+ - ``cpp``: ``names`` (list of names for the object)
+ - ``javascript``: ``object`` (name of the object), ``fullname`` (name of the item)
+
+ Example:
+
+ .. code-block:: python
+
+ def linkcode_resolve(domain, info):
+ if domain != 'py':
+ return None
+ if not info['module']:
+ return None
+ filename = info['module'].replace('.', '/')
+ return "http://somesite/sourcerepo/%s.py" % filename
diff --git a/doc/ext/math.rst b/doc/ext/math.rst
new file mode 100644
index 0000000..8b2924c
--- /dev/null
+++ b/doc/ext/math.rst
@@ -0,0 +1,241 @@
+.. highlight:: rest
+
+Math support in Sphinx
+======================
+
+.. module:: sphinx.ext.mathbase
+ :synopsis: Common math support for pngmath and mathjax / jsmath.
+
+.. versionadded:: 0.5
+
+Since mathematical notation isn't natively supported by HTML in any way, Sphinx
+supports math in documentation with several extensions.
+
+The basic math support is contained in :mod:`sphinx.ext.mathbase`. Other math
+support extensions should, if possible, reuse that support too.
+
+.. note::
+
+ :mod:`.mathbase` is not meant to be added to the :confval:`extensions` config
+ value, instead, use either :mod:`sphinx.ext.pngmath` or
+ :mod:`sphinx.ext.mathjax` as described below.
+
+The input language for mathematics is LaTeX markup. This is the de-facto
+standard for plain-text math notation and has the added advantage that no
+further translation is necessary when building LaTeX output.
+
+Keep in mind that when you put math markup in **Python docstrings** read by
+:mod:`autodoc <sphinx.ext.autodoc>`, you either have to double all backslashes,
+or use Python raw strings (``r"raw"``).
+
+:mod:`.mathbase` defines these new markup elements:
+
+.. rst:role:: math
+
+ Role for inline math. Use like this::
+
+ Since Pythagoras, we know that :math:`a^2 + b^2 = c^2`.
+
+.. rst:directive:: math
+
+ Directive for displayed math (math that takes the whole line for itself).
+
+ The directive supports multiple equations, which should be separated by a
+ blank line::
+
+ .. math::
+
+ (a + b)^2 = a^2 + 2ab + b^2
+
+ (a - b)^2 = a^2 - 2ab + b^2
+
+ In addition, each single equation is set within a ``split`` environment,
+ which means that you can have multiple aligned lines in an equation,
+ aligned at ``&`` and separated by ``\\``::
+
+ .. math::
+
+ (a + b)^2 &= (a + b)(a + b) \\
+ &= a^2 + 2ab + b^2
+
+ For more details, look into the documentation of the `AmSMath LaTeX
+ package`_.
+
+ When the math is only one line of text, it can also be given as a directive
+ argument::
+
+ .. math:: (a + b)^2 = a^2 + 2ab + b^2
+
+ Normally, equations are not numbered. If you want your equation to get a
+ number, use the ``label`` option. When given, it selects an internal label
+ for the equation, by which it can be cross-referenced, and causes an equation
+ number to be issued. See :rst:role:`eqref` for an example. The numbering
+ style depends on the output format.
+
+ There is also an option ``nowrap`` that prevents any wrapping of the given
+ math in a math environment. When you give this option, you must make sure
+ yourself that the math is properly set up. For example::
+
+ .. math::
+ :nowrap:
+
+ \begin{eqnarray}
+ y & = & ax^2 + bx + c \\
+ f(x) & = & x^2 + 2xy + y^2
+ \end{eqnarray}
+
+.. rst:role:: eq
+
+ Role for cross-referencing equations via their label. This currently works
+ only within the same document. Example::
+
+ .. math:: e^{i\pi} + 1 = 0
+ :label: euler
+
+ Euler's identity, equation :eq:`euler`, was elected one of the most
+ beautiful mathematical formulas.
+
+
+:mod:`sphinx.ext.pngmath` -- Render math as PNG images
+------------------------------------------------------
+
+.. module:: sphinx.ext.pngmath
+ :synopsis: Render math as PNG images.
+
+This extension renders math via LaTeX and dvipng_ into PNG images. This of
+course means that the computer where the docs are built must have both programs
+available.
+
+There are various config values you can set to influence how the images are
+built:
+
+.. confval:: pngmath_latex
+
+ The command name with which to invoke LaTeX. The default is ``'latex'``; you
+ may need to set this to a full path if ``latex`` is not in the executable
+ search path.
+
+ Since this setting is not portable from system to system, it is normally not
+ useful to set it in ``conf.py``; rather, giving it on the
+ :program:`sphinx-build` command line via the :option:`-D` option should be
+ preferable, like this::
+
+ sphinx-build -b html -D pngmath_latex=C:\tex\latex.exe . _build/html
+
+ .. versionchanged:: 0.5.1
+ This value should only contain the path to the latex executable, not
+ further arguments; use :confval:`pngmath_latex_args` for that purpose.
+
+.. confval:: pngmath_dvipng
+
+ The command name with which to invoke ``dvipng``. The default is
+ ``'dvipng'``; you may need to set this to a full path if ``dvipng`` is not in
+ the executable search path.
+
+.. confval:: pngmath_latex_args
+
+ Additional arguments to give to latex, as a list. The default is an empty
+ list.
+
+ .. versionadded:: 0.5.1
+
+.. confval:: pngmath_latex_preamble
+
+ Additional LaTeX code to put into the preamble of the short LaTeX files that
+ are used to translate the math snippets. This is empty by default. Use it
+ e.g. to add more packages whose commands you want to use in the math.
+
+.. confval:: pngmath_dvipng_args
+
+ Additional arguments to give to dvipng, as a list. The default value is
+ ``['-gamma', '1.5', '-D', '110', '-bg', 'Transparent']`` which makes the
+ image a bit darker and larger then it is by default, and produces PNGs with a
+ transparent background.
+
+ .. versionchanged:: 1.2
+ Now includes ``-bg Transparent`` by default.
+
+.. confval:: pngmath_use_preview
+
+ ``dvipng`` has the ability to determine the "depth" of the rendered text: for
+ example, when typesetting a fraction inline, the baseline of surrounding text
+ should not be flush with the bottom of the image, rather the image should
+ extend a bit below the baseline. This is what TeX calls "depth". When this
+ is enabled, the images put into the HTML document will get a
+ ``vertical-align`` style that correctly aligns the baselines.
+
+ Unfortunately, this only works when the `preview-latex package`_ is
+ installed. Therefore, the default for this option is ``False``.
+
+.. confval:: pngmath_add_tooltips
+
+ Default: true. If false, do not add the LaTeX code as an "alt" attribute for
+ math images.
+
+ .. versionadded:: 1.1
+
+
+:mod:`sphinx.ext.mathjax` -- Render math via JavaScript
+-------------------------------------------------------
+
+.. module:: sphinx.ext.mathjax
+ :synopsis: Render math using JavaScript via MathJax.
+
+.. versionadded:: 1.1
+
+This extension puts math as-is into the HTML files. The JavaScript package
+MathJax_ is then loaded and transforms the LaTeX markup to readable math live in
+the browser.
+
+Because MathJax (and the necessary fonts) is very large, it is not included in
+Sphinx.
+
+.. confval:: mathjax_path
+
+ The path to the JavaScript file to include in the HTML files in order to load
+ MathJax.
+
+ The default is the ``http://`` URL that loads the JS files from the `MathJax
+ CDN <http://docs.mathjax.org/en/latest/start.html>`_. If you want MathJax to
+ be available offline, you have to donwload it and set this value to a
+ different path.
+
+ The path can be absolute or relative; if it is relative, it is relative to
+ the ``_static`` directory of the built docs.
+
+ For example, if you put MathJax into the static path of the Sphinx docs, this
+ value would be ``MathJax/MathJax.js``. If you host more than one Sphinx
+ documentation set on one server, it is advisable to install MathJax in a
+ shared location.
+
+ You can also give a full ``http://`` URL different from the CDN URL.
+
+
+:mod:`sphinx.ext.jsmath` -- Render math via JavaScript
+------------------------------------------------------
+
+.. module:: sphinx.ext.jsmath
+ :synopsis: Render math using JavaScript via JSMath.
+
+This extension works just as the MathJax extension does, but uses the older
+package jsMath_. It provides this config value:
+
+.. confval:: jsmath_path
+
+ The path to the JavaScript file to include in the HTML files in order to load
+ JSMath. There is no default.
+
+ The path can be absolute or relative; if it is relative, it is relative to
+ the ``_static`` directory of the built docs.
+
+ For example, if you put JSMath into the static path of the Sphinx docs, this
+ value would be ``jsMath/easy/load.js``. If you host more than one
+ Sphinx documentation set on one server, it is advisable to install jsMath in
+ a shared location.
+
+
+.. _dvipng: http://savannah.nongnu.org/projects/dvipng/
+.. _MathJax: http://www.mathjax.org/
+.. _jsMath: http://www.math.union.edu/~dpvc/jsmath/
+.. _preview-latex package: http://www.gnu.org/software/auctex/preview-latex.html
+.. _AmSMath LaTeX package: http://www.ams.org/publications/authors/tex/amslatex
diff --git a/doc/ext/oldcmarkup.rst b/doc/ext/oldcmarkup.rst
new file mode 100644
index 0000000..0fdd9fe
--- /dev/null
+++ b/doc/ext/oldcmarkup.rst
@@ -0,0 +1,35 @@
+:mod:`sphinx.ext.oldcmarkup` -- Compatibility extension for old C markup
+========================================================================
+
+.. module:: sphinx.ext.oldcmarkup
+ :synopsis: Allow further use of the pre-domain C markup
+.. moduleauthor:: Georg Brandl
+
+.. versionadded:: 1.0
+
+
+This extension is a transition helper for projects that used the old
+(pre-domain) C markup, i.e. the directives like ``cfunction`` and roles like
+``cfunc``. Since the introduction of domains, they must be called by their
+fully-qualified name (``c:function`` and ``c:func``, respectively) or, with the
+default domain set to ``c``, by their new name (``function`` and ``func``).
+(See :ref:`c-domain` for the details.)
+
+If you activate this extension, it will register the old names, and you can
+use them like before Sphinx 1.0. The directives are:
+
+- ``cfunction``
+- ``cmember``
+- ``cmacro``
+- ``ctype``
+- ``cvar``
+
+The roles are:
+
+- ``cdata``
+- ``cfunc``
+- ``cmacro``
+- ``ctype``
+
+However, it is advised to migrate to the new markup -- this extension is a
+compatibility convenience and will disappear in a future version of Sphinx.
diff --git a/doc/ext/todo.rst b/doc/ext/todo.rst
new file mode 100644
index 0000000..349d286
--- /dev/null
+++ b/doc/ext/todo.rst
@@ -0,0 +1,30 @@
+:mod:`sphinx.ext.todo` -- Support for todo items
+================================================
+
+.. module:: sphinx.ext.todo
+ :synopsis: Allow inserting todo items into documents.
+.. moduleauthor:: Daniel Bültmann
+
+.. versionadded:: 0.5
+
+There are two additional directives when using this extension:
+
+.. rst:directive:: todo
+
+ Use this directive like, for example, :rst:dir:`note`.
+
+ It will only show up in the output if :confval:`todo_include_todos` is true.
+
+
+.. rst:directive:: todolist
+
+ This directive is replaced by a list of all todo directives in the whole
+ documentation, if :confval:`todo_include_todos` is true.
+
+
+There is also an additional config value:
+
+.. confval:: todo_include_todos
+
+ If this is ``True``, :rst:dir:`todo` and :rst:dir:`todolist` produce output, else
+ they produce nothing. The default is ``False``.
diff --git a/doc/ext/viewcode.rst b/doc/ext/viewcode.rst
new file mode 100644
index 0000000..ba6c8f8
--- /dev/null
+++ b/doc/ext/viewcode.rst
@@ -0,0 +1,19 @@
+:mod:`sphinx.ext.viewcode` -- Add links to highlighted source code
+==================================================================
+
+.. module:: sphinx.ext.viewcode
+ :synopsis: Add links to a highlighted version of the source code.
+.. moduleauthor:: Georg Brandl
+
+.. versionadded:: 1.0
+
+
+This extension looks at your Python object descriptions (``.. class::``,
+``.. function::`` etc.) and tries to find the source files where the objects are
+contained. When found, a separate HTML page will be output for each module with
+a highlighted version of the source code, and a link will be added to all object
+descriptions that leads to the source code of the described object. A link back
+from the source to the description will also be inserted.
+
+There are currently no configuration values for this extension; you just need to
+add ``'sphinx.ext.viewcode'`` to your :confval:`extensions` value for it to work.
diff --git a/doc/extdev/appapi.rst b/doc/extdev/appapi.rst
new file mode 100644
index 0000000..0321f5e
--- /dev/null
+++ b/doc/extdev/appapi.rst
@@ -0,0 +1,595 @@
+.. highlight:: rest
+
+Application API
+===============
+
+.. module:: sphinx.application
+ :synopsis: Application class and extensibility interface.
+
+
+Each Sphinx extension is a Python module with at least a :func:`setup` function.
+This function is called at initialization time with one argument, the
+application object representing the Sphinx process.
+
+.. class:: Sphinx
+
+ This application object has the public API described in the following.
+
+Extension setup
+---------------
+
+These methods are usually called in an extension's ``setup()`` function.
+
+Examples of using the Sphinx extension API can be seen in the :mod:`sphinx.ext`
+package.
+
+.. method:: Sphinx.setup_extension(name)
+
+ Load the extension given by the module *name*. Use this if your extension
+ needs the features provided by another extension.
+
+.. method:: Sphinx.add_builder(builder)
+
+ Register a new builder. *builder* must be a class that inherits from
+ :class:`~sphinx.builders.Builder`.
+
+.. method:: Sphinx.add_config_value(name, default, rebuild)
+
+ Register a configuration value. This is necessary for Sphinx to recognize
+ new values and set default values accordingly. The *name* should be prefixed
+ with the extension name, to avoid clashes. The *default* value can be any
+ Python object. The string value *rebuild* must be one of those values:
+
+ * ``'env'`` if a change in the setting only takes effect when a document is
+ parsed -- this means that the whole environment must be rebuilt.
+ * ``'html'`` if a change in the setting needs a full rebuild of HTML
+ documents.
+ * ``''`` if a change in the setting will not need any special rebuild.
+
+ .. versionchanged:: 0.4
+ If the *default* value is a callable, it will be called with the config
+ object as its argument in order to get the default value. This can be
+ used to implement config values whose default depends on other values.
+
+ .. versionchanged:: 0.6
+ Changed *rebuild* from a simple boolean (equivalent to ``''`` or
+ ``'env'``) to a string. However, booleans are still accepted and
+ converted internally.
+
+.. method:: Sphinx.add_domain(domain)
+
+ Make the given *domain* (which must be a class; more precisely, a subclass of
+ :class:`~sphinx.domains.Domain`) known to Sphinx.
+
+ .. versionadded:: 1.0
+
+.. method:: Sphinx.override_domain(domain)
+
+ Make the given *domain* class known to Sphinx, assuming that there is already
+ a domain with its ``.name``. The new domain must be a subclass of the
+ existing one.
+
+ .. versionadded:: 1.0
+
+.. method:: Sphinx.add_index_to_domain(domain, index)
+
+ Add a custom *index* class to the domain named *domain*. *index* must be a
+ subclass of :class:`~sphinx.domains.Index`.
+
+ .. versionadded:: 1.0
+
+.. method:: Sphinx.add_event(name)
+
+ Register an event called *name*. This is needed to be able to emit it.
+
+.. method:: Sphinx.add_node(node, **kwds)
+
+ Register a Docutils node class. This is necessary for Docutils internals.
+ It may also be used in the future to validate nodes in the parsed documents.
+
+ Node visitor functions for the Sphinx HTML, LaTeX, text and manpage writers
+ can be given as keyword arguments: the keyword must be one or more of
+ ``'html'``, ``'latex'``, ``'text'``, ``'man'``, ``'texinfo'``, the value a
+ 2-tuple of ``(visit, depart)`` methods. ``depart`` can be ``None`` if the
+ ``visit`` function raises :exc:`docutils.nodes.SkipNode`. Example:
+
+ .. code-block:: python
+
+ class math(docutils.nodes.Element): pass
+
+ def visit_math_html(self, node):
+ self.body.append(self.starttag(node, 'math'))
+ def depart_math_html(self, node):
+ self.body.append('</math>')
+
+ app.add_node(math, html=(visit_math_html, depart_math_html))
+
+ Obviously, translators for which you don't specify visitor methods will choke
+ on the node when encountered in a document to translate.
+
+ .. versionchanged:: 0.5
+ Added the support for keyword arguments giving visit functions.
+
+.. method:: Sphinx.add_directive(name, func, content, arguments, **options)
+ Sphinx.add_directive(name, directiveclass)
+
+ Register a Docutils directive. *name* must be the prospective directive
+ name. There are two possible ways to write a directive:
+
+ * In the docutils 0.4 style, *obj* is the directive function. *content*,
+ *arguments* and *options* are set as attributes on the function and
+ determine whether the directive has content, arguments and options,
+ respectively. **This style is deprecated.**
+
+ * In the docutils 0.5 style, *directiveclass* is the directive class. It
+ must already have attributes named *has_content*, *required_arguments*,
+ *optional_arguments*, *final_argument_whitespace* and *option_spec* that
+ correspond to the options for the function way. See `the Docutils docs
+ <http://docutils.sourceforge.net/docs/howto/rst-directives.html>`_ for
+ details.
+
+ The directive class must inherit from the class
+ ``docutils.parsers.rst.Directive``.
+
+ For example, the (already existing) :rst:dir:`literalinclude` directive would be
+ added like this:
+
+ .. code-block:: python
+
+ from docutils.parsers.rst import directives
+ add_directive('literalinclude', literalinclude_directive,
+ content = 0, arguments = (1, 0, 0),
+ linenos = directives.flag,
+ language = direcitves.unchanged,
+ encoding = directives.encoding)
+
+ .. versionchanged:: 0.6
+ Docutils 0.5-style directive classes are now supported.
+
+.. method:: Sphinx.add_directive_to_domain(domain, name, func, content, arguments, **options)
+ Sphinx.add_directive_to_domain(domain, name, directiveclass)
+
+ Like :meth:`add_directive`, but the directive is added to the domain named
+ *domain*.
+
+ .. versionadded:: 1.0
+
+.. method:: Sphinx.add_role(name, role)
+
+ Register a Docutils role. *name* must be the role name that occurs in the
+ source, *role* the role function (see the `Docutils documentation
+ <http://docutils.sourceforge.net/docs/howto/rst-roles.html>`_ on details).
+
+.. method:: Sphinx.add_role_to_domain(domain, name, role)
+
+ Like :meth:`add_role`, but the role is added to the domain named *domain*.
+
+ .. versionadded:: 1.0
+
+.. method:: Sphinx.add_generic_role(name, nodeclass)
+
+ Register a Docutils role that does nothing but wrap its contents in the
+ node given by *nodeclass*.
+
+ .. versionadded:: 0.6
+
+.. method:: Sphinx.add_object_type(directivename, rolename, indextemplate='', parse_node=None, \
+ ref_nodeclass=None, objname='', doc_field_types=[])
+
+ This method is a very convenient way to add a new :term:`object` type that
+ can be cross-referenced. It will do this:
+
+ * Create a new directive (called *directivename*) for documenting an object.
+ It will automatically add index entries if *indextemplate* is nonempty; if
+ given, it must contain exactly one instance of ``%s``. See the example
+ below for how the template will be interpreted.
+ * Create a new role (called *rolename*) to cross-reference to these
+ object descriptions.
+ * If you provide *parse_node*, it must be a function that takes a string and
+ a docutils node, and it must populate the node with children parsed from
+ the string. It must then return the name of the item to be used in
+ cross-referencing and index entries. See the :file:`conf.py` file in the
+ source for this documentation for an example.
+ * The *objname* (if not given, will default to *directivename*) names the
+ type of object. It is used when listing objects, e.g. in search results.
+
+ For example, if you have this call in a custom Sphinx extension::
+
+ app.add_object_type('directive', 'dir', 'pair: %s; directive')
+
+ you can use this markup in your documents::
+
+ .. rst:directive:: function
+
+ Document a function.
+
+ <...>
+
+ See also the :rst:dir:`function` directive.
+
+ For the directive, an index entry will be generated as if you had prepended ::
+
+ .. index:: pair: function; directive
+
+ The reference node will be of class ``literal`` (so it will be rendered in a
+ proportional font, as appropriate for code) unless you give the *ref_nodeclass*
+ argument, which must be a docutils node class (most useful are
+ ``docutils.nodes.emphasis`` or ``docutils.nodes.strong`` -- you can also use
+ ``docutils.nodes.generated`` if you want no further text decoration).
+
+ For the role content, you have the same syntactical possibilities as for
+ standard Sphinx roles (see :ref:`xref-syntax`).
+
+ This method is also available under the deprecated alias
+ ``add_description_unit``.
+
+.. method:: Sphinx.add_crossref_type(directivename, rolename, indextemplate='', ref_nodeclass=None, objname='')
+
+ This method is very similar to :meth:`add_object_type` except that the
+ directive it generates must be empty, and will produce no output.
+
+ That means that you can add semantic targets to your sources, and refer to
+ them using custom roles instead of generic ones (like :rst:role:`ref`). Example
+ call::
+
+ app.add_crossref_type('topic', 'topic', 'single: %s', docutils.nodes.emphasis)
+
+ Example usage::
+
+ .. topic:: application API
+
+ The application API
+ -------------------
+
+ <...>
+
+ See also :topic:`this section <application API>`.
+
+ (Of course, the element following the ``topic`` directive needn't be a
+ section.)
+
+.. method:: Sphinx.add_transform(transform)
+
+ Add the standard docutils :class:`Transform` subclass *transform* to the list
+ of transforms that are applied after Sphinx parses a reST document.
+
+.. method:: Sphinx.add_javascript(filename)
+
+ Add *filename* to the list of JavaScript files that the default HTML template
+ will include. The filename must be relative to the HTML static path, see
+ :confval:`the docs for the config value <html_static_path>`. A full URI with
+ scheme, like ``http://example.org/foo.js``, is also supported.
+
+ .. versionadded:: 0.5
+
+.. method:: Sphinx.add_stylesheet(filename)
+
+ Add *filename* to the list of CSS files that the default HTML template will
+ include. Like for :meth:`add_javascript`, the filename must be relative to
+ the HTML static path, or a full URI with scheme.
+
+ .. versionadded:: 1.0
+
+.. method:: Sphinx.add_lexer(alias, lexer)
+
+ Use *lexer*, which must be an instance of a Pygments lexer class, to
+ highlight code blocks with the given language *alias*.
+
+ .. versionadded:: 0.6
+
+.. method:: Sphinx.add_autodocumenter(cls)
+
+ Add *cls* as a new documenter class for the :mod:`sphinx.ext.autodoc`
+ extension. It must be a subclass of :class:`sphinx.ext.autodoc.Documenter`.
+ This allows to auto-document new types of objects. See the source of the
+ autodoc module for examples on how to subclass :class:`Documenter`.
+
+ .. XXX add real docs for Documenter and subclassing
+
+ .. versionadded:: 0.6
+
+.. method:: Sphinx.add_autodoc_attrgetter(type, getter)
+
+ Add *getter*, which must be a function with an interface compatible to the
+ :func:`getattr` builtin, as the autodoc attribute getter for objects that are
+ instances of *type*. All cases where autodoc needs to get an attribute of a
+ type are then handled by this function instead of :func:`getattr`.
+
+ .. versionadded:: 0.6
+
+.. method:: Sphinx.add_search_language(cls)
+
+ Add *cls*, which must be a subclass of :class:`sphinx.search.SearchLanguage`,
+ as a support language for building the HTML full-text search index. The
+ class must have a *lang* attribute that indicates the language it should be
+ used for. See :confval:`html_search_language`.
+
+ .. versionadded:: 1.1
+
+.. method:: Sphinx.require_sphinx(version)
+
+ Compare *version* (which must be a ``major.minor`` version string,
+ e.g. ``'1.1'``) with the version of the running Sphinx, and abort the build
+ when it is too old.
+
+ .. versionadded:: 1.0
+
+.. method:: Sphinx.connect(event, callback)
+
+ Register *callback* to be called when *event* is emitted. For details on
+ available core events and the arguments of callback functions, please see
+ :ref:`events`.
+
+ The method returns a "listener ID" that can be used as an argument to
+ :meth:`disconnect`.
+
+.. method:: Sphinx.disconnect(listener_id)
+
+ Unregister callback *listener_id*.
+
+
+.. exception:: ExtensionError
+
+ All these methods raise this exception if something went wrong with the
+ extension API.
+
+
+Emitting events
+---------------
+
+.. method:: Sphinx.emit(event, *arguments)
+
+ Emit *event* and pass *arguments* to the callback functions. Return the
+ return values of all callbacks as a list. Do not emit core Sphinx events
+ in extensions!
+
+.. method:: Sphinx.emit_firstresult(event, *arguments)
+
+ Emit *event* and pass *arguments* to the callback functions. Return the
+ result of the first callback that doesn't return ``None``.
+
+ .. versionadded:: 0.5
+
+
+Producing messages / logging
+----------------------------
+
+The application object also provides support for emitting leveled messages.
+
+.. note::
+
+ There is no "error" call: in Sphinx, errors are defined as things that stop
+ the build; just raise an exception (:exc:`sphinx.errors.SphinxError` or a
+ custom subclass) to do that.
+
+.. automethod:: Sphinx.warn
+
+.. automethod:: Sphinx.info
+
+.. automethod:: Sphinx.verbose
+
+.. automethod:: Sphinx.debug
+
+.. automethod:: Sphinx.debug2
+
+
+.. _events:
+
+Sphinx core events
+------------------
+
+These events are known to the core. The arguments shown are given to the
+registered event handlers. Use :meth:`.connect` in an extension's ``setup``
+function (note that ``conf.py`` can also have a ``setup`` function) to connect
+handlers to the events. Example:
+
+.. code-block:: python
+
+ def source_read_handler(app, docname, source):
+ print('do something here...')
+
+ def setup(app):
+ app.connect('source-read', source_read_handler)
+
+
+.. event:: builder-inited (app)
+
+ Emitted when the builder object has been created. It is available as
+ ``app.builder``.
+
+.. event:: env-get-outdated (app, env, added, changed, removed)
+
+ Emitted when the environment determines which source files have changed and
+ should be re-read. *added*, *changed* and *removed* are sets of docnames
+ that the environment has determined. You can return a list of docnames to
+ re-read in addition to these.
+
+ .. versionadded:: 1.1
+
+.. event:: env-purge-doc (app, env, docname)
+
+ Emitted when all traces of a source file should be cleaned from the
+ environment, that is, if the source file is removed or before it is freshly
+ read. This is for extensions that keep their own caches in attributes of the
+ environment.
+
+ For example, there is a cache of all modules on the environment. When a
+ source file has been changed, the cache's entries for the file are cleared,
+ since the module declarations could have been removed from the file.
+
+ .. versionadded:: 0.5
+
+.. event:: source-read (app, docname, source)
+
+ Emitted when a source file has been read. The *source* argument is a list
+ whose single element is the contents of the source file. You can process the
+ contents and replace this item to implement source-level transformations.
+
+ For example, if you want to use ``$`` signs to delimit inline math, like in
+ LaTeX, you can use a regular expression to replace ``$...$`` by
+ ``:math:`...```.
+
+ .. versionadded:: 0.5
+
+.. event:: doctree-read (app, doctree)
+
+ Emitted when a doctree has been parsed and read by the environment, and is
+ about to be pickled. The *doctree* can be modified in-place.
+
+.. event:: missing-reference (app, env, node, contnode)
+
+ Emitted when a cross-reference to a Python module or object cannot be
+ resolved. If the event handler can resolve the reference, it should return a
+ new docutils node to be inserted in the document tree in place of the node
+ *node*. Usually this node is a :class:`reference` node containing *contnode*
+ as a child.
+
+ :param env: The build environment (``app.builder.env``).
+ :param node: The :class:`pending_xref` node to be resolved. Its attributes
+ ``reftype``, ``reftarget``, ``modname`` and ``classname`` attributes
+ determine the type and target of the reference.
+ :param contnode: The node that carries the text and formatting inside the
+ future reference and should be a child of the returned reference node.
+
+ .. versionadded:: 0.5
+
+.. event:: doctree-resolved (app, doctree, docname)
+
+ Emitted when a doctree has been "resolved" by the environment, that is, all
+ references have been resolved and TOCs have been inserted. The *doctree* can
+ be modified in place.
+
+ Here is the place to replace custom nodes that don't have visitor methods in
+ the writers, so that they don't cause errors when the writers encounter them.
+
+.. event:: env-updated (app, env)
+
+ Emitted when the :meth:`update` method of the build environment has
+ completed, that is, the environment and all doctrees are now up-to-date.
+
+ .. versionadded:: 0.5
+
+.. event:: html-collect-pages (app)
+
+ Emitted when the HTML builder is starting to write non-document pages. You
+ can add pages to write by returning an iterable from this event consisting of
+ ``(pagename, context, templatename)``.
+
+ .. versionadded:: 1.0
+
+.. event:: html-page-context (app, pagename, templatename, context, doctree)
+
+ Emitted when the HTML builder has created a context dictionary to render a
+ template with -- this can be used to add custom elements to the context.
+
+ The *pagename* argument is the canonical name of the page being rendered,
+ that is, without ``.html`` suffix and using slashes as path separators. The
+ *templatename* is the name of the template to render, this will be
+ ``'page.html'`` for all pages from reST documents.
+
+ The *context* argument is a dictionary of values that are given to the
+ template engine to render the page and can be modified to include custom
+ values. Keys must be strings.
+
+ The *doctree* argument will be a doctree when the page is created from a reST
+ documents; it will be ``None`` when the page is created from an HTML template
+ alone.
+
+ .. versionadded:: 0.4
+
+.. event:: build-finished (app, exception)
+
+ Emitted when a build has finished, before Sphinx exits, usually used for
+ cleanup. This event is emitted even when the build process raised an
+ exception, given as the *exception* argument. The exception is reraised in
+ the application after the event handlers have run. If the build process
+ raised no exception, *exception* will be ``None``. This allows to customize
+ cleanup actions depending on the exception status.
+
+ .. versionadded:: 0.5
+
+
+Checking the Sphinx version
+---------------------------
+
+.. currentmodule:: sphinx
+
+Use this to adapt your extension to API changes in Sphinx.
+
+.. data:: version_info
+
+ A tuple of five elements; for Sphinx version 1.2.1 beta 3 this would be
+ ``(1, 2, 1, 'beta', 3)``.
+
+ .. versionadded:: 1.2
+ Before version 1.2, check the string ``sphinx.__version__``.
+
+
+The Config object
+-----------------
+
+.. module:: sphinx.config
+
+.. class:: Config
+
+ The config object makes the values of all config values available as
+ attributes.
+
+ It is available as the ``config`` attribute on the application and
+ environment objects. For example, to get the value of :confval:`language`,
+ use either ``app.config.language`` or ``env.config.language``.
+
+
+.. _template-bridge:
+
+The template bridge
+-------------------
+
+.. currentmodule:: sphinx.application
+
+.. autoclass:: TemplateBridge
+ :members:
+
+
+.. _exceptions:
+
+Exceptions
+----------
+
+.. module:: sphinx.errors
+
+.. exception:: SphinxError
+
+ This is the base class for "nice" exceptions. When such an exception is
+ raised, Sphinx will abort the build and present the exception category and
+ message to the user.
+
+ Extensions are encouraged to derive from this exception for their custom
+ errors.
+
+ Exceptions *not* derived from :exc:`SphinxError` are treated as unexpected
+ and shown to the user with a part of the traceback (and the full traceback
+ saved in a temporary file).
+
+ .. attribute:: category
+
+ Description of the exception "category", used in converting the exception
+ to a string ("category: message"). Should be set accordingly in
+ subclasses.
+
+.. exception:: ConfigError
+
+ Used for erroneous values or nonsensical combinations of configuration
+ values.
+
+.. exception:: ExtensionError
+
+ Used for errors in setting up extensions.
+
+.. exception:: ThemeError
+
+ Used for errors to do with themes.
+
+.. exception:: VersionRequirementError
+
+ Raised when the docs require a higher Sphinx version than the current one.
diff --git a/doc/extdev/builderapi.rst b/doc/extdev/builderapi.rst
new file mode 100644
index 0000000..cd8688a
--- /dev/null
+++ b/doc/extdev/builderapi.rst
@@ -0,0 +1,30 @@
+.. _writing-builders:
+
+Builder API
+===========
+
+.. todo:: Expand this.
+
+.. currentmodule:: sphinx.builders
+
+.. class:: Builder
+
+ This is the base class for all builders.
+
+ These methods are predefined and will be called from the application:
+
+ .. automethod:: get_relative_uri
+ .. automethod:: build_all
+ .. automethod:: build_specific
+ .. automethod:: build_update
+ .. automethod:: build
+
+ These methods can be overridden in concrete builder classes:
+
+ .. automethod:: init
+ .. automethod:: get_outdated_docs
+ .. automethod:: get_target_uri
+ .. automethod:: prepare_writing
+ .. automethod:: write_doc
+ .. automethod:: finish
+
diff --git a/doc/extdev/domainapi.rst b/doc/extdev/domainapi.rst
new file mode 100644
index 0000000..d6ecf06
--- /dev/null
+++ b/doc/extdev/domainapi.rst
@@ -0,0 +1,14 @@
+.. _domain-api:
+
+Domain API
+----------
+
+.. module:: sphinx.domains
+
+.. autoclass:: Domain
+ :members:
+
+.. autoclass:: ObjType
+
+.. autoclass:: Index
+ :members:
diff --git a/doc/extdev/envapi.rst b/doc/extdev/envapi.rst
new file mode 100644
index 0000000..84ad3e0
--- /dev/null
+++ b/doc/extdev/envapi.rst
@@ -0,0 +1,54 @@
+Build environment API
+=====================
+
+.. module:: sphinx.environment
+
+.. class:: BuildEnvironment
+
+ **Attributes**
+
+ .. attribute:: app
+
+ Reference to the :class:`.Sphinx` (application) object.
+
+ .. attribute:: config
+
+ Reference to the :class:`.Config` object.
+
+ .. attribute:: srcdir
+
+ Source directory (the directory containing ``conf.py``).
+
+ .. attribute:: doctreedir
+
+ Directory for storing pickled doctrees.
+
+ .. attribute:: found_docs
+
+ A set of all existing docnames.
+
+ .. attribute:: metadata
+
+ Dictionary mapping docnames to "metadata" (see :ref:`metadata`).
+
+ .. attribute:: titles
+
+ Dictionary mapping docnames to the docutils node for their main title.
+
+ .. autoattribute:: docname
+
+ **Utility methods**
+
+ .. automethod:: warn
+
+ .. automethod:: warn_node
+
+ .. automethod:: doc2path
+
+ .. automethod:: relfn2path
+
+ .. automethod:: note_dependency
+
+ .. automethod:: new_serialno
+
+ .. automethod:: note_reread
diff --git a/doc/extdev/index.rst b/doc/extdev/index.rst
new file mode 100644
index 0000000..b76928c
--- /dev/null
+++ b/doc/extdev/index.rst
@@ -0,0 +1,33 @@
+.. _dev-extensions:
+
+Developing extensions for Sphinx
+================================
+
+Since many projects will need special features in their documentation, Sphinx is
+designed to be extensible on several levels.
+
+This is what you can do in an extension: First, you can add new
+:term:`builder`\s to support new output formats or actions on the parsed
+documents. Then, it is possible to register custom reStructuredText roles and
+directives, extending the markup. And finally, there are so-called "hook
+points" at strategic places throughout the build process, where an extension can
+register a hook and run specialized code.
+
+An extension is simply a Python module. When an extension is loaded, Sphinx
+imports this module and executes its ``setup()`` function, which in turn
+notifies Sphinx of everything the extension offers -- see the extension tutorial
+for examples.
+
+The configuration file itself can be treated as an extension if it contains a
+``setup()`` function. All other extensions to load must be listed in the
+:confval:`extensions` configuration value.
+
+.. toctree::
+
+ tutorial
+ appapi
+ envapi
+ builderapi
+ markupapi
+ domainapi
+ nodes
diff --git a/doc/extdev/markupapi.rst b/doc/extdev/markupapi.rst
new file mode 100644
index 0000000..577a39e
--- /dev/null
+++ b/doc/extdev/markupapi.rst
@@ -0,0 +1,139 @@
+Docutils markup API
+===================
+
+This section describes the API for adding ReST markup elements (roles and
+directives).
+
+Roles
+-----
+
+
+Directives
+----------
+
+Directives are handled by classes derived from
+``docutils.parsers.rst.Directive``. They have to be registered by an extension
+using :meth:`.Sphinx.add_directive` or :meth:`.Sphinx.add_directive_to_domain`.
+
+.. module:: docutils.parsers.rst
+
+.. class:: Directive
+
+ The markup syntax of the new directive is determined by the follow five class
+ attributes:
+
+ .. autoattribute:: required_arguments
+ .. autoattribute:: optional_arguments
+ .. autoattribute:: final_argument_whitespace
+ .. autoattribute:: option_spec
+
+ Option validator functions take a single parameter, the option argument
+ (or ``None`` if not given), and should validate it or convert it to the
+ proper form. They raise :exc:`ValueError` or :exc:`TypeError` to indicate
+ failure.
+
+ There are several predefined and possibly useful validators in the
+ :mod:`docutils.parsers.rst.directives` module.
+
+ .. autoattribute:: has_content
+
+ New directives must implement the :meth:`run` method:
+
+ .. method:: run()
+
+ This method must process the directive arguments, options and content, and
+ return a list of Docutils/Sphinx nodes that will be inserted into the
+ document tree at the point where the directive was encountered.
+
+ Instance attributes that are always set on the directive are:
+
+ .. attribute:: name
+
+ The directive name (useful when registering the same directive class under
+ multiple names).
+
+ .. attribute:: arguments
+
+ The arguments given to the directive, as a list.
+
+ .. attribute:: options
+
+ The options given to the directive, as a dictionary mapping option names
+ to validated/converted values.
+
+ .. attribute:: content
+
+ The directive content, if given, as a :class:`.ViewList`.
+
+ .. attribute:: lineno
+
+ The absolute line number on which the directive appeared. This is not
+ always a useful value; use :attr:`srcline` instead.
+
+ .. attribute:: src
+
+ The source file of the directive.
+
+ .. attribute:: srcline
+
+ The line number in the source file on which the directive appeared.
+
+ .. attribute:: content_offset
+
+ Internal offset of the directive content. Used when calling
+ ``nested_parse`` (see below).
+
+ .. attribute:: block_text
+
+ The string containing the entire directive.
+
+ .. attribute:: state
+ state_machine
+
+ The state and state machine which controls the parsing. Used for
+ ``nested_parse``.
+
+
+ViewLists
+^^^^^^^^^
+
+Docutils represents document source lines in a class
+``docutils.statemachine.ViewList``. This is a list with extended functionality
+-- for one, slicing creates views of the original list, and also the list
+contains information about the source line numbers.
+
+The :attr:`Directive.content` attribute is a ViewList. If you generate content
+to be parsed as ReST, you have to create a ViewList yourself. Important for
+content generation are the following points:
+
+* The constructor takes a list of strings (lines) and a source (document) name.
+
+* The ``.append()`` method takes a line and a source name as well.
+
+
+Parsing directive content as ReST
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Many directives will contain more markup that must be parsed. To do this, use
+one of the following APIs from the :meth:`Directive.run` method:
+
+* ``self.state.nested_parse``
+* :func:`sphinx.util.nodes.nested_parse_with_titles` -- this allows titles in
+ the parsed content.
+
+Both APIs parse the content into a given node. They are used like this::
+
+ node = docutils.nodes.paragraph()
+ # either
+ nested_parse_with_titles(self.state, self.result, node)
+ # or
+ self.state.nested_parse(self.result, 0, node)
+
+If you don't need the wrapping node, you can use any concrete node type and
+return ``node.children`` from the Directive.
+
+
+.. seealso::
+
+ `Creating directives <http://docutils.sf.net/docs/howto/rst-directives.html>`_
+ HOWTO of the Docutils documentation
diff --git a/doc/extdev/nodes.rst b/doc/extdev/nodes.rst
new file mode 100644
index 0000000..e67fa3d
--- /dev/null
+++ b/doc/extdev/nodes.rst
@@ -0,0 +1,57 @@
+.. _nodes:
+
+Doctree node classes added by Sphinx
+====================================
+
+.. module:: sphinx.addnodes
+
+Nodes for domain-specific object descriptions
+---------------------------------------------
+
+.. autoclass:: desc
+.. autoclass:: desc_signature
+.. autoclass:: desc_addname
+.. autoclass:: desc_type
+.. autoclass:: desc_returns
+.. autoclass:: desc_name
+.. autoclass:: desc_parameterlist
+.. autoclass:: desc_parameter
+.. autoclass:: desc_optional
+.. autoclass:: desc_annotation
+.. autoclass:: desc_content
+
+New admonition-like constructs
+------------------------------
+
+.. autoclass:: versionmodified
+.. autoclass:: seealso
+
+Other paragraph-level nodes
+-------------------------------
+
+.. autoclass:: compact_paragraph
+
+New inline nodes
+----------------
+
+.. autoclass:: index
+.. autoclass:: pending_xref
+.. autoclass:: literal_emphasis
+.. autoclass:: abbreviation
+.. autoclass:: download_reference
+
+Special nodes
+-------------
+
+.. autoclass:: only
+.. autoclass:: meta
+.. autoclass:: highlightlang
+
+You should not need to generate the nodes below in extensions.
+
+.. autoclass:: glossary
+.. autoclass:: toctree
+.. autoclass:: start_of_file
+.. autoclass:: productionlist
+.. autoclass:: production
+.. autoclass:: termsep
diff --git a/doc/extdev/tutorial.rst b/doc/extdev/tutorial.rst
new file mode 100644
index 0000000..a03d6e0
--- /dev/null
+++ b/doc/extdev/tutorial.rst
@@ -0,0 +1,397 @@
+.. _exttut:
+
+Tutorial: Writing a simple extension
+====================================
+
+This section is intended as a walkthrough for the creation of custom extensions.
+It covers the basics of writing and activating an extensions, as well as
+commonly used features of extensions.
+
+As an example, we will cover a "todo" extension that adds capabilities to
+include todo entries in the documentation, and collecting these in a central
+place. (A similar "todo" extension is distributed with Sphinx.)
+
+
+Important objects
+-----------------
+
+There are several key objects whose API you will use while writing an
+extension. These are:
+
+**Application**
+ The application object (usually called ``app``) is an instance of
+ :class:`.Sphinx`. It controls the most high-level functionality, such as the
+ setup of extensions, event dispatching and producing output (logging).
+
+ If you have the environment object, the application is available as
+ ``env.app``.
+
+**Environment**
+ The build environment object (usually called ``env``) is an instance of
+ :class:`.BuildEnvironment`. It is responsible for parsing the source
+ documents stores all metadata about the document collection and is serialized
+ after each build.
+
+ Its API provides methods to do with access to metadata, resolving references,
+ etc. It can also be used by extensions to cache information that should
+ persist for incremental rebuilds.
+
+ If you have the application or builder object, the environment is available
+ as ``app.env`` or ``builder.env``.
+
+**Builder**
+ The builder object (usually called ``builder``) is an instance of a specific
+ subclass of :class:`.Builder`. Each builder class knows how to convert the
+ parsed documents into an output format, or otherwise process them (e.g. check
+ external links).
+
+ If you have the application object, the environment is available as
+ ``app.builder``.
+
+**Config**
+ The config object (usually called ``config``) provides the values of
+ configuration values set in :file:`conf.py` as attributes. It is an instance
+ of :class:`.Config`.
+
+ The config is available as ``app.config`` or ``env.config``.
+
+
+Build Phases
+------------
+
+One thing that is vital in order to understand extension mechanisms is the way
+in which a Sphinx project is built: this works in several phases.
+
+**Phase 0: Initialization**
+
+ In this phase, almost nothing interesting for us happens. The source
+ directory is searched for source files, and extensions are initialized.
+ Should a stored build environment exist, it is loaded, otherwise a new one is
+ created.
+
+**Phase 1: Reading**
+
+ In Phase 1, all source files (and on subsequent builds, those that are new or
+ changed) are read and parsed. This is the phase where directives and roles
+ are encountered by the docutils, and the corresponding code is executed. The
+ output of this phase is a *doctree* for each source files, that is a tree of
+ docutils nodes. For document elements that aren't fully known until all
+ existing files are read, temporary nodes are created.
+
+ There are nodes provided by docutils, which are documented `in the docutils
+ documentation <http://docutils.sourceforge.net/docs/ref/doctree.html>`__.
+ Additional nodes are provided by Sphinx and :ref:`documented here <nodes>`.
+
+ During reading, the build environment is updated with all meta- and cross
+ reference data of the read documents, such as labels, the names of headings,
+ described Python objects and index entries. This will later be used to
+ replace the temporary nodes.
+
+ The parsed doctrees are stored on the disk, because it is not possible to
+ hold all of them in memory.
+
+**Phase 2: Consistency checks**
+
+ Some checking is done to ensure no surprises in the built documents.
+
+**Phase 3: Resolving**
+
+ Now that the metadata and cross-reference data of all existing documents is
+ known, all temporary nodes are replaced by nodes that can be converted into
+ output. For example, links are created for object references that exist, and
+ simple literal nodes are created for those that don't.
+
+**Phase 4: Writing**
+
+ This phase converts the resolved doctrees to the desired output format, such
+ as HTML or LaTeX. This happens via a so-called docutils writer that visits
+ the individual nodes of each doctree and produces some output in the process.
+
+.. note::
+
+ Some builders deviate from this general build plan, for example, the builder
+ that checks external links does not need anything more than the parsed
+ doctrees and therefore does not have phases 2--4.
+
+
+Extension Design
+----------------
+
+We want the extension to add the following to Sphinx:
+
+* A "todo" directive, containing some content that is marked with "TODO", and
+ only shown in the output if a new config value is set. (Todo entries should
+ not be in the output by default.)
+
+* A "todolist" directive that creates a list of all todo entries throughout the
+ documentation.
+
+For that, we will need to add the following elements to Sphinx:
+
+* New directives, called ``todo`` and ``todolist``.
+* New document tree nodes to represent these directives, conventionally also
+ called ``todo`` and ``todolist``. We wouldn't need new nodes if the new
+ directives only produced some content representable by existing nodes.
+* A new config value ``todo_include_todos`` (config value names should start
+ with the extension name, in order to stay unique) that controls whether todo
+ entries make it into the output.
+* New event handlers: one for the :event:`doctree-resolved` event, to replace
+ the todo and todolist nodes, and one for :event:`env-purge-doc` (the reason
+ for that will be covered later).
+
+
+The Setup Function
+------------------
+
+.. currentmodule:: sphinx.application
+
+The new elements are added in the extension's setup function. Let us create a
+new Python module called :file:`todo.py` and add the setup function::
+
+ def setup(app):
+ app.add_config_value('todo_include_todos', False, False)
+
+ app.add_node(todolist)
+ app.add_node(todo,
+ html=(visit_todo_node, depart_todo_node),
+ latex=(visit_todo_node, depart_todo_node),
+ text=(visit_todo_node, depart_todo_node))
+
+ app.add_directive('todo', TodoDirective)
+ app.add_directive('todolist', TodolistDirective)
+ app.connect('doctree-resolved', process_todo_nodes)
+ app.connect('env-purge-doc', purge_todos)
+
+The calls in this function refer to classes and functions not yet written. What
+the individual calls do is the following:
+
+* :meth:`~Sphinx.add_config_value` lets Sphinx know that it should recognize the
+ new *config value* ``todo_include_todos``, whose default value should be
+ ``False`` (this also tells Sphinx that it is a boolean value).
+
+ If the third argument was ``True``, all documents would be re-read if the
+ config value changed its value. This is needed for config values that
+ influence reading (build phase 1).
+
+* :meth:`~Sphinx.add_node` adds a new *node class* to the build system. It also
+ can specify visitor functions for each supported output format. These visitor
+ functions are needed when the new nodes stay until phase 4 -- since the
+ ``todolist`` node is always replaced in phase 3, it doesn't need any.
+
+ We need to create the two node classes ``todo`` and ``todolist`` later.
+
+* :meth:`~Sphinx.add_directive` adds a new *directive*, given by name and class.
+
+ The handler functions are created later.
+
+* Finally, :meth:`~Sphinx.connect` adds an *event handler* to the event whose
+ name is given by the first argument. The event handler function is called
+ with several arguments which are documented with the event.
+
+
+The Node Classes
+----------------
+
+Let's start with the node classes::
+
+ from docutils import nodes
+
+ class todo(nodes.Admonition, nodes.Element):
+ pass
+
+ class todolist(nodes.General, nodes.Element):
+ pass
+
+ def visit_todo_node(self, node):
+ self.visit_admonition(node)
+
+ def depart_todo_node(self, node):
+ self.depart_admonition(node)
+
+Node classes usually don't have to do anything except inherit from the standard
+docutils classes defined in :mod:`docutils.nodes`. ``todo`` inherits from
+``Admonition`` because it should be handled like a note or warning, ``todolist``
+is just a "general" node.
+
+.. note::
+
+ Many extensions will not have to create their own node classes and work fine
+ with the nodes already provided by `docutils
+ <http://docutils.sourceforge.net/docs/ref/doctree.html>`__ and :ref:`Sphinx
+ <nodes>`.
+
+
+The Directive Classes
+---------------------
+
+A directive class is a class deriving usually from
+:class:`docutils.parsers.rst.Directive`. The directive interface is also
+covered in detail in the `docutils documentation`_; the important thing is that
+the class has attributes that configure the allowed markup and a method ``run``
+that returns a list of nodes.
+
+The ``todolist`` directive is quite simple::
+
+ from docutils.parsers.rst import Directive
+
+ class TodolistDirective(Directive):
+
+ def run(self):
+ return [todolist('')]
+
+An instance of our ``todolist`` node class is created and returned. The
+todolist directive has neither content nor arguments that need to be handled.
+
+The ``todo`` directive function looks like this::
+
+ from sphinx.util.compat import make_admonition
+
+ class TodoDirective(Directive):
+
+ # this enables content in the directive
+ has_content = True
+
+ def run(self):
+ env = self.state.document.settings.env
+
+ targetid = "todo-%d" % env.new_serialno('todo')
+ targetnode = nodes.target('', '', ids=[targetid])
+
+ ad = make_admonition(todo, self.name, [_('Todo')], self.options,
+ self.content, self.lineno, self.content_offset,
+ self.block_text, self.state, self.state_machine)
+
+ if not hasattr(env, 'todo_all_todos'):
+ env.todo_all_todos = []
+ env.todo_all_todos.append({
+ 'docname': env.docname,
+ 'lineno': self.lineno,
+ 'todo': ad[0].deepcopy(),
+ 'target': targetnode,
+ })
+
+ return [targetnode] + ad
+
+Several important things are covered here. First, as you can see, you can refer
+to the build environment instance using ``self.state.document.settings.env``.
+
+Then, to act as a link target (from the todolist), the todo directive needs to
+return a target node in addition to the todo node. The target ID (in HTML, this
+will be the anchor name) is generated by using ``env.new_serialno`` which
+returns a new unique integer on each call and therefore leads to unique target
+names. The target node is instantiated without any text (the first two
+arguments).
+
+An admonition is created using a standard docutils function (wrapped in Sphinx
+for docutils cross-version compatibility). The first argument gives the node
+class, in our case ``todo``. The third argument gives the admonition title (use
+``arguments`` here to let the user specify the title). A list of nodes is
+returned from ``make_admonition``.
+
+Then, the todo node is added to the environment. This is needed to be able to
+create a list of all todo entries throughout the documentation, in the place
+where the author puts a ``todolist`` directive. For this case, the environment
+attribute ``todo_all_todos`` is used (again, the name should be unique, so it is
+prefixed by the extension name). It does not exist when a new environment is
+created, so the directive must check and create it if necessary. Various
+information about the todo entry's location are stored along with a copy of the
+node.
+
+In the last line, the nodes that should be put into the doctree are returned:
+the target node and the admonition node.
+
+The node structure that the directive returns looks like this::
+
+ +--------------------+
+ | target node |
+ +--------------------+
+ +--------------------+
+ | todo node |
+ +--------------------+
+ \__+--------------------+
+ | admonition title |
+ +--------------------+
+ | paragraph |
+ +--------------------+
+ | ... |
+ +--------------------+
+
+
+The Event Handlers
+------------------
+
+Finally, let's look at the event handlers. First, the one for the
+:event:`env-purge-doc` event::
+
+ def purge_todos(app, env, docname):
+ if not hasattr(env, 'todo_all_todos'):
+ return
+ env.todo_all_todos = [todo for todo in env.todo_all_todos
+ if todo['docname'] != docname]
+
+Since we store information from source files in the environment, which is
+persistent, it may become out of date when the source file changes. Therefore,
+before each source file is read, the environment's records of it are cleared,
+and the :event:`env-purge-doc` event gives extensions a chance to do the same.
+Here we clear out all todos whose docname matches the given one from the
+``todo_all_todos`` list. If there are todos left in the document, they will be
+added again during parsing.
+
+The other handler belongs to the :event:`doctree-resolved` event. This event is
+emitted at the end of phase 3 and allows custom resolving to be done::
+
+ def process_todo_nodes(app, doctree, fromdocname):
+ if not app.config.todo_include_todos:
+ for node in doctree.traverse(todo):
+ node.parent.remove(node)
+
+ # Replace all todolist nodes with a list of the collected todos.
+ # Augment each todo with a backlink to the original location.
+ env = app.builder.env
+
+ for node in doctree.traverse(todolist):
+ if not app.config.todo_include_todos:
+ node.replace_self([])
+ continue
+
+ content = []
+
+ for todo_info in env.todo_all_todos:
+ para = nodes.paragraph()
+ filename = env.doc2path(todo_info['docname'], base=None)
+ description = (
+ _('(The original entry is located in %s, line %d and can be found ') %
+ (filename, todo_info['lineno']))
+ para += nodes.Text(description, description)
+
+ # Create a reference
+ newnode = nodes.reference('', '')
+ innernode = nodes.emphasis(_('here'), _('here'))
+ newnode['refdocname'] = todo_info['docname']
+ newnode['refuri'] = app.builder.get_relative_uri(
+ fromdocname, todo_info['docname'])
+ newnode['refuri'] += '#' + todo_info['target']['refid']
+ newnode.append(innernode)
+ para += newnode
+ para += nodes.Text('.)', '.)')
+
+ # Insert into the todolist
+ content.append(todo_info['todo'])
+ content.append(para)
+
+ node.replace_self(content)
+
+It is a bit more involved. If our new "todo_include_todos" config value is
+false, all todo and todolist nodes are removed from the documents.
+
+If not, todo nodes just stay where and how they are. Todolist nodes are
+replaced by a list of todo entries, complete with backlinks to the location
+where they come from. The list items are composed of the nodes from the todo
+entry and docutils nodes created on the fly: a paragraph for each entry,
+containing text that gives the location, and a link (reference node containing
+an italic node) with the backreference. The reference URI is built by
+``app.builder.get_relative_uri`` which creates a suitable URI depending on the
+used builder, and appending the todo node's (the target's) ID as the anchor
+name.
+
+.. _docutils documentation: http://docutils.sourceforge.net/docs/ref/rst/directives.html
diff --git a/doc/extensions.rst b/doc/extensions.rst
new file mode 100644
index 0000000..b2adbc1
--- /dev/null
+++ b/doc/extensions.rst
@@ -0,0 +1,71 @@
+.. _extensions:
+
+Sphinx Extensions
+=================
+
+Since many projects will need special features in their documentation, Sphinx
+allows to add "extensions" to the build process, each of which can modify almost
+any aspect of document processing.
+
+This chapter describes the extensions bundled with Sphinx. For the API
+documentation on writing your own extension, see :ref:`dev-extensions`.
+
+Builtin Sphinx extensions
+-------------------------
+
+These extensions are built in and can be activated by respective entries in the
+:confval:`extensions` configuration value:
+
+.. toctree::
+
+ ext/autodoc
+ ext/autosummary
+ ext/doctest
+ ext/intersphinx
+ ext/math
+ ext/graphviz
+ ext/inheritance
+ ext/ifconfig
+ ext/coverage
+ ext/todo
+ ext/extlinks
+ ext/viewcode
+ ext/linkcode
+ ext/oldcmarkup
+
+
+Third-party extensions
+----------------------
+
+You can find several extensions contributed by users in the `Sphinx Contrib`_
+repository. It is open for anyone who wants to maintain an extension
+publicly; just send a short message asking for write permissions.
+
+There are also several extensions hosted elsewhere. The `Wiki at BitBucket`_
+maintains a list of those.
+
+If you write an extension that you think others will find useful or you think
+should be included as a part of Sphinx, please write to the project mailing
+list (`join here <https://groups.google.com/group/sphinx-dev>`_).
+
+.. _Wiki at BitBucket: https://bitbucket.org/birkenfeld/sphinx/wiki/Home
+.. _Sphinx Contrib: https://bitbucket.org/birkenfeld/sphinx-contrib
+
+
+Where to put your own extensions?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Extensions local to a project should be put within the project's directory
+structure. Set Python's module search path, ``sys.path``, accordingly so that
+Sphinx can find them.
+E.g., if your extension ``foo.py`` lies in the ``exts`` subdirectory of the
+project root, put into :file:`conf.py`::
+
+ import sys, os
+
+ sys.path.append(os.path.abspath('exts'))
+
+ extensions = ['foo']
+
+You can also install extensions anywhere else on ``sys.path``, e.g. in the
+``site-packages`` directory.
diff --git a/doc/faq.rst b/doc/faq.rst
new file mode 100644
index 0000000..7aa35d1
--- /dev/null
+++ b/doc/faq.rst
@@ -0,0 +1,268 @@
+.. _faq:
+
+Sphinx FAQ
+==========
+
+This is a list of Frequently Asked Questions about Sphinx. Feel free to
+suggest new entries!
+
+How do I...
+-----------
+
+... create PDF files without LaTeX?
+ You can use `rst2pdf <http://rst2pdf.googlecode.com>`_ version 0.12 or greater
+ which comes with built-in Sphinx integration. See the :ref:`builders`
+ section for details.
+
+... get section numbers?
+ They are automatic in LaTeX output; for HTML, give a ``:numbered:`` option to
+ the :rst:dir:`toctree` directive where you want to start numbering.
+
+... customize the look of the built HTML files?
+ Use themes, see :doc:`theming`.
+
+... add global substitutions or includes?
+ Add them in the :confval:`rst_epilog` config value.
+
+... display the whole TOC tree in the sidebar?
+ Use the :data:`toctree` callable in a custom layout template, probably in the
+ ``sidebartoc`` block.
+
+... write my own extension?
+ See the :ref:`extension tutorial <exttut>`.
+
+... convert from my existing docs using MoinMoin markup?
+ The easiest way is to convert to xhtml, then convert `xhtml to reST`_. You'll
+ still need to mark up classes and such, but the headings and code examples
+ come through cleanly.
+
+... create HTML slides from Sphinx documents?
+ See the "Hieroglyph" package at https://github.com/nyergler/hieroglyph.
+
+For many more extensions and other contributed stuff, see the sphinx-contrib_
+repository.
+
+.. _sphinx-contrib: https://bitbucket.org/birkenfeld/sphinx-contrib/
+
+.. _usingwith:
+
+Using Sphinx with...
+--------------------
+
+Read the Docs
+ https://readthedocs.org is a documentation hosting service based around Sphinx.
+ They will host sphinx documentation, along with supporting a number of other
+ features including version support, PDF generation, and more. The `Getting
+ Started <http://read-the-docs.readthedocs.org/en/latest/getting_started.html>`_
+ guide is a good place to start.
+
+Epydoc
+ There's a third-party extension providing an `api role`_ which refers to
+ Epydoc's API docs for a given identifier.
+
+Doxygen
+ Michael Jones is developing a reST/Sphinx bridge to doxygen called `breathe
+ <https://github.com/michaeljones/breathe/tree/master>`_.
+
+SCons
+ Glenn Hutchings has written a SCons build script to build Sphinx
+ documentation; it is hosted here: https://bitbucket.org/zondo/sphinx-scons
+
+PyPI
+ Jannis Leidel wrote a `setuptools command
+ <https://pypi.python.org/pypi/Sphinx-PyPI-upload>`_ that automatically uploads
+ Sphinx documentation to the PyPI package documentation area at
+ http://pythonhosted.org/.
+
+GitHub Pages
+ Directories starting with underscores are ignored by default which breaks
+ static files in Sphinx. GitHub's preprocessor can be `disabled
+ <https://github.com/blog/572-bypassing-jekyll-on-github-pages>`_ to support
+ Sphinx HTML output properly.
+
+MediaWiki
+ See https://bitbucket.org/kevindunn/sphinx-wiki, a project by Kevin Dunn.
+
+Google Analytics
+ You can use a custom ``layout.html`` template, like this:
+
+ .. code-block:: html+django
+
+ {% extends "!layout.html" %}
+
+ {%- block extrahead %}
+ {{ super() }}
+ <script type="text/javascript">
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'XXX account number XXX']);
+ _gaq.push(['_trackPageview']);
+ </script>
+ {% endblock %}
+
+ {% block footer %}
+ {{ super() }}
+ <div class="footer">This page uses <a href="http://analytics.google.com/">
+ Google Analytics</a> to collect statistics. You can disable it by blocking
+ the JavaScript coming from www.google-analytics.com.
+ <script type="text/javascript">
+ (function() {
+ var ga = document.createElement('script');
+ ga.src = ('https:' == document.location.protocol ?
+ 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ ga.setAttribute('async', 'true');
+ document.documentElement.firstChild.appendChild(ga);
+ })();
+ </script>
+ </div>
+ {% endblock %}
+
+
+.. _api role: http://git.savannah.gnu.org/cgit/kenozooid.git/tree/doc/extapi.py
+.. _xhtml to reST: http://docutils.sourceforge.net/sandbox/xhtml2rest/xhtml2rest.py
+
+
+.. _epub-faq:
+
+Epub info
+---------
+
+The following list gives some hints for the creation of epub files:
+
+* Split the text into several files. The longer the individual HTML files are,
+ the longer it takes the ebook reader to render them. In extreme cases, the
+ rendering can take up to one minute.
+
+* Try to minimize the markup. This also pays in rendering time.
+
+* For some readers you can use embedded or external fonts using the CSS
+ ``@font-face`` directive. This is *extremely* useful for code listings which
+ are often cut at the right margin. The default Courier font (or variant) is
+ quite wide and you can only display up to 60 characters on a line. If you
+ replace it with a narrower font, you can get more characters on a line. You
+ may even use `FontForge <http://fontforge.org/>`_ and create
+ narrow variants of some free font. In my case I get up to 70 characters on a
+ line.
+
+ You may have to experiment a little until you get reasonable results.
+
+* Test the created epubs. You can use several alternatives. The ones I am aware
+ of are Epubcheck_, Calibre_, FBreader_ (although it does not render the CSS),
+ and Bookworm_. For bookworm you can download the source from
+ http://code.google.com/p/threepress/ and run your own local server.
+
+* Large floating divs are not displayed properly.
+ If they cover more than one page, the div is only shown on the first page.
+ In that case you can copy the :file:`epub.css` from the
+ ``sphinx/themes/epub/static/`` directory to your local ``_static/``
+ directory and remove the float settings.
+
+* Files that are inserted outside of the ``toctree`` directive must be manually
+ included. This sometimes applies to appendixes, e.g. the glossary or
+ the indices. You can add them with the :confval:`epub_post_files` option.
+
+* The handling of the epub cover page differs from the reStructuredText
+ procedure which automatically resolves image paths and puts the images
+ into the ``_images`` directory. For the epub cover page put the image in the
+ :confval:`html_static_path` directory and reference it with its full path in
+ the :confval:`epub_cover` config option.
+
+.. _Epubcheck: http://code.google.com/p/epubcheck/
+.. _Calibre: http://calibre-ebook.com/
+.. _FBreader: http://fbreader.org/
+.. _Bookworm: http://oreilly.com/bookworm/index.html
+
+
+.. _texinfo-faq:
+
+Texinfo info
+------------
+
+There are two main programs for reading Info files, ``info`` and GNU Emacs. The
+``info`` program has less features but is available in most Unix environments
+and can be quickly accessed from the terminal. Emacs provides better font and
+color display and supports extensive customization (of course).
+
+.. _texinfo-links:
+
+Displaying Links
+~~~~~~~~~~~~~~~~
+
+One noticeable problem you may encounter with the generated Info files is how
+references are displayed. If you read the source of an Info file, a reference
+to this section would look like::
+
+ * note Displaying Links: target-id
+
+In the stand-alone reader, ``info``, references are displayed just as they
+appear in the source. Emacs, on the other-hand, will by default replace
+``*note:`` with ``see`` and hide the ``target-id``. For example:
+
+ :ref:`texinfo-links`
+
+The exact behavior of how Emacs displays references is dependent on the variable
+``Info-hide-note-references``. If set to the value of ``hide``, Emacs will hide
+both the ``*note:`` part and the ``target-id``. This is generally the best way
+to view Sphinx-based documents since they often make frequent use of links and
+do not take this limitation into account. However, changing this variable
+affects how all Info documents are displayed and most due take this behavior
+into account.
+
+If you want Emacs to display Info files produced by Sphinx using the value
+``hide`` for ``Info-hide-note-references`` and the default value for all other
+Info files, try adding the following Emacs Lisp code to your start-up file,
+``~/.emacs.d/init.el``.
+
+::
+
+ (defadvice info-insert-file-contents (after
+ sphinx-info-insert-file-contents
+ activate)
+ "Hack to make `Info-hide-note-references' buffer-local and
+ automatically set to `hide' iff it can be determined that this file
+ was created from a Texinfo file generated by Docutils or Sphinx."
+ (set (make-local-variable 'Info-hide-note-references)
+ (default-value 'Info-hide-note-references))
+ (save-excursion
+ (save-restriction
+ (widen) (goto-char (point-min))
+ (when (re-search-forward
+ "^Generated by \\(Sphinx\\|Docutils\\)"
+ (save-excursion (search-forward "\x1f" nil t)) t)
+ (set (make-local-variable 'Info-hide-note-references)
+ 'hide)))))
+
+
+Notes
+~~~~~
+
+The following notes may be helpful if you want to create Texinfo files:
+
+- Each section corresponds to a different ``node`` in the Info file.
+
+- Colons (``:``) cannot be properly escaped in menu entries and xrefs.
+ They will be replaced with semicolons (``;``).
+
+- Links to external Info files can be created using the somewhat official URI
+ scheme ``info``. For example::
+
+ info:Texinfo#makeinfo_options
+
+ which produces:
+
+ info:Texinfo#makeinfo_options
+
+- Inline markup
+
+ The standard formatting for ``*strong*`` and ``_emphasis_`` can
+ result in ambiguous output when used to markup parameter names and
+ other values. Since this is a fairly common practice, the default
+ formatting has been changed so that ``emphasis`` and ``strong`` are
+ now displayed like ```literal'``\s.
+
+ The standard formatting can be re-enabled by adding the following to
+ your :file:`conf.py`::
+
+ texinfo_elements = {'preamble': """
+ @definfoenclose strong,*,*
+ @definfoenclose emph,_,_
+ """}
diff --git a/doc/glossary.rst b/doc/glossary.rst
new file mode 100644
index 0000000..8bc393e
--- /dev/null
+++ b/doc/glossary.rst
@@ -0,0 +1,83 @@
+.. _glossary:
+
+Glossary
+========
+
+.. glossary::
+
+ builder
+ A class (inheriting from :class:`~sphinx.builders.Builder`) that takes
+ parsed documents and performs an action on them. Normally, builders
+ translate the documents to an output format, but it is also possible to
+ use the builder builders that e.g. check for broken links in the
+ documentation, or build coverage information.
+
+ See :ref:`builders` for an overview over Sphinx' built-in builders.
+
+ configuration directory
+ The directory containing :file:`conf.py`. By default, this is the same as
+ the :term:`source directory`, but can be set differently with the **-c**
+ command-line option.
+
+ directive
+ A reStructuredText markup element that allows marking a block of content
+ with special meaning. Directives are supplied not only by docutils, but
+ Sphinx and custom extensions can add their own. The basic directive
+ syntax looks like this:
+
+ .. sourcecode:: rst
+
+ .. directivename:: argument ...
+ :option: value
+
+ Content of the directive.
+
+ See :ref:`directives` for more information.
+
+ document name
+ Since reST source files can have different extensions (some people like
+ ``.txt``, some like ``.rst`` -- the extension can be configured with
+ :confval:`source_suffix`) and different OSes have different path separators,
+ Sphinx abstracts them: :dfn:`document names` are always relative to the
+ :term:`source directory`, the extension is stripped, and path separators
+ are converted to slashes. All values, parameters and such referring to
+ "documents" expect such document names.
+
+ Examples for document names are ``index``, ``library/zipfile``, or
+ ``reference/datamodel/types``. Note that there is no leading or trailing
+ slash.
+
+ domain
+ A domain is a collection of markup (reStructuredText :term:`directive`\ s
+ and :term:`role`\ s) to describe and link to :term:`object`\ s belonging
+ together, e.g. elements of a programming language. Directive and role
+ names in a domain have names like ``domain:name``, e.g. ``py:function``.
+
+ Having domains means that there are no naming problems when one set of
+ documentation wants to refer to e.g. C++ and Python classes. It also
+ means that extensions that support the documentation of whole new
+ languages are much easier to write. For more information about domains,
+ see the chapter :ref:`domains`.
+
+ environment
+ A structure where information about all documents under the root is saved,
+ and used for cross-referencing. The environment is pickled after the
+ parsing stage, so that successive runs only need to read and parse new and
+ changed documents.
+
+ master document
+ The document that contains the root :rst:dir:`toctree` directive.
+
+ object
+ The basic building block of Sphinx documentation. Every "object
+ directive" (e.g. :rst:dir:`function` or :rst:dir:`object`) creates such a block;
+ and most objects can be cross-referenced to.
+
+ role
+ A reStructuredText markup element that allows marking a piece of text.
+ Like directives, roles are extensible. The basic syntax looks like this:
+ ``:rolename:`content```. See :ref:`inlinemarkup` for details.
+
+ source directory
+ The directory which, including its subdirectories, contains all source
+ files for one Sphinx project.
diff --git a/doc/install.rst b/doc/install.rst
new file mode 100644
index 0000000..bf65387
--- /dev/null
+++ b/doc/install.rst
@@ -0,0 +1,151 @@
+:orphan:
+
+Installing Sphinx
+=================
+
+Since Sphinx is written in the Python language, you need to install Python
+(the required version is at least 2.5) and Sphinx.
+
+Sphinx packages are available on the `Python Package Index
+<https://pypi.python.org/pypi/Sphinx>`_.
+
+You can also download a snapshot from the Mercurial development repository:
+
+* as a `.tar.bz2 <https://bitbucket.org/birkenfeld/sphinx/get/default.tar.bz2>`_
+ file or
+* as a `.zip <https://bitbucket.org/birkenfeld/sphinx/get/default.zip>`_ file
+
+There are introductions for several environments:
+
+.. contents::
+ :depth: 1
+ :local:
+ :backlinks: none
+
+
+Debian/Ubuntu: Install Sphinx using packaging system
+----------------------------------------------------
+
+You may install using this command if you use Debian/Ubuntu.
+
+.. code-block:: bash
+
+ $ apt-get install python-sphinx
+
+
+Other Linux distributions
+-------------------------
+
+Most Linux distributions have Sphinx in their package repositories. Usually the
+package is called "python-sphinx", "python-Sphinx" or "sphinx". Be aware that
+there are two other packages with "sphinx" in their name: a speech recognition
+toolkit (CMU Sphinx) and a full-text search database (Sphinx search).
+
+
+Mac OS X: Install Sphinx using MacPorts
+---------------------------------------
+
+If you use Mac OS X `MacPorts <http://www.macports.org/>`_, use this command to
+install all necessary software.
+
+.. code-block:: bash
+
+ $ sudo port install py27-sphinx
+
+To set up the executable paths, use the ``port select`` command:
+
+.. code-block:: bash
+
+ $ sudo port select --set python python27
+ $ sudo port select --set sphinx py27-sphinx
+
+Type :command:`which sphinx-quickstart` to check if the installation was
+successful.
+
+
+Windows: Install Python and Sphinx
+----------------------------------
+
+Install Python
+^^^^^^^^^^^^^^
+
+Most Windows users do not have Python, so we begin with the installation of
+Python itself. If you have already installed Python, please skip this section.
+
+Go to http://python.org, the main download site for Python. Look at the left
+sidebar and under "Quick Links", click "Windows Installer" to download.
+
+.. image:: pythonorg.png
+
+.. note::
+
+ Currently, Python offers two major versions, 2.x and 3.x. Sphinx 1.2 can run
+ under Python 2.5 to 2.7 and 3.1 to 3.3, with the recommended version being
+ 2.7. This chapter assumes you have installed Python 2.7.
+
+Follow the Windows installer for Python.
+
+.. image:: installpython.jpg
+
+After installation, you better add the Python executable directories to the
+environment variable ``PATH`` in order to run Python and package commands such
+as ``sphinx-build`` easily from the Command Prompt.
+
+* Right-click the "My Computer" icon and choose "Properties"
+* Click the "Environment Variables" button under the "Advanced" tab
+
+* If "Path" (or "PATH") is already an entry in the "System variables" list, edit
+ it. If it is not present, add a new variable called "PATH".
+
+* Add these paths, separating entries by ";":
+
+ - ``C:\Python27`` -- this folder contains the main Python executable
+ - ``C:\Python27\Scripts`` -- this folder will contain executables added by
+ Python packages installed with easy_install (see below)
+
+ This is for Python 2.7. If you use another version of
+ Python or installed to a non-default location, change the digits "27"
+ accordingly.
+
+* Now run the **Command Prompt**. After command prompt window appear, type
+ ``python`` and Enter. If the Python installation was successful, the
+ installed Python version is printed, and you are greeted by the prompt
+ ``>>>``. Type ``Ctrl+Z`` and Enter to quit.
+
+
+Install the easy_install command
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Python has a very useful :command:`easy_install` command which can download and
+install 3rd-party libraries with a single command. This is provided by the
+"setuptools" project: https://pypi.python.org/pypi/setuptools.
+
+To install setuptools, download
+https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py and
+save it somewhere. After download, invoke the command prompt, go to the
+directory with ez_setup.py and run this command:
+
+.. code-block:: bat
+
+ C:\> python ez_setup.py
+
+Now setuptools and its :command:`easy_install` command is installed. From there
+we can go to the Sphinx install.
+
+
+Installing Sphinx with easy_install
+-----------------------------------
+
+If you finished the installation of setuptools, type this line in the command
+prompt:
+
+.. code-block:: bat
+
+ C:\> easy_install sphinx
+
+After installation, type :command:`sphinx-build` on the command prompt. If
+everything worked fine, you will get a Sphinx version number and a list of
+options for this command.
+
+That it. Installation is over. Head to :doc:`tutorial` to make a Sphinx
+project.
diff --git a/doc/installpython.jpg b/doc/installpython.jpg
new file mode 100644
index 0000000..b0e458e
Binary files /dev/null and b/doc/installpython.jpg differ
diff --git a/doc/intl.rst b/doc/intl.rst
new file mode 100644
index 0000000..3363dc5
--- /dev/null
+++ b/doc/intl.rst
@@ -0,0 +1,298 @@
+.. _intl:
+
+Internationalization
+====================
+
+.. versionadded:: 1.1
+
+Complementary to translations provided for Sphinx-generated messages such as
+navigation bars, Sphinx provides mechanisms facilitating *document* translations
+in itself. See the :ref:`intl-options` for details on configuration.
+
+.. figure:: translation.png
+ :width: 100%
+
+ Workflow visualization of translations in Sphinx. (The stick-figure is taken
+ from an `XKCD comic <http://xkcd.com/779/>`_.)
+
+.. contents::
+ :local:
+
+Sphinx internationalization details
+-----------------------------------
+
+**gettext** [1]_ is an established standard for internationalization and
+localization. It naively maps messages in a program to a translated string.
+Sphinx uses these facilities to translate whole documents.
+
+Initially project maintainers have to collect all translatable strings (also
+referred to as *messages*) to make them known to translators. Sphinx extracts
+these through invocation of ``sphinx-build -b gettext``.
+
+Every single element in the doctree will end up in a single message which
+results in lists being equally split into different chunks while large
+paragraphs will remain as coarsely-grained as they were in the original
+document. This grants seamless document updates while still providing a little
+bit of context for translators in free-text passages. It is the maintainer's
+task to split up paragraphs which are too large as there is no sane automated
+way to do that.
+
+After Sphinx successfully ran the
+:class:`~sphinx.builders.gettext.MessageCatalogBuilder` you will find a collection
+of ``.pot`` files in your output directory. These are **catalog templates**
+and contain messages in your original language *only*.
+
+They can be delivered to translators which will transform them to ``.po`` files
+--- so called **message catalogs** --- containing a mapping from the original
+messages to foreign-language strings.
+
+Gettext compiles them into a binary format known as **binary catalogs** through
+:program:`msgfmt` for efficiency reasons. If you make these files discoverable
+with :confval:`locale_dirs` for your :confval:`language`, Sphinx will pick them
+up automatically.
+
+An example: you have a document ``usage.rst`` in your Sphinx project. The
+gettext builder will put its messages into ``usage.pot``. Imagine you have
+Spanish translations [2]_ on your hands in ``usage.po`` --- for your builds to
+be translated you need to follow these instructions:
+
+* Compile your message catalog to a locale directory, say ``locale``, so it
+ ends up in ``./locale/es/LC_MESSAGES/usage.mo`` in your source directory
+ (where ``es`` is the language code for Spanish.) ::
+
+ msgfmt "usage.po" -o "locale/es/LC_MESSAGES/usage.mo"
+
+* Set :confval:`locale_dirs` to ``["locale/"]``.
+* Set :confval:`language` to ``es`` (also possible via :option:`-D`).
+* Run your desired build.
+
+
+Translating with sphinx-intl
+----------------------------
+
+Quick guide
+^^^^^^^^^^^
+
+`sphinx-intl`_ is a useful tool to work with Sphinx translation flow.
+This section describe a easy way to translate with sphinx-intl.
+
+#. Install `sphinx-intl`_ by :command:`pip install sphinx-intl` or
+ :command:`easy_install sphinx-intl`.
+
+#. Add configurations to your `conf.py`::
+
+ locale_dirs = ['locale/'] # path is example but recommended.
+ gettext_compact = False # optional.
+
+ This case-study assumes that :confval:`locale_dirs` is set to 'locale/' and
+ :confval:`gettext_compact` is set to `False` (the Sphinx document is
+ already configured as such).
+
+#. Extract document's translatable messages into pot files::
+
+ $ make gettext
+
+ As a result, many pot files are generated under ``_build/locale``
+ directory.
+
+#. Setup/Update your `locale_dir`::
+
+ $ sphinx-intl update -p _build/locale -l de -l ja
+
+ Done. You got these directories that contain po files:
+
+ * `./locale/de/LC_MESSAGES/`
+ * `./locale/ja/LC_MESSAGES/`
+
+#. Translate your po files under `./locale/<lang>/LC_MESSAGES/`.
+
+#. Build mo files and make translated document.
+
+ You need a :confval:`language` parameter in ``conf.py`` or you may also
+ specify the parameter on the command line::
+
+ $ sphinx-intl build
+ $ make -e SPHINXOPTS="-D language='de'" html
+
+Congratulations! You got the translated documentation in the ``_build/html``
+directory.
+
+
+Translating
+^^^^^^^^^^^
+
+Translate po file under ``./locale/de/LC_MESSAGES`` directory.
+The case of builders.po file for sphinx document:
+
+.. code-block:: po
+
+ # a5600c3d2e3d48fc8c261ea0284db79b
+ #: ../../builders.rst:4
+ msgid "Available builders"
+ msgstr "<FILL HERE BY TARGET LANGUAGE>"
+
+Another case, msgid is multi-line text and contains reStructuredText
+syntax:
+
+.. code-block:: po
+
+ # 302558364e1d41c69b3277277e34b184
+ #: ../../builders.rst:9
+ msgid ""
+ "These are the built-in Sphinx builders. More builders can be added by "
+ ":ref:`extensions <extensions>`."
+ msgstr ""
+ "FILL HERE BY TARGET LANGUAGE FILL HERE BY TARGET LANGUAGE FILL HERE "
+ "BY TARGET LANGUAGE :ref:`EXTENSIONS <extensions>` FILL HERE."
+
+Please be careful not to break reST notation. Most po-editors will help you
+with that.
+
+
+Update your po files by new pot files
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If a document is updated, it is necessary to generate updated pot files
+and to apply differences to translated po files.
+In order to apply the updating difference of a pot file to po file,
+use the :command:`sphinx-intl update` command.
+
+.. code-block:: bash
+
+ $ sphinx-intl update -p _build/locale
+
+
+Using Transifex service for team translation
+--------------------------------------------
+
+Transifex_ is one of several services that allow collaborative translation via a
+web interface. It has a nifty Python-based command line client that makes it
+easy to fetch and push translations.
+
+.. TODO: why use transifex?
+
+
+#. Install `transifex-client`_
+
+ You need :command:`tx` command to upload resources (pot files).
+
+ .. code-block:: bash
+
+ $ pip install transifex-client
+
+ .. seealso:: `Transifex Client v0.8 — Transifex documentation`_
+
+
+#. Create your transifex_ account and create new project for your document
+
+ Currently, transifex does not allow for a translation project to have more
+ than one version of the document, so you'd better include a version number in
+ your project name.
+
+ For example:
+
+ :Project ID: ``sphinx-document-test_1_0``
+ :Project URL: https://www.transifex.com/projects/p/sphinx-document-test_1_0/
+
+
+#. Create config files for tx command
+
+ This process will create ``.tx/config`` in the current directory, as well as
+ a ``~/.transifexrc`` file that includes auth information.
+
+ .. code-block:: bash
+
+ $ tx init --user=<transifex-username> --pass=<transifex-password>
+ Creating .tx folder...
+ Transifex instance [https://www.transifex.com]:
+ ...
+ Done.
+
+#. Upload pot files to transifex service
+
+ Register pot files to ``.tx/config`` file:
+
+ .. code-block:: bash
+
+ $ cd /your/document/root
+ $ sphinx-intl update-txconfig-resources --pot-dir _build/locale \
+ --transifex-project-name sphinx-document-test_1_0
+
+ and upload pot files:
+
+ .. code-block:: bash
+
+ $ tx push -s
+ Pushing translations for resource sphinx-document-test_1_0.builders:
+ Pushing source file (locale/pot/builders.pot)
+ Resource does not exist. Creating...
+ ...
+ Done.
+
+
+#. Forward the translation on transifex
+
+ .. TODO: write this section
+
+
+#. Pull translated po files and make translated html
+
+ Get translated catalogs and build mo files (ex. for 'de'):
+
+ .. code-block:: bash
+
+ $ cd /your/document/root
+ $ tx pull -l de
+ Pulling translations for resource sphinx-document-test_1_0.builders (...)
+ -> de: locale/de/LC_MESSAGES/builders.po
+ ...
+ Done.
+
+ Build po files into mo and make html::
+
+ $ sphinx-intl build
+ $ make -e SPHINXOPTS="-D language='de'" html
+
+
+That's all!
+
+
+.. tip:: Translating locally and on Transifex
+
+ If you want to push all language's po files, you can be done by using
+ :command:`tx push -t` command.
+ Watch out! This operation overwrites translations in transifex.
+
+ In other words, if you have updated each in the service and local po files,
+ it would take much time and effort to integrate them.
+
+
+
+Contributing to Sphinx reference translation
+--------------------------------------------
+
+The recommended way for new contributors to translate Sphinx reference
+is to join the translation team on Transifex.
+
+There is `sphinx translation page`_ for Sphinx-1.2 documentation.
+
+1. Login to transifex_ service.
+2. Go to `sphinx translation page`_.
+3. Click ``Request language`` and fill form.
+4. Wait acceptance by transifex sphinx translation maintainers.
+5. (after acceptance) translate on transifex.
+
+
+.. rubric:: Footnotes
+
+.. [1] See the `GNU gettext utilites
+ <http://www.gnu.org/software/gettext/manual/gettext.html#Introduction>`_
+ for details on that software suite.
+.. [2] Because nobody expects the Spanish Inquisition!
+
+
+.. _`transifex-client`: https://pypi.python.org/pypi/transifex-client
+.. _`sphinx-intl`: https://pypi.python.org/pypi/sphinx-intl
+.. _Transifex: https://www.transifex.com/
+.. _`sphinx translation page`: https://www.transifex.com/projects/p/sphinx-doc-1_2_0/
+.. _`Transifex Client v0.8 — Transifex documentation`: http://help.transifex.com/features/client/index.html
diff --git a/doc/intro.rst b/doc/intro.rst
new file mode 100644
index 0000000..66d0c58
--- /dev/null
+++ b/doc/intro.rst
@@ -0,0 +1,72 @@
+Introduction
+============
+
+This is the documentation for the Sphinx documentation builder. Sphinx is a
+tool that translates a set of reStructuredText_ source files into various output
+formats, automatically producing cross-references, indices etc. That is, if
+you have a directory containing a bunch of reST-formatted documents (and
+possibly subdirectories of docs in there as well), Sphinx can generate a
+nicely-organized arrangement of HTML files (in some other directory) for easy
+browsing and navigation. But from the same source, it can also generate a
+LaTeX file that you can compile into a PDF version of the documents, or a
+PDF file directly using `rst2pdf <http://rst2pdf.googlecode.com>`_.
+
+The focus is on hand-written documentation, rather than auto-generated API docs.
+Though there is support for that kind of docs as well (which is intended to be
+freely mixed with hand-written content), if you need pure API docs have a look
+at `Epydoc <http://epydoc.sf.net/>`_, which also understands reST.
+
+For a great "introduction" to writing docs in general -- the whys and hows, see
+also `Write the docs <http://write-the-docs.readthedocs.org/>`_, written by Eric
+Holscher.
+
+
+Conversion from other systems
+-----------------------------
+
+This section is intended to collect helpful hints for those wanting to migrate
+to reStructuredText/Sphinx from other documentation systems.
+
+* Gerard Flanagan has written a script to convert pure HTML to reST; it can be
+ found at the `Python Package Index <https://pypi.python.org/pypi/html2rest>`_.
+
+* For converting the old Python docs to Sphinx, a converter was written which
+ can be found at `the Python SVN repository
+ <http://svn.python.org/projects/doctools/converter>`_. It contains generic
+ code to convert Python-doc-style LaTeX markup to Sphinx reST.
+
+* Marcin Wojdyr has written a script to convert Docbook to reST with Sphinx
+ markup; it is at `Google Code <http://code.google.com/p/db2rst/>`_.
+
+* Christophe de Vienne wrote a tool to convert from Open/LibreOffice documents
+ to Sphinx: `odt2sphinx <https://pypi.python.org/pypi/odt2sphinx/>`_.
+
+* To convert different markups, `Pandoc <http://johnmacfarlane.net/pandoc/>`_ is
+ a very helpful tool.
+
+
+Use with other systems
+----------------------
+
+See the :ref:`pertinent section in the FAQ list <usingwith>`.
+
+
+Prerequisites
+-------------
+
+Sphinx needs at least **Python 2.5** or **Python 3.1** to run, as well as the
+docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.7
+or some (not broken) SVN trunk snapshot. If you like to have source code
+highlighting support, you must also install the Pygments_ library.
+
+.. _reStructuredText: http://docutils.sf.net/rst.html
+.. _docutils: http://docutils.sf.net/
+.. _Jinja2: http://jinja.pocoo.org/
+.. _Pygments: http://pygments.org/
+
+
+Usage
+-----
+
+See :doc:`tutorial` for an introduction. It also contains links to more
+advanced sections in this manual for the topics it discusses.
diff --git a/doc/invocation.rst b/doc/invocation.rst
new file mode 100644
index 0000000..654921b
--- /dev/null
+++ b/doc/invocation.rst
@@ -0,0 +1,314 @@
+.. _invocation:
+
+Invocation of sphinx-build
+==========================
+
+The :program:`sphinx-build` script builds a Sphinx documentation set. It is
+called like this::
+
+ $ sphinx-build [options] sourcedir builddir [filenames]
+
+where *sourcedir* is the :term:`source directory`, and *builddir* is the
+directory in which you want to place the built documentation. Most of the time,
+you don't need to specify any *filenames*.
+
+The :program:`sphinx-build` script has several options:
+
+.. program:: sphinx-build
+
+.. option:: -b buildername
+
+ The most important option: it selects a builder. The most common builders
+ are:
+
+ **html**
+ Build HTML pages. This is the default builder.
+
+ **dirhtml**
+ Build HTML pages, but with a single directory per document. Makes for
+ prettier URLs (no ``.html``) if served from a webserver.
+
+ **singlehtml**
+ Build a single HTML with the whole content.
+
+ **htmlhelp**, **qthelp**, **devhelp**, **epub**
+ Build HTML files with additional information for building a documentation
+ collection in one of these formats.
+
+ **latex**
+ Build LaTeX sources that can be compiled to a PDF document using
+ :program:`pdflatex`.
+
+ **man**
+ Build manual pages in groff format for UNIX systems.
+
+ **texinfo**
+ Build Texinfo files that can be processed into Info files using
+ :program:`makeinfo`.
+
+ **text**
+ Build plain text files.
+
+ **gettext**
+ Build gettext-style message catalogs (``.pot`` files).
+
+ **doctest**
+ Run all doctests in the documentation, if the :mod:`~sphinx.ext.doctest`
+ extension is enabled.
+
+ **linkcheck**
+ Check the integrity of all external links.
+
+ **xml**
+ Build Docutils-native XML files.
+
+ **pseudoxml**
+ Build compact pretty-printed "pseudo-XML" files displaying the
+ internal structure of the intermediate document trees.
+
+ See :ref:`builders` for a list of all builders shipped with Sphinx.
+ Extensions can add their own builders.
+
+.. option:: -a
+
+ If given, always write all output files. The default is to only write output
+ files for new and changed source files. (This may not apply to all
+ builders.)
+
+.. option:: -E
+
+ Don't use a saved :term:`environment` (the structure caching all
+ cross-references), but rebuild it completely. The default is to only read
+ and parse source files that are new or have changed since the last run.
+
+.. option:: -t tag
+
+ Define the tag *tag*. This is relevant for :rst:dir:`only` directives that only
+ include their content if this tag is set.
+
+ .. versionadded:: 0.6
+
+.. option:: -d path
+
+ Since Sphinx has to read and parse all source files before it can write an
+ output file, the parsed source files are cached as "doctree pickles".
+ Normally, these files are put in a directory called :file:`.doctrees` under
+ the build directory; with this option you can select a different cache
+ directory (the doctrees can be shared between all builders).
+
+.. option:: -j N
+
+ Distribute the build over *N* processes in parallel, to make building on
+ multiprocessor machines more effective. Note that not all parts and not all
+ builders of Sphinx can be parallelized.
+
+ .. versionadded:: 1.2
+ This option should be considered *experimental*.
+
+.. option:: -c path
+
+ Don't look for the :file:`conf.py` in the source directory, but use the given
+ configuration directory instead. Note that various other files and paths
+ given by configuration values are expected to be relative to the
+ configuration directory, so they will have to be present at this location
+ too.
+
+ .. versionadded:: 0.3
+
+.. option:: -C
+
+ Don't look for a configuration file; only take options via the ``-D`` option.
+
+ .. versionadded:: 0.5
+
+.. option:: -D setting=value
+
+ Override a configuration value set in the :file:`conf.py` file. The value
+ must be a string or dictionary value. For the latter, supply the setting
+ name and key like this: ``-D latex_elements.docclass=scrartcl``. For boolean
+ values, use ``0`` or ``1`` as the value.
+
+ .. versionchanged:: 0.6
+ The value can now be a dictionary value.
+
+.. option:: -A name=value
+
+ Make the *name* assigned to *value* in the HTML templates.
+
+ .. versionadded:: 0.5
+
+.. option:: -n
+
+ Run in nit-picky mode. Currently, this generates warnings for all missing
+ references. See the config value :confval:`nitpick_ignore` for a way to
+ exclude some references as "known missing".
+
+.. option:: -N
+
+ Do not emit colored output. (On Windows, colored output is disabled in any
+ case.)
+
+.. option:: -v
+
+ Increase verbosity (loglevel). This option can be given up to three times
+ to get more debug logging output. It implies :option:`-T`.
+
+ .. versionadded:: 1.2
+
+.. option:: -q
+
+ Do not output anything on standard output, only write warnings and errors to
+ standard error.
+
+.. option:: -Q
+
+ Do not output anything on standard output, also suppress warnings. Only
+ errors are written to standard error.
+
+.. option:: -w file
+
+ Write warnings (and errors) to the given file, in addition to standard error.
+
+.. option:: -W
+
+ Turn warnings into errors. This means that the build stops at the first
+ warning and ``sphinx-build`` exits with exit status 1.
+
+.. option:: -T
+
+ Display the full traceback when an unhandled exception occurs. Otherwise,
+ only a summary is displayed and the traceback information is saved to a file
+ for further analysis.
+
+ .. versionadded:: 1.2
+
+.. option:: -P
+
+ (Useful for debugging only.) Run the Python debugger, :mod:`pdb`, if an
+ unhandled exception occurs while building.
+
+.. option:: -h, --help, --version
+
+ Display usage summary or Sphinx version.
+
+ .. versionadded:: 1.2
+
+You can also give one or more filenames on the command line after the source and
+build directories. Sphinx will then try to build only these output files (and
+their dependencies).
+
+
+Makefile options
+----------------
+
+The :file:`Makefile` and :file:`make.bat` files created by
+:program:`sphinx-quickstart` usually run :program:`sphinx-build` only with the
+:option:`-b` and :option:`-d` options. However, they support the following
+variables to customize behavior:
+
+.. describe:: PAPER
+
+ The value for :confval:`latex_paper_size`.
+
+.. describe:: SPHINXBUILD
+
+ The command to use instead of ``sphinx-build``.
+
+.. describe:: BUILDDIR
+
+ The build directory to use instead of the one chosen in
+ :program:`sphinx-quickstart`.
+
+.. describe:: SPHINXOPTS
+
+ Additional options for :program:`sphinx-build`.
+
+
+.. _invocation-apidoc:
+
+Invocation of sphinx-apidoc
+===========================
+
+The :program:`sphinx-apidoc` generates completely automatic API documentation
+for a Python package. It is called like this::
+
+ $ sphinx-apidoc [options] -o outputdir packagedir [pathnames]
+
+where *packagedir* is the path to the package to document, and *outputdir* is
+the directory where the generated sources are placed. Any *pathnames* given
+are paths to be excluded ignored during generation.
+
+.. warning::
+
+ ``sphinx-apidoc`` generates reST files that use :mod:`sphinx.ext.autodoc` to
+ document all found modules. If any modules have side effects on import,
+ these will be executed by ``autodoc`` when ``sphinx-build`` is run.
+
+ If you document scripts (as opposed to library modules), make sure their main
+ routine is protected by a ``if __name__ == '__main__'`` condition.
+
+
+The :program:`sphinx-apidoc` script has several options:
+
+.. program:: sphinx-apidoc
+
+.. option:: -o outputdir
+
+ Gives the directory in which to place the generated output.
+
+.. option:: -f, --force
+
+ Normally, sphinx-apidoc does not overwrite any files. Use this option to
+ force the overwrite of all files that it generates.
+
+.. option:: -n, --dry-run
+
+ With this option given, no files will be written at all.
+
+.. option:: -s suffix
+
+ This option selects the file name suffix of output files. By default, this
+ is ``rst``.
+
+.. option:: -d maxdepth
+
+ This sets the maximum depth of the table of contents, if one is generated.
+
+.. option:: -l, --follow-links
+
+ This option makes sphinx-apidoc follow symbolic links when recursing the
+ filesystem to discover packages and modules. You may need it if you want
+ to generate documentation from a source directory managed by
+ `collective.recipe.omelette
+ <https://pypi.python.org/pypi/collective.recipe.omelette/>`_.
+ By default, symbolic links are skipped.
+
+ .. versionadded:: 1.2
+
+.. option:: -T, --no-toc
+
+ This prevents the generation of a table-of-contents file ``modules.rst``.
+ This has no effect when :option:`--full` is given.
+
+.. option:: -F, --full
+
+ This option makes sphinx-apidoc create a full Sphinx project, using the same
+ mechanism as :program:`sphinx-quickstart`. Most configuration values are set
+ to default values, but you can influence the most important ones using the
+ following options.
+
+.. option:: -H project
+
+ Sets the project name to put in generated files (see :confval:`project`).
+
+.. option:: -A author
+
+ Sets the author name(s) to put in generated files (see :confval:`copyright`).
+
+.. option:: -V version
+
+ Sets the project version to put in generated files (see :confval:`version`).
+
+.. option:: -R release
+
+ Sets the project release to put in generated files (see :confval:`release`).
diff --git a/doc/man/sphinx-apidoc.rst b/doc/man/sphinx-apidoc.rst
new file mode 100644
index 0000000..a01d2a8
--- /dev/null
+++ b/doc/man/sphinx-apidoc.rst
@@ -0,0 +1,68 @@
+:orphan:
+
+sphinx-apidoc manual page
+=========================
+
+Synopsis
+--------
+
+**sphinx-apidoc** [*options*] -o <*outputdir*> <*sourcedir*> [*pathnames* ...]
+
+
+Description
+-----------
+
+:program:`sphinx-apidoc` is a tool for automatic generation of Sphinx sources
+that, using the autodoc extension, document a whole package in the style of
+other automatic API documentation tools.
+
+*sourcedir* must point to a Python package. Any *pathnames* given are paths to
+be excluded from the generation.
+
+.. warning::
+
+ ``sphinx-apidoc`` generates source files that use :mod:`sphinx.ext.autodoc`
+ to document all found modules. If any modules have side effects on import,
+ these will be executed by ``autodoc`` when ``sphinx-build`` is run.
+
+ If you document scripts (as opposed to library modules), make sure their main
+ routine is protected by a ``if __name__ == '__main__'`` condition.
+
+
+Options
+-------
+
+-o <outputdir> Directory to place the output files. If it does not exist,
+ it is created.
+-f, --force Usually, apidoc does not overwrite files, unless this option
+ is given.
+-l, --follow-links Follow symbolic links.
+-n, --dry-run If given, apidoc does not create any files.
+-s <suffix> Suffix for the source files generated, default is ``rst``.
+-d <maxdepth> Maximum depth for the generated table of contents file.
+-T, --no-toc Do not create a table of contents file.
+-F, --full If given, a full Sphinx project is generated (``conf.py``,
+ ``Makefile`` etc.) using sphinx-quickstart.
+-e, --separate Put each module file in its own page.
+-E, --no-headings Don't create headings for the modules/packages
+-P, --private Include "_private" modules
+
+These options are used with ``-F``:
+
+-H <project> Project name to put into the configuration.
+-A <author> Author name(s) to put into the configuration.
+-V <version> Project version.
+-R <release> Project release.
+
+
+See also
+--------
+
+:manpage:`sphinx-build(1)`
+
+
+Author
+------
+
+Etienne Desautels, <etienne.desautels at gmail.com>, Georg Brandl
+<georg at python.org> et al.
diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst
new file mode 100644
index 0000000..aa1d71c
--- /dev/null
+++ b/doc/man/sphinx-build.rst
@@ -0,0 +1,130 @@
+:orphan:
+
+sphinx-build manual page
+========================
+
+Synopsis
+--------
+
+**sphinx-build** [*options*] <*sourcedir*> <*outdir*> [*filenames* ...]
+
+
+Description
+-----------
+
+:program:`sphinx-build` generates documentation from the files in
+``<sourcedir>`` and places it in the ``<outdir>``.
+
+:program:`sphinx-build` looks for ``<sourcedir>/conf.py`` for the configuration
+settings. :manpage:`sphinx-quickstart(1)` may be used to generate template
+files, including ``conf.py``.
+
+:program:`sphinx-build` can create documentation in different formats. A format
+is selected by specifying the builder name on the command line; it defaults to
+HTML. Builders can also perform other tasks related to documentation
+processing.
+
+By default, everything that is outdated is built. Output only for selected
+files can be built by specifying individual filenames.
+
+List of available builders:
+
+html
+ HTML file generation. This is the default builder.
+
+dirhtml
+ HTML file generation with every HTML file named "index.html" in a separate
+ directory.
+
+singlehtml
+ HTML file generation with all content in a single HTML file.
+
+htmlhelp
+ Generates files for CHM (compiled help files) generation.
+
+qthelp
+ Generates files for Qt help collection generation.
+
+devhelp
+ Generates files for the GNOME Devhelp help viewer.
+
+latex
+ Generates LaTeX output that can be compiled to a PDF document.
+
+man
+ Generates manual pages.
+
+texinfo
+ Generates Texinfo output that can be processed by :program:`makeinfo` to
+ generate an Info document.
+
+epub
+ Generates an ePub e-book version of the HTML output.
+
+text
+ Generates a plain-text version of the documentation.
+
+gettext
+ Generates Gettext message catalogs for content translation.
+
+changes
+ Generates HTML files listing changed/added/deprecated items for
+ the current version of the documented project.
+
+linkcheck
+ Checks the integrity of all external links in the source.
+
+pickle / json
+ Generates serialized HTML files for use in web applications.
+
+xml
+ Generates Docutils-native XML files.
+
+pseudoxml
+ Generates compact pretty-printed "pseudo-XML" files displaying the
+ internal structure of the intermediate document trees.
+
+
+Options
+-------
+
+-b <builder> Builder to use; defaults to html. See the full list
+ of builders above.
+-a Generate output for all files; without this option only
+ output for new and changed files is generated.
+-E Ignore cached files, forces to re-read all source files
+ from disk.
+-d <path> Path to cached files; defaults to <outdir>/.doctrees.
+-j <N> Build in parallel with N processes where possible.
+-c <path> Locate the conf.py file in the specified path instead of
+ <sourcedir>.
+-C Specify that no conf.py file at all is to be used.
+ Configuration can only be set with the -D option.
+-D <setting=value> Override a setting from the configuration file.
+-t <tag> Define *tag* for use in "only" blocks.
+-A <name=value> Pass a value into the HTML templates (only for HTML builders).
+-n Run in nit-picky mode, warn about all missing references.
+-v Increase verbosity (can be repeated).
+-N Prevent colored output.
+-q Quiet operation, just print warnings and errors on stderr.
+-Q Very quiet operation, don't print anything except for errors.
+-w <file> Write warnings and errors into the given file, in addition
+ to stderr.
+-W Turn warnings into errors.
+-T Show full traceback on exception.
+-P Run Pdb on exception.
+
+
+See also
+--------
+
+:manpage:`sphinx-quickstart(1)`
+
+Author
+------
+
+Georg Brandl <georg at python.org>, Armin Ronacher <armin.ronacher at active-4.com> et
+al.
+
+This manual page was initially written by Mikhail Gusarov
+<dottedmag at dottedmag.net>, for the Debian project.
diff --git a/doc/man/sphinx-quickstart.rst b/doc/man/sphinx-quickstart.rst
new file mode 100644
index 0000000..1727726
--- /dev/null
+++ b/doc/man/sphinx-quickstart.rst
@@ -0,0 +1,33 @@
+:orphan:
+
+sphinx-quickstart manual page
+=============================
+
+Synopsis
+--------
+
+**sphinx-quickstart**
+
+
+Description
+-----------
+
+:program:`sphinx-quickstart` is an interactive tool that asks some questions
+about your project and then generates a complete documentation directory and
+sample Makefile to be used with :manpage:`sphinx-build(1)`.
+
+
+See also
+--------
+
+:manpage:`sphinx-build(1)`
+
+
+Author
+------
+
+Georg Brandl <georg at python.org>, Armin Ronacher <armin.ronacher at active-4.com> et
+al.
+
+This manual page was initially written by Mikhail Gusarov
+<dottedmag at dottedmag.net>, for the Debian project.
diff --git a/doc/markup/code.rst b/doc/markup/code.rst
new file mode 100644
index 0000000..957774f
--- /dev/null
+++ b/doc/markup/code.rst
@@ -0,0 +1,183 @@
+.. highlight:: rest
+
+.. _code-examples:
+
+Showing code examples
+---------------------
+
+.. index:: pair: code; examples
+ single: sourcecode
+
+Examples of Python source code or interactive sessions are represented using
+standard reST literal blocks. They are started by a ``::`` at the end of the
+preceding paragraph and delimited by indentation.
+
+Representing an interactive session requires including the prompts and output
+along with the Python code. No special markup is required for interactive
+sessions. After the last line of input or output presented, there should not be
+an "unused" primary prompt; this is an example of what *not* to do::
+
+ >>> 1 + 1
+ 2
+ >>>
+
+Syntax highlighting is done with `Pygments <http://pygments.org>`_ (if it's
+installed) and handled in a smart way:
+
+* There is a "highlighting language" for each source file. Per default, this is
+ ``'python'`` as the majority of files will have to highlight Python snippets,
+ but the doc-wide default can be set with the :confval:`highlight_language`
+ config value.
+
+* Within Python highlighting mode, interactive sessions are recognized
+ automatically and highlighted appropriately. Normal Python code is only
+ highlighted if it is parseable (so you can use Python as the default, but
+ interspersed snippets of shell commands or other code blocks will not be
+ highlighted as Python).
+
+* The highlighting language can be changed using the ``highlight`` directive,
+ used as follows::
+
+ .. highlight:: c
+
+ This language is used until the next ``highlight`` directive is encountered.
+
+* For documents that have to show snippets in different languages, there's also
+ a :rst:dir:`code-block` directive that is given the highlighting language
+ directly::
+
+ .. code-block:: ruby
+
+ Some Ruby code.
+
+ The directive's alias name :rst:dir:`sourcecode` works as well.
+
+* The valid values for the highlighting language are:
+
+ * ``none`` (no highlighting)
+ * ``python`` (the default when :confval:`highlight_language` isn't set)
+ * ``guess`` (let Pygments guess the lexer based on contents, only works with
+ certain well-recognizable languages)
+ * ``rest``
+ * ``c``
+ * ... and any other `lexer alias that Pygments supports
+ <http://pygments.org/docs/lexers/>`_.
+
+* If highlighting with the selected language fails (i.e. Pygments emits an
+ "Error" token), the block is not highlighted in any way.
+
+Line numbers
+^^^^^^^^^^^^
+
+If installed, Pygments can generate line numbers for code blocks. For
+automatically-highlighted blocks (those started by ``::``), line numbers must be
+switched on in a :rst:dir:`highlight` directive, with the ``linenothreshold``
+option::
+
+ .. highlight:: python
+ :linenothreshold: 5
+
+This will produce line numbers for all code blocks longer than five lines.
+
+For :rst:dir:`code-block` blocks, a ``linenos`` flag option can be given to switch
+on line numbers for the individual block::
+
+ .. code-block:: ruby
+ :linenos:
+
+ Some more Ruby code.
+
+Additionally, an ``emphasize-lines`` option can be given to have Pygments
+emphasize particular lines::
+
+ .. code-block:: python
+ :emphasize-lines: 3,5
+
+ def some_function():
+ interesting = False
+ print 'This line is highlighted.'
+ print 'This one is not...'
+ print '...but this one is.'
+
+.. versionchanged:: 1.1
+ ``emphasize-lines`` has been added.
+
+
+Includes
+^^^^^^^^
+
+.. rst:directive:: .. literalinclude:: filename
+
+ Longer displays of verbatim text may be included by storing the example text in
+ an external file containing only plain text. The file may be included using the
+ ``literalinclude`` directive. [1]_ For example, to include the Python source file
+ :file:`example.py`, use::
+
+ .. literalinclude:: example.py
+
+ The file name is usually relative to the current file's path. However, if it
+ is absolute (starting with ``/``), it is relative to the top source
+ directory.
+
+ Tabs in the input are expanded if you give a ``tab-width`` option with the
+ desired tab width.
+
+ The directive also supports the ``linenos`` flag option to switch on line
+ numbers, the ``emphasize-lines`` option to emphasize particular lines, and
+ a ``language`` option to select a language different from the current
+ file's standard language. Example with options::
+
+ .. literalinclude:: example.rb
+ :language: ruby
+ :emphasize-lines: 12,15-18
+ :linenos:
+
+ Include files are assumed to be encoded in the :confval:`source_encoding`.
+ If the file has a different encoding, you can specify it with the
+ ``encoding`` option::
+
+ .. literalinclude:: example.py
+ :encoding: latin-1
+
+ The directive also supports including only parts of the file. If it is a
+ Python module, you can select a class, function or method to include using
+ the ``pyobject`` option::
+
+ .. literalinclude:: example.py
+ :pyobject: Timer.start
+
+ This would only include the code lines belonging to the ``start()`` method in
+ the ``Timer`` class within the file.
+
+ Alternately, you can specify exactly which lines to include by giving a
+ ``lines`` option::
+
+ .. literalinclude:: example.py
+ :lines: 1,3,5-10,20-
+
+ This includes the lines 1, 3, 5 to 10 and lines 20 to the last line.
+
+ Another way to control which part of the file is included is to use the
+ ``start-after`` and ``end-before`` options (or only one of them). If
+ ``start-after`` is given as a string option, only lines that follow the first
+ line containing that string are included. If ``end-before`` is given as a
+ string option, only lines that precede the first lines containing that string
+ are included.
+
+ You can prepend and/or append a line to the included code, using the
+ ``prepend`` and ``append`` option, respectively. This is useful e.g. for
+ highlighting PHP code that doesn't include the ``<?php``/``?>`` markers.
+
+ .. versionadded:: 0.4.3
+ The ``encoding`` option.
+ .. versionadded:: 0.6
+ The ``pyobject``, ``lines``, ``start-after`` and ``end-before`` options,
+ as well as support for absolute filenames.
+ .. versionadded:: 1.0
+ The ``prepend`` and ``append`` options, as well as ``tab-width``.
+
+
+.. rubric:: Footnotes
+
+.. [1] There is a standard ``.. include`` directive, but it raises errors if the
+ file is not found. This one only emits a warning.
diff --git a/doc/markup/index.rst b/doc/markup/index.rst
new file mode 100644
index 0000000..ca70b95
--- /dev/null
+++ b/doc/markup/index.rst
@@ -0,0 +1,19 @@
+.. _sphinxmarkup:
+
+Sphinx Markup Constructs
+========================
+
+Sphinx adds a lot of new directives and interpreted text roles to `standard reST
+markup`_. This section contains the reference material for these facilities.
+
+.. toctree::
+
+ toctree
+ para
+ code
+ inline
+ misc
+
+More markup is added by :ref:`domains`.
+
+.. _standard reST markup: http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html
diff --git a/doc/markup/inline.rst b/doc/markup/inline.rst
new file mode 100644
index 0000000..69dd832
--- /dev/null
+++ b/doc/markup/inline.rst
@@ -0,0 +1,371 @@
+.. highlight:: rest
+
+.. _inline-markup:
+
+Inline markup
+=============
+
+Sphinx uses interpreted text roles to insert semantic markup into documents.
+They are written as ``:rolename:`content```.
+
+.. note::
+
+ The default role (```content```) has no special meaning by default. You are
+ free to use it for anything you like, e.g. variable names; use the
+ :confval:`default_role` config value to set it to a known role.
+
+See :ref:`domains` for roles added by domains.
+
+
+.. _xref-syntax:
+
+Cross-referencing syntax
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Cross-references are generated by many semantic interpreted text roles.
+Basically, you only need to write ``:role:`target```, and a link will be created
+to the item named *target* of the type indicated by *role*. The links's text
+will be the same as *target*.
+
+There are some additional facilities, however, that make cross-referencing roles
+more versatile:
+
+* You may supply an explicit title and reference target, like in reST direct
+ hyperlinks: ``:role:`title <target>``` will refer to *target*, but the link
+ text will be *title*.
+
+* If you prefix the content with ``!``, no reference/hyperlink will be created.
+
+* If you prefix the content with ``~``, the link text will only be the last
+ component of the target. For example, ``:py:meth:`~Queue.Queue.get``` will
+ refer to ``Queue.Queue.get`` but only display ``get`` as the link text.
+
+ In HTML output, the link's ``title`` attribute (that is e.g. shown as a
+ tool-tip on mouse-hover) will always be the full target name.
+
+
+Cross-referencing objects
+-------------------------
+
+These roles are described with their respective domains:
+
+* :ref:`Python <python-roles>`
+* :ref:`C <c-roles>`
+* :ref:`C++ <cpp-roles>`
+* :ref:`JavaScript <js-roles>`
+* :ref:`ReST <rst-roles>`
+
+
+.. _ref-role:
+
+Cross-referencing arbitrary locations
+-------------------------------------
+
+.. rst:role:: ref
+
+ To support cross-referencing to arbitrary locations in any document, the
+ standard reST labels are used. For this to work label names must be unique
+ throughout the entire documentation. There are two ways in which you can
+ refer to labels:
+
+ * If you place a label directly before a section title, you can reference to
+ it with ``:ref:`label-name```. Example::
+
+ .. _my-reference-label:
+
+ Section to cross-reference
+ --------------------------
+
+ This is the text of the section.
+
+ It refers to the section itself, see :ref:`my-reference-label`.
+
+ The ``:ref:`` role would then generate a link to the section, with the link
+ title being "Section to cross-reference". This works just as well when
+ section and reference are in different source files.
+
+ Automatic labels also work with figures: given ::
+
+ .. _my-figure:
+
+ .. figure:: whatever
+
+ Figure caption
+
+ a reference ``:ref:`my-figure``` would insert a reference to the figure
+ with link text "Figure caption".
+
+ The same works for tables that are given an explicit caption using the
+ :dudir:`table` directive.
+
+ * Labels that aren't placed before a section title can still be referenced
+ to, but you must give the link an explicit title, using this syntax:
+ ``:ref:`Link title <label-name>```.
+
+ Using :rst:role:`ref` is advised over standard reStructuredText links to sections
+ (like ```Section title`_``) because it works across files, when section
+ headings are changed, and for all builders that support cross-references.
+
+
+Cross-referencing documents
+---------------------------
+
+.. versionadded:: 0.6
+
+There is also a way to directly link to documents:
+
+.. rst:role:: doc
+
+ Link to the specified document; the document name can be specified in
+ absolute or relative fashion. For example, if the reference
+ ``:doc:`parrot``` occurs in the document ``sketches/index``, then the link
+ refers to ``sketches/parrot``. If the reference is ``:doc:`/people``` or
+ ``:doc:`../people```, the link refers to ``people``.
+
+ If no explicit link text is given (like usual: ``:doc:`Monty Python members
+ </people>```), the link caption will be the title of the given document.
+
+
+Referencing downloadable files
+------------------------------
+
+.. versionadded:: 0.6
+
+.. rst:role:: download
+
+ This role lets you link to files within your source tree that are not reST
+ documents that can be viewed, but files that can be downloaded.
+
+ When you use this role, the referenced file is automatically marked for
+ inclusion in the output when building (obviously, for HTML output only).
+ All downloadable files are put into the ``_downloads`` subdirectory of the
+ output directory; duplicate filenames are handled.
+
+ An example::
+
+ See :download:`this example script <../example.py>`.
+
+ The given filename is usually relative to the directory the current source
+ file is contained in, but if it absolute (starting with ``/``), it is taken
+ as relative to the top source directory.
+
+ The ``example.py`` file will be copied to the output directory, and a
+ suitable link generated to it.
+
+
+Cross-referencing other items of interest
+-----------------------------------------
+
+The following roles do possibly create a cross-reference, but do not refer to
+objects:
+
+.. rst:role:: envvar
+
+ An environment variable. Index entries are generated. Also generates a link
+ to the matching :rst:dir:`envvar` directive, if it exists.
+
+.. rst:role:: token
+
+ The name of a grammar token (used to create links between
+ :rst:dir:`productionlist` directives).
+
+.. rst:role:: keyword
+
+ The name of a keyword in Python. This creates a link to a reference label
+ with that name, if it exists.
+
+.. rst:role:: option
+
+ A command-line option to an executable program. The leading hyphen(s) must
+ be included. This generates a link to a :rst:dir:`option` directive, if it
+ exists.
+
+
+The following role creates a cross-reference to the term in the glossary:
+
+.. rst:role:: term
+
+ Reference to a term in the glossary. The glossary is created using the
+ ``glossary`` directive containing a definition list with terms and
+ definitions. It does not have to be in the same file as the ``term`` markup,
+ for example the Python docs have one global glossary in the ``glossary.rst``
+ file.
+
+ If you use a term that's not explained in a glossary, you'll get a warning
+ during build.
+
+
+Other semantic markup
+~~~~~~~~~~~~~~~~~~~~~
+
+The following roles don't do anything special except formatting the text
+in a different style:
+
+.. rst:role:: abbr
+
+ An abbreviation. If the role content contains a parenthesized explanation,
+ it will be treated specially: it will be shown in a tool-tip in HTML, and
+ output only once in LaTeX.
+
+ Example: ``:abbr:`LIFO (last-in, first-out)```.
+
+ .. versionadded:: 0.6
+
+.. rst:role:: command
+
+ The name of an OS-level command, such as ``rm``.
+
+.. rst:role:: dfn
+
+ Mark the defining instance of a term in the text. (No index entries are
+ generated.)
+
+.. rst:role:: file
+
+ The name of a file or directory. Within the contents, you can use curly
+ braces to indicate a "variable" part, for example::
+
+ ... is installed in :file:`/usr/lib/python2.{x}/site-packages` ...
+
+ In the built documentation, the ``x`` will be displayed differently to
+ indicate that it is to be replaced by the Python minor version.
+
+.. rst:role:: guilabel
+
+ Labels presented as part of an interactive user interface should be marked
+ using ``guilabel``. This includes labels from text-based interfaces such as
+ those created using :mod:`curses` or other text-based libraries. Any label
+ used in the interface should be marked with this role, including button
+ labels, window titles, field names, menu and menu selection names, and even
+ values in selection lists.
+
+ .. versionchanged:: 1.0
+ An accelerator key for the GUI label can be included using an ampersand;
+ this will be stripped and displayed underlined in the output (example:
+ ``:guilabel:`&Cancel```). To include a literal ampersand, double it.
+
+.. rst:role:: kbd
+
+ Mark a sequence of keystrokes. What form the key sequence takes may depend
+ on platform- or application-specific conventions. When there are no relevant
+ conventions, the names of modifier keys should be spelled out, to improve
+ accessibility for new users and non-native speakers. For example, an
+ *xemacs* key sequence may be marked like ``:kbd:`C-x C-f```, but without
+ reference to a specific application or platform, the same sequence should be
+ marked as ``:kbd:`Control-x Control-f```.
+
+.. rst:role:: mailheader
+
+ The name of an RFC 822-style mail header. This markup does not imply that
+ the header is being used in an email message, but can be used to refer to any
+ header of the same "style." This is also used for headers defined by the
+ various MIME specifications. The header name should be entered in the same
+ way it would normally be found in practice, with the camel-casing conventions
+ being preferred where there is more than one common usage. For example:
+ ``:mailheader:`Content-Type```.
+
+.. rst:role:: makevar
+
+ The name of a :command:`make` variable.
+
+.. rst:role:: manpage
+
+ A reference to a Unix manual page including the section,
+ e.g. ``:manpage:`ls(1)```.
+
+.. rst:role:: menuselection
+
+ Menu selections should be marked using the ``menuselection`` role. This is
+ used to mark a complete sequence of menu selections, including selecting
+ submenus and choosing a specific operation, or any subsequence of such a
+ sequence. The names of individual selections should be separated by
+ ``-->``.
+
+ For example, to mark the selection "Start > Programs", use this markup::
+
+ :menuselection:`Start --> Programs`
+
+ When including a selection that includes some trailing indicator, such as the
+ ellipsis some operating systems use to indicate that the command opens a
+ dialog, the indicator should be omitted from the selection name.
+
+ ``menuselection`` also supports ampersand accelerators just like
+ :rst:role:`guilabel`.
+
+.. rst:role:: mimetype
+
+ The name of a MIME type, or a component of a MIME type (the major or minor
+ portion, taken alone).
+
+.. rst:role:: newsgroup
+
+ The name of a Usenet newsgroup.
+
+.. rst:role:: program
+
+ The name of an executable program. This may differ from the file name for
+ the executable for some platforms. In particular, the ``.exe`` (or other)
+ extension should be omitted for Windows programs.
+
+.. rst:role:: regexp
+
+ A regular expression. Quotes should not be included.
+
+.. rst:role:: samp
+
+ A piece of literal text, such as code. Within the contents, you can use
+ curly braces to indicate a "variable" part, as in :rst:role:`file`. For
+ example, in ``:samp:`print 1+{variable}```, the part ``variable`` would be
+ emphasized.
+
+ If you don't need the "variable part" indication, use the standard
+ ````code```` instead.
+
+There is also an :rst:role:`index` role to generate index entries.
+
+The following roles generate external links:
+
+.. rst:role:: pep
+
+ A reference to a Python Enhancement Proposal. This generates appropriate
+ index entries. The text "PEP *number*\ " is generated; in the HTML output,
+ this text is a hyperlink to an online copy of the specified PEP. You can
+ link to a specific section by saying ``:pep:`number#anchor```.
+
+.. rst:role:: rfc
+
+ A reference to an Internet Request for Comments. This generates appropriate
+ index entries. The text "RFC *number*\ " is generated; in the HTML output,
+ this text is a hyperlink to an online copy of the specified RFC. You can
+ link to a specific section by saying ``:rfc:`number#anchor```.
+
+
+Note that there are no special roles for including hyperlinks as you can use
+the standard reST markup for that purpose.
+
+
+.. _default-substitutions:
+
+Substitutions
+~~~~~~~~~~~~~
+
+The documentation system provides three substitutions that are defined by default.
+They are set in the build configuration file.
+
+.. describe:: |release|
+
+ Replaced by the project release the documentation refers to. This is meant
+ to be the full version string including alpha/beta/release candidate tags,
+ e.g. ``2.5.2b3``. Set by :confval:`release`.
+
+.. describe:: |version|
+
+ Replaced by the project version the documentation refers to. This is meant to
+ consist only of the major and minor version parts, e.g. ``2.5``, even for
+ version 2.5.1. Set by :confval:`version`.
+
+.. describe:: |today|
+
+ Replaced by either today's date (the date on which the document is read), or
+ the date set in the build configuration file. Normally has the format
+ ``April 14, 2007``. Set by :confval:`today_fmt` and :confval:`today`.
diff --git a/doc/markup/misc.rst b/doc/markup/misc.rst
new file mode 100644
index 0000000..5a391d0
--- /dev/null
+++ b/doc/markup/misc.rst
@@ -0,0 +1,259 @@
+.. highlight:: rest
+
+Miscellaneous markup
+====================
+
+.. _metadata:
+
+File-wide metadata
+------------------
+
+reST has the concept of "field lists"; these are a sequence of fields marked up
+like this::
+
+ :fieldname: Field content
+
+A field list near the top of a file is parsed by docutils as the "docinfo"
+which is normally used to record the author, date of publication and other
+metadata. *In Sphinx*, a field list preceding any other markup is moved from
+the docinfo to the Sphinx environment as document metadata and is not displayed
+in the output; a field list appearing after the document title will be part of
+the docinfo as normal and will be displayed in the output.
+
+At the moment, these metadata fields are recognized:
+
+``tocdepth``
+ The maximum depth for a table of contents of this file.
+
+ .. versionadded:: 0.4
+
+``nocomments``
+ If set, the web application won't display a comment form for a page generated
+ from this source file.
+
+``orphan``
+ If set, warnings about this file not being included in any toctree will be
+ suppressed.
+
+ .. versionadded:: 1.0
+
+
+Meta-information markup
+-----------------------
+
+.. rst:directive:: .. sectionauthor:: name <email>
+
+ Identifies the author of the current section. The argument should include
+ the author's name such that it can be used for presentation and email
+ address. The domain name portion of the address should be lower case.
+ Example::
+
+ .. sectionauthor:: Guido van Rossum <guido at python.org>
+
+ By default, this markup isn't reflected in the output in any way (it helps
+ keep track of contributions), but you can set the configuration value
+ :confval:`show_authors` to True to make them produce a paragraph in the
+ output.
+
+
+.. rst:directive:: .. codeauthor:: name <email>
+
+ The :rst:dir:`codeauthor` directive, which can appear multiple times, names the
+ authors of the described code, just like :rst:dir:`sectionauthor` names the
+ author(s) of a piece of documentation. It too only produces output if the
+ :confval:`show_authors` configuration value is True.
+
+
+Index-generating markup
+-----------------------
+
+Sphinx automatically creates index entries from all object descriptions (like
+functions, classes or attributes) like discussed in :ref:`domains`.
+
+However, there is also explicit markup available, to make the index more
+comprehensive and enable index entries in documents where information is not
+mainly contained in information units, such as the language reference.
+
+.. rst:directive:: .. index:: <entries>
+
+ This directive contains one or more index entries. Each entry consists of a
+ type and a value, separated by a colon.
+
+ For example::
+
+ .. index::
+ single: execution; context
+ module: __main__
+ module: sys
+ triple: module; search; path
+
+ The execution context
+ ---------------------
+
+ ...
+
+ This directive contains five entries, which will be converted to entries in
+ the generated index which link to the exact location of the index statement
+ (or, in case of offline media, the corresponding page number).
+
+ Since index directives generate cross-reference targets at their location in
+ the source, it makes sense to put them *before* the thing they refer to --
+ e.g. a heading, as in the example above.
+
+ The possible entry types are:
+
+ single
+ Creates a single index entry. Can be made a subentry by separating the
+ subentry text with a semicolon (this notation is also used below to
+ describe what entries are created).
+ pair
+ ``pair: loop; statement`` is a shortcut that creates two index entries,
+ namely ``loop; statement`` and ``statement; loop``.
+ triple
+ Likewise, ``triple: module; search; path`` is a shortcut that creates
+ three index entries, which are ``module; search path``, ``search; path,
+ module`` and ``path; module search``.
+ see
+ ``see: entry; other`` creates an index entry that refers from ``entry`` to
+ ``other``.
+ seealso
+ Like ``see``, but inserts "see also" instead of "see".
+ module, keyword, operator, object, exception, statement, builtin
+ These all create two index entries. For example, ``module: hashlib``
+ creates the entries ``module; hashlib`` and ``hashlib; module``. (These
+ are Python-specific and therefore deprecated.)
+
+ You can mark up "main" index entries by prefixing them with an exclamation
+ mark. The references to "main" entries are emphasized in the generated
+ index. For example, if two pages contain ::
+
+ .. index:: Python
+
+ and one page contains ::
+
+ .. index:: ! Python
+
+ then the backlink to the latter page is emphasized among the three backlinks.
+
+ For index directives containing only "single" entries, there is a shorthand
+ notation::
+
+ .. index:: BNF, grammar, syntax, notation
+
+ This creates four index entries.
+
+ .. versionchanged:: 1.1
+ Added ``see`` and ``seealso`` types, as well as marking main entries.
+
+.. rst:role:: index
+
+ While the :rst:dir:`index` directive is a block-level markup and links to the
+ beginning of the next paragraph, there is also a corresponding role that sets
+ the link target directly where it is used.
+
+ The content of the role can be a simple phrase, which is then kept in the
+ text and used as an index entry. It can also be a combination of text and
+ index entry, styled like with explicit targets of cross-references. In that
+ case, the "target" part can be a full entry as described for the directive
+ above. For example::
+
+ This is a normal reST :index:`paragraph` that contains several
+ :index:`index entries <pair: index; entry>`.
+
+ .. versionadded:: 1.1
+
+
+.. _tags:
+
+Including content based on tags
+-------------------------------
+
+.. rst:directive:: .. only:: <expression>
+
+ Include the content of the directive only if the *expression* is true. The
+ expression should consist of tags, like this::
+
+ .. only:: html and draft
+
+ Undefined tags are false, defined tags (via the ``-t`` command-line option or
+ within :file:`conf.py`, see :ref:`here <conf-tags>`) are true. Boolean
+ expressions, also using parentheses (like ``html and (latex or draft)``) are
+ supported.
+
+ The *format* and the *name* of the current builder (``html``, ``latex`` or
+ ``text``) are always set as a tag [#]_. To make the distinction between
+ format and name explicit, they are also added with the prefix ``format_`` and
+ ``builder_``, e.g. the epub builder defines the tags ``html``, ``epub``,
+ ``format_html`` and ``builder_epub``.
+
+ These standard tags are set *after* the configuration file is read, so they
+ are not available there.
+
+ .. versionadded:: 0.6
+ .. versionchanged:: 1.2
+ Added the name of the builder and the prefixes.
+
+
+Tables
+------
+
+Use :ref:`standard reStructuredText tables <rst-tables>`. They work fine in
+HTML output, however there are some gotchas when using tables in LaTeX: the
+column width is hard to determine correctly automatically. For this reason, the
+following directive exists:
+
+.. rst:directive:: .. tabularcolumns:: column spec
+
+ This directive gives a "column spec" for the next table occurring in the
+ source file. The spec is the second argument to the LaTeX ``tabulary``
+ package's environment (which Sphinx uses to translate tables). It can have
+ values like ::
+
+ |l|l|l|
+
+ which means three left-adjusted, nonbreaking columns. For columns with
+ longer text that should automatically be broken, use either the standard
+ ``p{width}`` construct, or tabulary's automatic specifiers:
+
+ +-----+------------------------------------------+
+ |``L``| flush left column with automatic width |
+ +-----+------------------------------------------+
+ |``R``| flush right column with automatic width |
+ +-----+------------------------------------------+
+ |``C``| centered column with automatic width |
+ +-----+------------------------------------------+
+ |``J``| justified column with automatic width |
+ +-----+------------------------------------------+
+
+ The automatic width is determined by rendering the content in the table, and
+ scaling them according to their share of the total width.
+
+ By default, Sphinx uses a table layout with ``L`` for every column.
+
+ .. versionadded:: 0.3
+
+.. warning::
+
+ Tables that contain list-like elements such as object descriptions,
+ blockquotes or any kind of lists cannot be set out of the box with
+ ``tabulary``. They are therefore set with the standard LaTeX ``tabular``
+ environment if you don't give a ``tabularcolumns`` directive. If you do, the
+ table will be set with ``tabulary``, but you must use the ``p{width}``
+ construct for the columns that contain these elements.
+
+ Literal blocks do not work with ``tabulary`` at all, so tables containing a
+ literal block are always set with ``tabular``. Also, the verbatim
+ environment used for literal blocks only works in ``p{width}`` columns, which
+ means that by default, Sphinx generates such column specs for such tables.
+ Use the :rst:dir:`tabularcolumns` directive to get finer control over such
+ tables.
+
+.. rubric:: Footnotes
+
+.. [#] For most builders name and format are the same. At the moment only
+ builders derived from the html builder distinguish between the builder
+ format and the builder name.
+
+ Note that the current builder tag is not available in ``conf.py``, it is
+ only available after the builder is intialized.
+
diff --git a/doc/markup/para.rst b/doc/markup/para.rst
new file mode 100644
index 0000000..b532bc6
--- /dev/null
+++ b/doc/markup/para.rst
@@ -0,0 +1,231 @@
+.. highlight:: rest
+
+Paragraph-level markup
+----------------------
+
+.. index:: note, warning
+ pair: changes; in version
+
+These directives create short paragraphs and can be used inside information
+units as well as normal text:
+
+.. rst:directive:: .. note::
+
+ An especially important bit of information about an API that a user should be
+ aware of when using whatever bit of API the note pertains to. The content of
+ the directive should be written in complete sentences and include all
+ appropriate punctuation.
+
+ Example::
+
+ .. note::
+
+ This function is not suitable for sending spam e-mails.
+
+.. rst:directive:: .. warning::
+
+ An important bit of information about an API that a user should be very aware
+ of when using whatever bit of API the warning pertains to. The content of
+ the directive should be written in complete sentences and include all
+ appropriate punctuation. This differs from :rst:dir:`note` in that it is
+ recommended over :rst:dir:`note` for information regarding security.
+
+.. rst:directive:: .. versionadded:: version
+
+ This directive documents the version of the project which added the described
+ feature to the library or C API. When this applies to an entire module, it
+ should be placed at the top of the module section before any prose.
+
+ The first argument must be given and is the version in question; you can add
+ a second argument consisting of a *brief* explanation of the change.
+
+ Example::
+
+ .. versionadded:: 2.5
+ The *spam* parameter.
+
+ Note that there must be no blank line between the directive head and the
+ explanation; this is to make these blocks visually continuous in the markup.
+
+.. rst:directive:: .. versionchanged:: version
+
+ Similar to :rst:dir:`versionadded`, but describes when and what changed in
+ the named feature in some way (new parameters, changed side effects, etc.).
+
+.. rst:directive:: .. deprecated:: version
+
+ Similar to :rst:dir:`versionchanged`, but describes when the feature was
+ deprecated. An explanation can also be given, for example to inform the
+ reader what should be used instead. Example::
+
+ .. deprecated:: 3.1
+ Use :func:`spam` instead.
+
+
+--------------
+
+.. rst:directive:: seealso
+
+ Many sections include a list of references to module documentation or
+ external documents. These lists are created using the :rst:dir:`seealso`
+ directive.
+
+ The :rst:dir:`seealso` directive is typically placed in a section just before any
+ sub-sections. For the HTML output, it is shown boxed off from the main flow
+ of the text.
+
+ The content of the :rst:dir:`seealso` directive should be a reST definition list.
+ Example::
+
+ .. seealso::
+
+ Module :py:mod:`zipfile`
+ Documentation of the :py:mod:`zipfile` standard module.
+
+ `GNU tar manual, Basic Tar Format <http://link>`_
+ Documentation for tar archive files, including GNU tar extensions.
+
+ There's also a "short form" allowed that looks like this::
+
+ .. seealso:: modules :py:mod:`zipfile`, :py:mod:`tarfile`
+
+ .. versionadded:: 0.5
+ The short form.
+
+.. rst:directive:: .. rubric:: title
+
+ This directive creates a paragraph heading that is not used to create a
+ table of contents node.
+
+ .. note::
+
+ If the *title* of the rubric is "Footnotes" (or the selected language's
+ equivalent), this rubric is ignored by the LaTeX writer, since it is
+ assumed to only contain footnote definitions and therefore would create an
+ empty heading.
+
+
+.. rst:directive:: centered
+
+ This directive creates a centered boldfaced line of text. Use it as
+ follows::
+
+ .. centered:: LICENSE AGREEMENT
+
+ .. deprecated:: 1.1
+ This presentation-only directive is a legacy from older versions. Use a
+ :rst:dir:`rst-class` directive instead and add an appropriate style.
+
+
+.. rst:directive:: hlist
+
+ This directive must contain a bullet list. It will transform it into a more
+ compact list by either distributing more than one item horizontally, or
+ reducing spacing between items, depending on the builder.
+
+ For builders that support the horizontal distribution, there is a ``columns``
+ option that specifies the number of columns; it defaults to 2. Example::
+
+ .. hlist::
+ :columns: 3
+
+ * A list of
+ * short items
+ * that should be
+ * displayed
+ * horizontally
+
+ .. versionadded:: 0.6
+
+
+Table-of-contents markup
+------------------------
+
+The :rst:dir:`toctree` directive, which generates tables of contents of
+subdocuments, is described in :ref:`toctree-directive`.
+
+For local tables of contents, use the standard reST :dudir:`contents directive
+<table-of-contents>`.
+
+
+Glossary
+--------
+
+.. rst:directive:: .. glossary::
+
+ This directive must contain a reST definition-list-like markup with terms and
+ definitions. The definitions will then be referencable with the
+ :rst:role:`term` role. Example::
+
+ .. glossary::
+
+ environment
+ A structure where information about all documents under the root is
+ saved, and used for cross-referencing. The environment is pickled
+ after the parsing stage, so that successive runs only need to read
+ and parse new and changed documents.
+
+ source directory
+ The directory which, including its subdirectories, contains all
+ source files for one Sphinx project.
+
+ In contrast to regular definition lists, *multiple* terms per entry are
+ allowed, and inline markup is allowed in terms. You can link to all of the
+ terms. For example::
+
+ .. glossary::
+
+ term 1
+ term 2
+ Definition of both terms.
+
+ (When the glossary is sorted, the first term determines the sort order.)
+
+ .. versionadded:: 0.6
+ You can now give the glossary directive a ``:sorted:`` flag that will
+ automatically sort the entries alphabetically.
+
+ .. versionchanged:: 1.1
+ Now supports multiple terms and inline markup in terms.
+
+
+Grammar production displays
+---------------------------
+
+Special markup is available for displaying the productions of a formal grammar.
+The markup is simple and does not attempt to model all aspects of BNF (or any
+derived forms), but provides enough to allow context-free grammars to be
+displayed in a way that causes uses of a symbol to be rendered as hyperlinks to
+the definition of the symbol. There is this directive:
+
+.. rst:directive:: .. productionlist:: [name]
+
+ This directive is used to enclose a group of productions. Each production is
+ given on a single line and consists of a name, separated by a colon from the
+ following definition. If the definition spans multiple lines, each
+ continuation line must begin with a colon placed at the same column as in the
+ first line.
+
+ The argument to :rst:dir:`productionlist` serves to distinguish different sets of
+ production lists that belong to different grammars.
+
+ Blank lines are not allowed within ``productionlist`` directive arguments.
+
+ The definition can contain token names which are marked as interpreted text
+ (e.g. ``sum ::= `integer` "+" `integer```) -- this generates cross-references
+ to the productions of these tokens. Outside of the production list, you can
+ reference to token productions using :rst:role:`token`.
+
+ Note that no further reST parsing is done in the production, so that you
+ don't have to escape ``*`` or ``|`` characters.
+
+The following is an example taken from the Python Reference Manual::
+
+ .. productionlist::
+ try_stmt: try1_stmt | try2_stmt
+ try1_stmt: "try" ":" `suite`
+ : ("except" [`expression` ["," `target`]] ":" `suite`)+
+ : ["else" ":" `suite`]
+ : ["finally" ":" `suite`]
+ try2_stmt: "try" ":" `suite`
+ : "finally" ":" `suite`
diff --git a/doc/markup/toctree.rst b/doc/markup/toctree.rst
new file mode 100644
index 0000000..1d5d667
--- /dev/null
+++ b/doc/markup/toctree.rst
@@ -0,0 +1,222 @@
+.. highlight:: rst
+.. _toctree-directive:
+
+The TOC tree
+============
+
+.. index:: pair: table of; contents
+
+Since reST does not have facilities to interconnect several documents, or split
+documents into multiple output files, Sphinx uses a custom directive to add
+relations between the single files the documentation is made of, as well as
+tables of contents. The ``toctree`` directive is the central element.
+
+.. note::
+
+ Simple "inclusion" of one file in another can be done with the
+ :dudir:`include` directive.
+
+.. rst:directive:: toctree
+
+ This directive inserts a "TOC tree" at the current location, using the
+ individual TOCs (including "sub-TOC trees") of the documents given in the
+ directive body. Relative document names (not beginning with a slash) are
+ relative to the document the directive occurs in, absolute names are relative
+ to the source directory. A numeric ``maxdepth`` option may be given to
+ indicate the depth of the tree; by default, all levels are included. [#]_
+
+ Consider this example (taken from the Python docs' library reference index)::
+
+ .. toctree::
+ :maxdepth: 2
+
+ intro
+ strings
+ datatypes
+ numeric
+ (many more documents listed here)
+
+ This accomplishes two things:
+
+ * Tables of contents from all those documents are inserted, with a maximum
+ depth of two, that means one nested heading. ``toctree`` directives in
+ those documents are also taken into account.
+ * Sphinx knows that the relative order of the documents ``intro``,
+ ``strings`` and so forth, and it knows that they are children of the shown
+ document, the library index. From this information it generates "next
+ chapter", "previous chapter" and "parent chapter" links.
+
+ **Entries**
+
+ Document titles in the :rst:dir:`toctree` will be automatically read from the
+ title of the referenced document. If that isn't what you want, you can
+ specify an explicit title and target using a similar syntax to reST
+ hyperlinks (and Sphinx's :ref:`cross-referencing syntax <xref-syntax>`). This
+ looks like::
+
+ .. toctree::
+
+ intro
+ All about strings <strings>
+ datatypes
+
+ The second line above will link to the ``strings`` document, but will use the
+ title "All about strings" instead of the title of the ``strings`` document.
+
+ You can also add external links, by giving an HTTP URL instead of a document
+ name.
+
+ **Section numbering**
+
+ If you want to have section numbers even in HTML output, give the
+ **toplevel** toctree a ``numbered`` option. For example::
+
+ .. toctree::
+ :numbered:
+
+ foo
+ bar
+
+ Numbering then starts at the heading of ``foo``. Sub-toctrees are
+ automatically numbered (don't give the ``numbered`` flag to those).
+
+ Numbering up to a specific depth is also possible, by giving the depth as a
+ numeric argument to ``numbered``.
+
+ **Additional options**
+
+ If you want only the titles of documents in the tree to show up, not other
+ headings of the same level, you can use the ``titlesonly`` option::
+
+ .. toctree::
+ :titlesonly:
+
+ foo
+ bar
+
+ You can use "globbing" in toctree directives, by giving the ``glob`` flag
+ option. All entries are then matched against the list of available
+ documents, and matches are inserted into the list alphabetically. Example::
+
+ .. toctree::
+ :glob:
+
+ intro*
+ recipe/*
+ *
+
+ This includes first all documents whose names start with ``intro``, then all
+ documents in the ``recipe`` folder, then all remaining documents (except the
+ one containing the directive, of course.) [#]_
+
+ The special entry name ``self`` stands for the document containing the
+ toctree directive. This is useful if you want to generate a "sitemap" from
+ the toctree.
+
+ You can also give a "hidden" option to the directive, like this::
+
+ .. toctree::
+ :hidden:
+
+ doc_1
+ doc_2
+
+ This will still notify Sphinx of the document hierarchy, but not insert links
+ into the document at the location of the directive -- this makes sense if you
+ intend to insert these links yourself, in a different style, or in the HTML
+ sidebar.
+
+ In cases where you want to have only one top-level toctree and hide all other
+ lower level toctrees you can add the "includehidden" option to the top-level
+ toctree entry::
+
+ .. toctree::
+ :includehidden:
+
+ doc_1
+ doc_2
+
+ All other toctree entries can then be eliminated by the "hidden" option.
+
+ In the end, all documents in the :term:`source directory` (or subdirectories)
+ must occur in some ``toctree`` directive; Sphinx will emit a warning if it
+ finds a file that is not included, because that means that this file will not
+ be reachable through standard navigation.
+
+ Use :confval:`exclude_patterns` to explicitly exclude documents or
+ directories from building completely. Use :ref:`the "orphan" metadata
+ <metadata>` to let a document be built, but notify Sphinx that it is not
+ reachable via a toctree.
+
+ The "master document" (selected by :confval:`master_doc`) is the "root" of
+ the TOC tree hierarchy. It can be used as the documentation's main page, or
+ as a "full table of contents" if you don't give a ``maxdepth`` option.
+
+ .. versionchanged:: 0.3
+ Added "globbing" option.
+
+ .. versionchanged:: 0.6
+ Added "numbered" and "hidden" options as well as external links and
+ support for "self" references.
+
+ .. versionchanged:: 1.0
+ Added "titlesonly" option.
+
+ .. versionchanged:: 1.1
+ Added numeric argument to "numbered".
+
+ .. versionchanged:: 1.2
+ Added "includehidden" option.
+
+Special names
+-------------
+
+Sphinx reserves some document names for its own use; you should not try to
+create documents with these names -- it will cause problems.
+
+The special document names (and pages generated for them) are:
+
+* ``genindex``, ``modindex``, ``search``
+
+ These are used for the general index, the Python module index, and the search
+ page, respectively.
+
+ The general index is populated with entries from modules, all index-generating
+ :ref:`object descriptions <basic-domain-markup>`, and from :rst:dir:`index`
+ directives.
+
+ The Python module index contains one entry per :rst:dir:`py:module` directive.
+
+ The search page contains a form that uses the generated JSON search index and
+ JavaScript to full-text search the generated documents for search words; it
+ should work on every major browser that supports modern JavaScript.
+
+* every name beginning with ``_``
+
+ Though only few such names are currently used by Sphinx, you should not create
+ documents or document-containing directories with such names. (Using ``_`` as
+ a prefix for a custom template directory is fine.)
+
+.. warning::
+
+ Be careful with unusual characters in filenames. Some formats may interpret
+ these characters in unexpected ways:
+
+ * Do not user the colon ``:`` for HTML based formats. Links to other parts
+ may not work.
+
+ * Do not use the plus ``+`` for the ePub format. Some resources may not be
+ found.
+
+.. rubric:: Footnotes
+
+.. [#] The ``maxdepth`` option does not apply to the LaTeX writer, where the
+ whole table of contents will always be presented at the begin of the
+ document, and its depth is controlled by the ``tocdepth`` counter, which
+ you can reset in your :confval:`latex_preamble` config value using
+ e.g. ``\setcounter{tocdepth}{2}``.
+
+.. [#] A note on available globbing syntax: you can use the standard shell
+ constructs ``*``, ``?``, ``[...]`` and ``[!...]`` with the feature that
+ these all don't match slashes. A double star ``**`` can be used to match
+ any sequence of characters *including* slashes.
diff --git a/doc/more.png b/doc/more.png
new file mode 100644
index 0000000..3eb7b05
Binary files /dev/null and b/doc/more.png differ
diff --git a/doc/pythonorg.png b/doc/pythonorg.png
new file mode 100644
index 0000000..83b54df
Binary files /dev/null and b/doc/pythonorg.png differ
diff --git a/doc/rest.rst b/doc/rest.rst
new file mode 100644
index 0000000..b5efbf9
--- /dev/null
+++ b/doc/rest.rst
@@ -0,0 +1,489 @@
+.. highlightlang:: rest
+
+.. _rst-primer:
+
+reStructuredText Primer
+=======================
+
+This section is a brief introduction to reStructuredText (reST) concepts and
+syntax, intended to provide authors with enough information to author documents
+productively. Since reST was designed to be a simple, unobtrusive markup
+language, this will not take too long.
+
+.. seealso::
+
+ The authoritative `reStructuredText User Documentation
+ <http://docutils.sourceforge.net/rst.html>`_. The "ref" links in this
+ document link to the description of the individual constructs in the reST
+ reference.
+
+
+Paragraphs
+----------
+
+The paragraph (:duref:`ref <paragraphs>`) is the most basic block in a reST
+document. Paragraphs are simply chunks of text separated by one or more blank
+lines. As in Python, indentation is significant in reST, so all lines of the
+same paragraph must be left-aligned to the same level of indentation.
+
+
+.. _inlinemarkup:
+
+Inline markup
+-------------
+
+The standard reST inline markup is quite simple: use
+
+* one asterisk: ``*text*`` for emphasis (italics),
+* two asterisks: ``**text**`` for strong emphasis (boldface), and
+* backquotes: ````text```` for code samples.
+
+If asterisks or backquotes appear in running text and could be confused with
+inline markup delimiters, they have to be escaped with a backslash.
+
+Be aware of some restrictions of this markup:
+
+* it may not be nested,
+* content may not start or end with whitespace: ``* text*`` is wrong,
+* it must be separated from surrounding text by non-word characters. Use a
+ backslash escaped space to work around that: ``thisis\ *one*\ word``.
+
+These restrictions may be lifted in future versions of the docutils.
+
+reST also allows for custom "interpreted text roles", which signify that the
+enclosed text should be interpreted in a specific way. Sphinx uses this to
+provide semantic markup and cross-referencing of identifiers, as described in
+the appropriate section. The general syntax is ``:rolename:`content```.
+
+Standard reST provides the following roles:
+
+* :durole:`emphasis` -- alternate spelling for ``*emphasis*``
+* :durole:`strong` -- alternate spelling for ``**strong**``
+* :durole:`literal` -- alternate spelling for ````literal````
+* :durole:`subscript` -- subscript text
+* :durole:`superscript` -- superscript text
+* :durole:`title-reference` -- for titles of books, periodicals, and other
+ materials
+
+See :ref:`inline-markup` for roles added by Sphinx.
+
+
+Lists and Quote-like blocks
+---------------------------
+
+List markup (:duref:`ref <bullet-lists>`) is natural: just place an asterisk at
+the start of a paragraph and indent properly. The same goes for numbered lists;
+they can also be autonumbered using a ``#`` sign::
+
+ * This is a bulleted list.
+ * It has two items, the second
+ item uses two lines.
+
+ 1. This is a numbered list.
+ 2. It has two items too.
+
+ #. This is a numbered list.
+ #. It has two items too.
+
+
+Nested lists are possible, but be aware that they must be separated from the
+parent list items by blank lines::
+
+ * this is
+ * a list
+
+ * with a nested list
+ * and some subitems
+
+ * and here the parent list continues
+
+Definition lists (:duref:`ref <definition-lists>`) are created as follows::
+
+ term (up to a line of text)
+ Definition of the term, which must be indented
+
+ and can even consist of multiple paragraphs
+
+ next term
+ Description.
+
+Note that the term cannot have more than one line of text.
+
+Quoted paragraphs (:duref:`ref <block-quotes>`) are created by just indenting
+them more than the surrounding paragraphs.
+
+Line blocks (:duref:`ref <line-blocks>`) are a way of preserving line breaks::
+
+ | These lines are
+ | broken exactly like in
+ | the source file.
+
+There are also several more special blocks available:
+
+* field lists (:duref:`ref <field-lists>`)
+* option lists (:duref:`ref <option-lists>`)
+* quoted literal blocks (:duref:`ref <quoted-literal-blocks>`)
+* doctest blocks (:duref:`ref <doctest-blocks>`)
+
+
+Source Code
+-----------
+
+Literal code blocks (:duref:`ref <literal-blocks>`) are introduced by ending a
+paragraph with the special marker ``::``. The literal block must be indented
+(and, like all paragraphs, separated from the surrounding ones by blank lines)::
+
+ This is a normal text paragraph. The next paragraph is a code sample::
+
+ It is not processed in any way, except
+ that the indentation is removed.
+
+ It can span multiple lines.
+
+ This is a normal text paragraph again.
+
+The handling of the ``::`` marker is smart:
+
+* If it occurs as a paragraph of its own, that paragraph is completely left
+ out of the document.
+* If it is preceded by whitespace, the marker is removed.
+* If it is preceded by non-whitespace, the marker is replaced by a single
+ colon.
+
+That way, the second sentence in the above example's first paragraph would be
+rendered as "The next paragraph is a code sample:".
+
+
+.. _rst-tables:
+
+Tables
+------
+
+Two forms of tables are supported. For *grid tables* (:duref:`ref
+<grid-tables>`), you have to "paint" the cell grid yourself. They look like
+this::
+
+ +------------------------+------------+----------+----------+
+ | Header row, column 1 | Header 2 | Header 3 | Header 4 |
+ | (header rows optional) | | | |
+ +========================+============+==========+==========+
+ | body row 1, column 1 | column 2 | column 3 | column 4 |
+ +------------------------+------------+----------+----------+
+ | body row 2 | ... | ... | |
+ +------------------------+------------+----------+----------+
+
+*Simple tables* (:duref:`ref <simple-tables>`) are easier to write, but
+limited: they must contain more than one row, and the first column cannot
+contain multiple lines. They look like this::
+
+ ===== ===== =======
+ A B A and B
+ ===== ===== =======
+ False False False
+ True False False
+ False True False
+ True True True
+ ===== ===== =======
+
+
+Hyperlinks
+----------
+
+External links
+^^^^^^^^^^^^^^
+
+Use ```Link text <http://example.com/>`_`` for inline web links. If the link
+text should be the web address, you don't need special markup at all, the parser
+finds links and mail addresses in ordinary text.
+
+You can also separate the link and the target definition (:duref:`ref
+<hyperlink-targets>`), like this::
+
+ This is a paragraph that contains `a link`_.
+
+ .. _a link: http://example.com/
+
+
+Internal links
+^^^^^^^^^^^^^^
+
+Internal linking is done via a special reST role provided by Sphinx, see the
+section on specific markup, :ref:`ref-role`.
+
+
+Sections
+--------
+
+Section headers (:duref:`ref <sections>`) are created by underlining (and
+optionally overlining) the section title with a punctuation character, at least
+as long as the text::
+
+ =================
+ This is a heading
+ =================
+
+Normally, there are no heading levels assigned to certain characters as the
+structure is determined from the succession of headings. However, for the
+Python documentation, this convention is used which you may follow:
+
+* ``#`` with overline, for parts
+* ``*`` with overline, for chapters
+* ``=``, for sections
+* ``-``, for subsections
+* ``^``, for subsubsections
+* ``"``, for paragraphs
+
+Of course, you are free to use your own marker characters (see the reST
+documentation), and use a deeper nesting level, but keep in mind that most
+target formats (HTML, LaTeX) have a limited supported nesting depth.
+
+
+Explicit Markup
+---------------
+
+"Explicit markup" (:duref:`ref <explicit-markup-blocks>`) is used in reST for
+most constructs that need special handling, such as footnotes,
+specially-highlighted paragraphs, comments, and generic directives.
+
+An explicit markup block begins with a line starting with ``..`` followed by
+whitespace and is terminated by the next paragraph at the same level of
+indentation. (There needs to be a blank line between explicit markup and normal
+paragraphs. This may all sound a bit complicated, but it is intuitive enough
+when you write it.)
+
+
+.. _directives:
+
+Directives
+----------
+
+A directive (:duref:`ref <directives>`) is a generic block of explicit markup.
+Besides roles, it is one of the extension mechanisms of reST, and Sphinx makes
+heavy use of it.
+
+Docutils supports the following directives:
+
+* Admonitions: :dudir:`attention`, :dudir:`caution`, :dudir:`danger`,
+ :dudir:`error`, :dudir:`hint`, :dudir:`important`, :dudir:`note`,
+ :dudir:`tip`, :dudir:`warning` and the generic
+ :dudir:`admonition <admonitions>`. (Most themes style only "note" and
+ "warning" specially.)
+
+* Images:
+
+ - :dudir:`image` (see also Images_ below)
+ - :dudir:`figure` (an image with caption and optional legend)
+
+* Additional body elements:
+
+ - :dudir:`contents <table-of-contents>` (a local, i.e. for the current file
+ only, table of contents)
+ - :dudir:`container` (a container with a custom class, useful to generate an
+ outer ``<div>`` in HTML)
+ - :dudir:`rubric` (a heading without relation to the document sectioning)
+ - :dudir:`topic`, :dudir:`sidebar` (special highlighted body elements)
+ - :dudir:`parsed-literal` (literal block that supports inline markup)
+ - :dudir:`epigraph` (a block quote with optional attribution line)
+ - :dudir:`highlights`, :dudir:`pull-quote` (block quotes with their own
+ class attribute)
+ - :dudir:`compound <compound-paragraph>` (a compound paragraph)
+
+* Special tables:
+
+ - :dudir:`table` (a table with title)
+ - :dudir:`csv-table` (a table generated from comma-separated values)
+ - :dudir:`list-table` (a table generated from a list of lists)
+
+* Special directives:
+
+ - :dudir:`raw <raw-data-pass-through>` (include raw target-format markup)
+ - :dudir:`include` (include reStructuredText from another file)
+ -- in Sphinx, when given an absolute include file path, this directive takes
+ it as relative to the source directory
+ - :dudir:`class` (assign a class attribute to the next element) [1]_
+
+* HTML specifics:
+
+ - :dudir:`meta` (generation of HTML ``<meta>`` tags)
+ - :dudir:`title <metadata-document-title>` (override document title)
+
+* Influencing markup:
+
+ - :dudir:`default-role` (set a new default role)
+ - :dudir:`role` (create a new role)
+
+ Since these are only per-file, better use Sphinx' facilities for setting the
+ :confval:`default_role`.
+
+Do *not* use the directives :dudir:`sectnum`, :dudir:`header` and
+:dudir:`footer`.
+
+Directives added by Sphinx are described in :ref:`sphinxmarkup`.
+
+Basically, a directive consists of a name, arguments, options and content. (Keep
+this terminology in mind, it is used in the next chapter describing custom
+directives.) Looking at this example, ::
+
+ .. function:: foo(x)
+ foo(y, z)
+ :module: some.module.name
+
+ Return a line of text input from the user.
+
+``function`` is the directive name. It is given two arguments here, the
+remainder of the first line and the second line, as well as one option
+``module`` (as you can see, options are given in the lines immediately following
+the arguments and indicated by the colons). Options must be indented to the
+same level as the directive content.
+
+The directive content follows after a blank line and is indented relative to the
+directive start.
+
+
+Images
+------
+
+reST supports an image directive (:dudir:`ref <image>`), used like so::
+
+ .. image:: gnu.png
+ (options)
+
+When used within Sphinx, the file name given (here ``gnu.png``) must either be
+relative to the source file, or absolute which means that they are relative to
+the top source directory. For example, the file ``sketch/spam.rst`` could refer
+to the image ``images/spam.png`` as ``../images/spam.png`` or
+``/images/spam.png``.
+
+Sphinx will automatically copy image files over to a subdirectory of the output
+directory on building (e.g. the ``_static`` directory for HTML output.)
+
+Interpretation of image size options (``width`` and ``height``) is as follows:
+if the size has no unit or the unit is pixels, the given size will only be
+respected for output channels that support pixels (i.e. not in LaTeX output).
+Other units (like ``pt`` for points) will be used for HTML and LaTeX output.
+
+Sphinx extends the standard docutils behavior by allowing an asterisk for the
+extension::
+
+ .. image:: gnu.*
+
+Sphinx then searches for all images matching the provided pattern and determines
+their type. Each builder then chooses the best image out of these candidates.
+For instance, if the file name ``gnu.*`` was given and two files :file:`gnu.pdf`
+and :file:`gnu.png` existed in the source tree, the LaTeX builder would choose
+the former, while the HTML builder would prefer the latter.
+Supported image types and choosing priority are defined at :ref:`builders`.
+
+Note that image file names should not contain spaces.
+
+.. versionchanged:: 0.4
+ Added the support for file names ending in an asterisk.
+
+.. versionchanged:: 0.6
+ Image paths can now be absolute.
+
+
+Footnotes
+---------
+
+For footnotes (:duref:`ref <footnotes>`), use ``[#name]_`` to mark the footnote
+location, and add the footnote body at the bottom of the document after a
+"Footnotes" rubric heading, like so::
+
+ Lorem ipsum [#f1]_ dolor sit amet ... [#f2]_
+
+ .. rubric:: Footnotes
+
+ .. [#f1] Text of the first footnote.
+ .. [#f2] Text of the second footnote.
+
+You can also explicitly number the footnotes (``[1]_``) or use auto-numbered
+footnotes without names (``[#]_``).
+
+
+Citations
+---------
+
+Standard reST citations (:duref:`ref <citations>`) are supported, with the
+additional feature that they are "global", i.e. all citations can be referenced
+from all files. Use them like so::
+
+ Lorem ipsum [Ref]_ dolor sit amet.
+
+ .. [Ref] Book or article reference, URL or whatever.
+
+Citation usage is similar to footnote usage, but with a label that is not
+numeric or begins with ``#``.
+
+
+Substitutions
+-------------
+
+reST supports "substitutions" (:duref:`ref <substitution-definitions>`), which
+are pieces of text and/or markup referred to in the text by ``|name|``. They
+are defined like footnotes with explicit markup blocks, like this::
+
+ .. |name| replace:: replacement *text*
+
+or this::
+
+ .. |caution| image:: warning.png
+ :alt: Warning!
+
+See the :duref:`reST reference for substitutions <substitution-definitions>`
+for details.
+
+If you want to use some substitutions for all documents, put them into
+:confval:`rst_prolog` or put them into a separate file and include it into all
+documents you want to use them in, using the :rst:dir:`include` directive. (Be
+sure to give the include file a file name extension differing from that of other
+source files, to avoid Sphinx finding it as a standalone document.)
+
+Sphinx defines some default substitutions, see :ref:`default-substitutions`.
+
+
+Comments
+--------
+
+Every explicit markup block which isn't a valid markup construct (like the
+footnotes above) is regarded as a comment (:duref:`ref <comments>`). For
+example::
+
+ .. This is a comment.
+
+You can indent text after a comment start to form multiline comments::
+
+ ..
+ This whole indented block
+ is a comment.
+
+ Still in the comment.
+
+
+Source encoding
+---------------
+
+Since the easiest way to include special characters like em dashes or copyright
+signs in reST is to directly write them as Unicode characters, one has to
+specify an encoding. Sphinx assumes source files to be encoded in UTF-8 by
+default; you can change this with the :confval:`source_encoding` config value.
+
+
+Gotchas
+-------
+
+There are some problems one commonly runs into while authoring reST documents:
+
+* **Separation of inline markup:** As said above, inline markup spans must be
+ separated from the surrounding text by non-word characters, you have to use a
+ backslash-escaped space to get around that. See
+ :duref:`the reference <substitution-definitions>` for the details.
+
+* **No nested inline markup:** Something like ``*see :func:`foo`*`` is not
+ possible.
+
+
+.. rubric:: Footnotes
+
+.. [1] When the default domain contains a :rst:dir:`class` directive, this directive
+ will be shadowed. Therefore, Sphinx re-exports it as :rst:dir:`rst-class`.
diff --git a/doc/templating.rst b/doc/templating.rst
new file mode 100644
index 0000000..b9561b6
--- /dev/null
+++ b/doc/templating.rst
@@ -0,0 +1,397 @@
+.. highlight:: html+jinja
+
+.. _templating:
+
+Templating
+==========
+
+Sphinx uses the `Jinja <http://jinja.pocoo.org>`_ templating engine for its HTML
+templates. Jinja is a text-based engine, and inspired by Django templates, so
+anyone having used Django will already be familiar with it. It also has
+excellent documentation for those who need to make themselves familiar with it.
+
+
+Do I need to use Sphinx' templates to produce HTML?
+---------------------------------------------------
+
+No. You have several other options:
+
+* You can write a :class:`~sphinx.application.TemplateBridge` subclass that
+ calls your template engine of choice, and set the :confval:`template_bridge`
+ configuration value accordingly.
+
+* You can :ref:`write a custom builder <writing-builders>` that derives from
+ :class:`~sphinx.builders.html.StandaloneHTMLBuilder` and calls your template
+ engine of choice.
+
+* You can use the :class:`~sphinx.builders.html.PickleHTMLBuilder` that produces
+ pickle files with the page contents, and postprocess them using a custom tool,
+ or use them in your Web application.
+
+
+Jinja/Sphinx Templating Primer
+------------------------------
+
+The default templating language in Sphinx is Jinja. It's Django/Smarty inspired
+and easy to understand. The most important concept in Jinja is :dfn:`template
+inheritance`, which means that you can overwrite only specific blocks within a
+template, customizing it while also keeping the changes at a minimum.
+
+To customize the output of your documentation you can override all the templates
+(both the layout templates and the child templates) by adding files with the
+same name as the original filename into the template directory of the structure
+the Sphinx quickstart generated for you.
+
+Sphinx will look for templates in the folders of :confval:`templates_path`
+first, and if it can't find the template it's looking for there, it falls back
+to the selected theme's templates.
+
+A template contains **variables**, which are replaced with values when the
+template is evaluated, **tags**, which control the logic of the template and
+**blocks** which are used for template inheritance.
+
+Sphinx' *basic* theme provides base templates with a couple of blocks it will
+fill with data. These are located in the :file:`themes/basic` subdirectory of
+the Sphinx installation directory, and used by all builtin Sphinx themes.
+Templates with the same name in the :confval:`templates_path` override templates
+supplied by the selected theme.
+
+For example, to add a new link to the template area containing related links all
+you have to do is to add a new template called ``layout.html`` with the
+following contents::
+
+ {% extends "!layout.html" %}
+ {% block rootrellink %}
+ <li><a href="http://project.invalid/">Project Homepage</a> »</li>
+ {{ super() }}
+ {% endblock %}
+
+By prefixing the name of the overridden template with an exclamation mark,
+Sphinx will load the layout template from the underlying HTML theme.
+
+**Important**: If you override a block, call ``{{ super() }}`` somewhere to
+render the block's content in the extended template -- unless you don't want
+that content to show up.
+
+
+Working with the builtin templates
+----------------------------------
+
+The builtin **basic** theme supplies the templates that all builtin Sphinx
+themes are based on. It has the following elements you can override or use:
+
+Blocks
+~~~~~~
+
+The following blocks exist in the ``layout.html`` template:
+
+`doctype`
+ The doctype of the output format. By default this is XHTML 1.0 Transitional
+ as this is the closest to what Sphinx and Docutils generate and it's a good
+ idea not to change it unless you want to switch to HTML 5 or a different but
+ compatible XHTML doctype.
+
+`linktags`
+ This block adds a couple of ``<link>`` tags to the head section of the
+ template.
+
+`extrahead`
+ This block is empty by default and can be used to add extra contents into
+ the ``<head>`` tag of the generated HTML file. This is the right place to
+ add references to JavaScript or extra CSS files.
+
+`relbar1` / `relbar2`
+ This block contains the *relation bar*, the list of related links (the
+ parent documents on the left, and the links to index, modules etc. on the
+ right). `relbar1` appears before the document, `relbar2` after the
+ document. By default, both blocks are filled; to show the relbar only
+ before the document, you would override `relbar2` like this::
+
+ {% block relbar2 %}{% endblock %}
+
+`rootrellink` / `relbaritems`
+ Inside the relbar there are three sections: The `rootrellink`, the links
+ from the documentation and the custom `relbaritems`. The `rootrellink` is a
+ block that by default contains a list item pointing to the master document
+ by default, the `relbaritems` is an empty block. If you override them to
+ add extra links into the bar make sure that they are list items and end with
+ the :data:`reldelim1`.
+
+`document`
+ The contents of the document itself. It contains the block "body" where the
+ individual content is put by subtemplates like ``page.html``.
+
+`sidebar1` / `sidebar2`
+ A possible location for a sidebar. `sidebar1` appears before the document
+ and is empty by default, `sidebar2` after the document and contains the
+ default sidebar. If you want to swap the sidebar location override this and
+ call the `sidebar` helper:
+
+ .. sourcecode:: html+jinja
+
+ {% block sidebar1 %}{{ sidebar() }}{% endblock %}
+ {% block sidebar2 %}{% endblock %}
+
+ (The `sidebar2` location for the sidebar is needed by the ``sphinxdoc.css``
+ stylesheet, for example.)
+
+`sidebarlogo`
+ The logo location within the sidebar. Override this if you want to place
+ some content at the top of the sidebar.
+
+`footer`
+ The block for the footer div. If you want a custom footer or markup before
+ or after it, override this one.
+
+The following four blocks are *only* used for pages that do not have assigned a
+list of custom sidebars in the :confval:`html_sidebars` config value. Their use
+is deprecated in favor of separate sidebar templates, which can be included via
+:confval:`html_sidebars`.
+
+`sidebartoc`
+ The table of contents within the sidebar.
+
+ .. deprecated:: 1.0
+
+`sidebarrel`
+ The relation links (previous, next document) within the sidebar.
+
+ .. deprecated:: 1.0
+
+`sidebarsourcelink`
+ The "Show source" link within the sidebar (normally only shown if this is
+ enabled by :confval:`html_show_sourcelink`).
+
+ .. deprecated:: 1.0
+
+`sidebarsearch`
+ The search box within the sidebar. Override this if you want to place some
+ content at the bottom of the sidebar.
+
+ .. deprecated:: 1.0
+
+
+Configuration Variables
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Inside templates you can set a couple of variables used by the layout template
+using the ``{% set %}`` tag:
+
+.. data:: reldelim1
+
+ The delimiter for the items on the left side of the related bar. This
+ defaults to ``' »'`` Each item in the related bar ends with the value
+ of this variable.
+
+.. data:: reldelim2
+
+ The delimiter for the items on the right side of the related bar. This
+ defaults to ``' |'``. Each item except of the last one in the related bar
+ ends with the value of this variable.
+
+Overriding works like this::
+
+ {% extends "!layout.html" %}
+ {% set reldelim1 = ' >' %}
+
+.. data:: script_files
+
+ Add additional script files here, like this::
+
+ {% set script_files = script_files + ["_static/myscript.js"] %}
+
+.. data:: css_files
+
+ Similar to :data:`script_files`, for CSS files.
+
+
+Helper Functions
+~~~~~~~~~~~~~~~~
+
+Sphinx provides various Jinja functions as helpers in the template. You can use
+them to generate links or output multiply used elements.
+
+.. function:: pathto(document)
+
+ Return the path to a Sphinx document as a URL. Use this to refer to built
+ documents.
+
+.. function:: pathto(file, 1)
+
+ Return the path to a *file* which is a filename relative to the root of the
+ generated output. Use this to refer to static files.
+
+.. function:: hasdoc(document)
+
+ Check if a document with the name *document* exists.
+
+.. function:: sidebar()
+
+ Return the rendered sidebar.
+
+.. function:: relbar()
+
+ Return the rendered relation bar.
+
+
+Global Variables
+~~~~~~~~~~~~~~~~
+
+These global variables are available in every template and are safe to use.
+There are more, but most of them are an implementation detail and might change
+in the future.
+
+.. data:: builder
+
+ The name of the builder (e.g. ``html`` or ``htmlhelp``).
+
+.. data:: copyright
+
+ The value of :confval:`copyright`.
+
+.. data:: docstitle
+
+ The title of the documentation (the value of :confval:`html_title`), except
+ when the "single-file" builder is used, when it is set to ``None``.
+
+.. data:: embedded
+
+ True if the built HTML is meant to be embedded in some viewing application
+ that handles navigation, not the web browser, such as for HTML help or Qt
+ help formats. In this case, the sidebar is not included.
+
+.. data:: favicon
+
+ The path to the HTML favicon in the static path, or ``''``.
+
+.. data:: file_suffix
+
+ The value of the builder's :attr:`~.SerializingHTMLBuilder.out_suffix`
+ attribute, i.e. the file name extension that the output files will get. For
+ a standard HTML builder, this is usually ``.html``.
+
+.. data:: has_source
+
+ True if the reST document sources are copied (if :confval:`html_copy_source`
+ is true).
+
+.. data:: last_updated
+
+ The build date.
+
+.. data:: logo
+
+ The path to the HTML logo image in the static path, or ``''``.
+
+.. data:: master_doc
+
+ The value of :confval:`master_doc`, for usage with :func:`pathto`.
+
+.. data:: next
+
+ The next document for the navigation. This variable is either false or has
+ two attributes `link` and `title`. The title contains HTML markup. For
+ example, to generate a link to the next page, you can use this snippet::
+
+ {% if next %}
+ <a href="{{ next.link|e }}">{{ next.title }}</a>
+ {% endif %}
+
+.. data:: pagename
+
+ The "page name" of the current file, i.e. either the document name if the
+ file is generated from a reST source, or the equivalent hierarchical name
+ relative to the output directory (``[directory/]filename_without_extension``).
+
+.. data:: parents
+
+ A list of parent documents for navigation, structured like the :data:`next`
+ item.
+
+.. data:: prev
+
+ Like :data:`next`, but for the previous page.
+
+.. data:: project
+
+ The value of :confval:`project`.
+
+.. data:: release
+
+ The value of :confval:`release`.
+
+.. data:: rellinks
+
+ A list of links to put at the left side of the relbar, next to "next" and
+ "prev". This usually contains links to the general index and other indices,
+ such as the Python module index. If you add something yourself, it must be a
+ tuple ``(pagename, link title, accesskey, link text)``.
+
+.. data:: shorttitle
+
+ The value of :confval:`html_short_title`.
+
+.. data:: show_source
+
+ True if :confval:`html_show_sourcelink` is true.
+
+.. data:: sphinx_version
+
+ The version of Sphinx used to build.
+
+.. data:: style
+
+ The name of the main stylesheet, as given by the theme or
+ :confval:`html_style`.
+
+.. data:: title
+
+ The title of the current document, as used in the ``<title>`` tag.
+
+.. data:: use_opensearch
+
+ The value of :confval:`html_use_opensearch`.
+
+.. data:: version
+
+ The value of :confval:`version`.
+
+
+In addition to these values, there are also all **theme options** available
+(prefixed by ``theme_``), as well as the values given by the user in
+:confval:`html_context`.
+
+In documents that are created from source files (as opposed to
+automatically-generated files like the module index, or documents that already
+are in HTML form), these variables are also available:
+
+.. data:: meta
+
+ Document metadata (a dictionary), see :ref:`metadata`.
+
+.. data:: sourcename
+
+ The name of the copied source file for the current document. This is only
+ nonempty if the :confval:`html_copy_source` value is true.
+
+.. data:: toc
+
+ The local table of contents for the current page, rendered as HTML bullet
+ lists.
+
+.. data:: toctree
+
+ A callable yielding the global TOC tree containing the current page, rendered
+ as HTML bullet lists. Optional keyword arguments:
+
+ * ``collapse`` (true by default): if true, all TOC entries that are not
+ ancestors of the current page are collapsed
+
+ * ``maxdepth`` (defaults to the max depth selected in the toctree directive):
+ the maximum depth of the tree; set it to ``-1`` to allow unlimited depth
+
+ * ``titles_only`` (false by default): if true, put only toplevel document
+ titles in the tree
+
+ * ``includehidden`` (false by default): if true, the TOC tree will also
+ contain hidden entries.
diff --git a/doc/themes/agogo.png b/doc/themes/agogo.png
new file mode 100644
index 0000000..d29aa45
Binary files /dev/null and b/doc/themes/agogo.png differ
diff --git a/doc/themes/default.png b/doc/themes/default.png
new file mode 100644
index 0000000..93d8526
Binary files /dev/null and b/doc/themes/default.png differ
diff --git a/doc/themes/fullsize/agogo.png b/doc/themes/fullsize/agogo.png
new file mode 100644
index 0000000..93fadfc
Binary files /dev/null and b/doc/themes/fullsize/agogo.png differ
diff --git a/doc/themes/fullsize/default.png b/doc/themes/fullsize/default.png
new file mode 100644
index 0000000..b6af8bc
Binary files /dev/null and b/doc/themes/fullsize/default.png differ
diff --git a/doc/themes/fullsize/haiku.png b/doc/themes/fullsize/haiku.png
new file mode 100644
index 0000000..1590da5
Binary files /dev/null and b/doc/themes/fullsize/haiku.png differ
diff --git a/doc/themes/fullsize/nature.png b/doc/themes/fullsize/nature.png
new file mode 100644
index 0000000..d42957e
Binary files /dev/null and b/doc/themes/fullsize/nature.png differ
diff --git a/doc/themes/fullsize/pyramid.png b/doc/themes/fullsize/pyramid.png
new file mode 100644
index 0000000..429a8b7
Binary files /dev/null and b/doc/themes/fullsize/pyramid.png differ
diff --git a/doc/themes/fullsize/scrolls.png b/doc/themes/fullsize/scrolls.png
new file mode 100644
index 0000000..7d46f7e
Binary files /dev/null and b/doc/themes/fullsize/scrolls.png differ
diff --git a/doc/themes/fullsize/sphinxdoc.png b/doc/themes/fullsize/sphinxdoc.png
new file mode 100644
index 0000000..722fb90
Binary files /dev/null and b/doc/themes/fullsize/sphinxdoc.png differ
diff --git a/doc/themes/fullsize/traditional.png b/doc/themes/fullsize/traditional.png
new file mode 100644
index 0000000..103fd3c
Binary files /dev/null and b/doc/themes/fullsize/traditional.png differ
diff --git a/doc/themes/haiku.png b/doc/themes/haiku.png
new file mode 100644
index 0000000..a8ae855
Binary files /dev/null and b/doc/themes/haiku.png differ
diff --git a/doc/themes/nature.png b/doc/themes/nature.png
new file mode 100644
index 0000000..3d4f587
Binary files /dev/null and b/doc/themes/nature.png differ
diff --git a/doc/themes/pyramid.png b/doc/themes/pyramid.png
new file mode 100644
index 0000000..b16095c
Binary files /dev/null and b/doc/themes/pyramid.png differ
diff --git a/doc/themes/scrolls.png b/doc/themes/scrolls.png
new file mode 100644
index 0000000..8073c10
Binary files /dev/null and b/doc/themes/scrolls.png differ
diff --git a/doc/themes/sphinxdoc.png b/doc/themes/sphinxdoc.png
new file mode 100644
index 0000000..f4b59ec
Binary files /dev/null and b/doc/themes/sphinxdoc.png differ
diff --git a/doc/themes/traditional.png b/doc/themes/traditional.png
new file mode 100644
index 0000000..4ad2b5c
Binary files /dev/null and b/doc/themes/traditional.png differ
diff --git a/doc/theming.rst b/doc/theming.rst
new file mode 100644
index 0000000..73ec9f2
--- /dev/null
+++ b/doc/theming.rst
@@ -0,0 +1,321 @@
+.. highlightlang:: python
+
+HTML theming support
+====================
+
+.. versionadded:: 0.6
+
+Sphinx supports changing the appearance of its HTML output via *themes*. A
+theme is a collection of HTML templates, stylesheet(s) and other static files.
+Additionally, it has a configuration file which specifies from which theme to
+inherit, which highlighting style to use, and what options exist for customizing
+the theme's look and feel.
+
+Themes are meant to be project-unaware, so they can be used for different
+projects without change.
+
+
+Using a theme
+-------------
+
+Using an existing theme is easy. If the theme is builtin to Sphinx, you only
+need to set the :confval:`html_theme` config value. With the
+:confval:`html_theme_options` config value you can set theme-specific options
+that change the look and feel. For example, you could have the following in
+your :file:`conf.py`::
+
+ html_theme = "default"
+ html_theme_options = {
+ "rightsidebar": "true",
+ "relbarbgcolor": "black"
+ }
+
+That would give you the default theme, but with a sidebar on the right side and
+a black background for the relation bar (the bar with the navigation links at
+the page's top and bottom).
+
+If the theme does not come with Sphinx, it can be in two static forms: either a
+directory (containing :file:`theme.conf` and other needed files), or a zip file
+with the same contents. Either of them must be put where Sphinx can find it;
+for this there is the config value :confval:`html_theme_path`. It gives a list
+of directories, relative to the directory containing :file:`conf.py`, that can
+contain theme directories or zip files. For example, if you have a theme in the
+file :file:`blue.zip`, you can put it right in the directory containing
+:file:`conf.py` and use this configuration::
+
+ html_theme = "blue"
+ html_theme_path = ["."]
+
+The third form provides your theme path dynamically to Sphinx if the
+``setuptools`` package is installed. You can provide an entry point section
+called ``sphinx_themes`` in your setup.py file and write a ``get_path`` function
+that has to return the directory with themes in it::
+
+ // in your 'setup.py'
+
+ setup(
+ ...
+ entry_points = {
+ 'sphinx_themes': [
+ 'path = your_package:get_path',
+ ]
+ },
+ ...
+ )
+
+ // in 'your_package.py'
+
+ from os import path
+ package_dir = path.abspath(path.dirname(__file__))
+ template_path = path.join(package_dir, 'themes')
+
+ def get_path():
+ return template_path
+
+.. versionadded:: 1.2
+ 'sphinx_themes' entry_points feature.
+
+
+.. _builtin-themes:
+
+Builtin themes
+--------------
+
+.. cssclass:: right
+
++--------------------+--------------------+
+| **Theme overview** | |
++--------------------+--------------------+
+| |default| | |sphinxdoc| |
+| | |
+| *default* | *sphinxdoc* |
++--------------------+--------------------+
+| |scrolls| | |agogo| |
+| | |
+| *scrolls* | *agogo* |
++--------------------+--------------------+
+| |traditional| | |nature| |
+| | |
+| *traditional* | *nature* |
++--------------------+--------------------+
+| |haiku| | |pyramid| |
+| | |
+| *haiku* | *pyramid* |
++--------------------+--------------------+
+
+.. |default| image:: themes/default.png
+.. |sphinxdoc| image:: themes/sphinxdoc.png
+.. |scrolls| image:: themes/scrolls.png
+.. |agogo| image:: themes/agogo.png
+.. |traditional| image:: themes/traditional.png
+.. |nature| image:: themes/nature.png
+.. |haiku| image:: themes/haiku.png
+.. |pyramid| image:: themes/pyramid.png
+
+Sphinx comes with a selection of themes to choose from.
+
+These themes are:
+
+* **basic** -- This is a basically unstyled layout used as the base for the
+ other themes, and usable as the base for custom themes as well. The HTML
+ contains all important elements like sidebar and relation bar. There are
+ these options (which are inherited by the other themes):
+
+ - **nosidebar** (true or false): Don't include the sidebar. Defaults to
+ false.
+
+ - **sidebarwidth** (an integer): Width of the sidebar in pixels. (Do not
+ include ``px`` in the value.) Defaults to 230 pixels.
+
+* **default** -- This is the default theme, which looks like `the Python
+ documentation <http://docs.python.org/>`_. It can be customized via these
+ options:
+
+ - **rightsidebar** (true or false): Put the sidebar on the right side.
+ Defaults to false.
+
+ - **stickysidebar** (true or false): Make the sidebar "fixed" so that it
+ doesn't scroll out of view for long body content. This may not work well
+ with all browsers. Defaults to false.
+
+ - **collapsiblesidebar** (true or false): Add an *experimental* JavaScript
+ snippet that makes the sidebar collapsible via a button on its side.
+ *Doesn't work with "stickysidebar".* Defaults to false.
+
+ - **externalrefs** (true or false): Display external links differently from
+ internal links. Defaults to false.
+
+ There are also various color and font options that can change the color scheme
+ without having to write a custom stylesheet:
+
+ - **footerbgcolor** (CSS color): Background color for the footer line.
+ - **footertextcolor** (CSS color): Text color for the footer line.
+ - **sidebarbgcolor** (CSS color): Background color for the sidebar.
+ - **sidebarbtncolor** (CSS color): Background color for the sidebar collapse
+ button (used when *collapsiblesidebar* is true).
+ - **sidebartextcolor** (CSS color): Text color for the sidebar.
+ - **sidebarlinkcolor** (CSS color): Link color for the sidebar.
+ - **relbarbgcolor** (CSS color): Background color for the relation bar.
+ - **relbartextcolor** (CSS color): Text color for the relation bar.
+ - **relbarlinkcolor** (CSS color): Link color for the relation bar.
+ - **bgcolor** (CSS color): Body background color.
+ - **textcolor** (CSS color): Body text color.
+ - **linkcolor** (CSS color): Body link color.
+ - **visitedlinkcolor** (CSS color): Body color for visited links.
+ - **headbgcolor** (CSS color): Background color for headings.
+ - **headtextcolor** (CSS color): Text color for headings.
+ - **headlinkcolor** (CSS color): Link color for headings.
+ - **codebgcolor** (CSS color): Background color for code blocks.
+ - **codetextcolor** (CSS color): Default text color for code blocks, if not
+ set differently by the highlighting style.
+
+ - **bodyfont** (CSS font-family): Font for normal text.
+ - **headfont** (CSS font-family): Font for headings.
+
+* **sphinxdoc** -- The theme used for this documentation. It features a sidebar
+ on the right side. There are currently no options beyond *nosidebar* and
+ *sidebarwidth*.
+
+* **scrolls** -- A more lightweight theme, based on `the Jinja documentation
+ <http://jinja.pocoo.org/>`_. The following color options are available:
+
+ - **headerbordercolor**
+ - **subheadlinecolor**
+ - **linkcolor**
+ - **visitedlinkcolor**
+ - **admonitioncolor**
+
+* **agogo** -- A theme created by Andi Albrecht. The following options are
+ supported:
+
+ - **bodyfont** (CSS font family): Font for normal text.
+ - **headerfont** (CSS font family): Font for headings.
+ - **pagewidth** (CSS length): Width of the page content, default 70em.
+ - **documentwidth** (CSS length): Width of the document (without sidebar),
+ default 50em.
+ - **sidebarwidth** (CSS length): Width of the sidebar, default 20em.
+ - **bgcolor** (CSS color): Background color.
+ - **headerbg** (CSS value for "background"): background for the header area,
+ default a grayish gradient.
+ - **footerbg** (CSS value for "background"): background for the footer area,
+ default a light gray gradient.
+ - **linkcolor** (CSS color): Body link color.
+ - **headercolor1**, **headercolor2** (CSS color): colors for <h1> and <h2>
+ headings.
+ - **headerlinkcolor** (CSS color): Color for the backreference link in
+ headings.
+ - **textalign** (CSS *text-align* value): Text alignment for the body, default
+ is ``justify``.
+
+* **nature** -- A greenish theme. There are currently no options beyond
+ *nosidebar* and *sidebarwidth*.
+
+* **pyramid** -- A theme from the Pyramid web framework project, designed by
+ Blaise Laflamme. There are currently no options beyond *nosidebar* and
+ *sidebarwidth*.
+
+* **haiku** -- A theme without sidebar inspired by the `Haiku OS user guide
+ <http://www.haiku-os.org/docs/userguide/en/contents.html>`_. The following
+ options are supported:
+
+ - **full_logo** (true or false, default false): If this is true, the header
+ will only show the :confval:`html_logo`. Use this for large logos. If this
+ is false, the logo (if present) will be shown floating right, and the
+ documentation title will be put in the header.
+ - **textcolor**, **headingcolor**, **linkcolor**, **visitedlinkcolor**,
+ **hoverlinkcolor** (CSS colors): Colors for various body elements.
+
+* **traditional** -- A theme resembling the old Python documentation. There are
+ currently no options beyond *nosidebar* and *sidebarwidth*.
+
+* **epub** -- A theme for the epub builder. This theme tries to save visual
+ space which is a sparse resource on ebook readers. The following options
+ are supported:
+
+ - **relbar1** (true or false, default true): If this is true, the
+ `relbar1` block is inserted in the epub output, otherwise it is omitted.
+ - **footer** (true or false, default true): If this is true, the
+ `footer` block is inserted in the epub output, otherwise it is ommitted.
+
+Creating themes
+---------------
+
+As said, themes are either a directory or a zipfile (whose name is the theme
+name), containing the following:
+
+* A :file:`theme.conf` file, see below.
+* HTML templates, if needed.
+* A ``static/`` directory containing any static files that will be copied to the
+ output static directory on build. These can be images, styles, script files.
+
+The :file:`theme.conf` file is in INI format [1]_ (readable by the standard
+Python :mod:`ConfigParser` module) and has the following structure:
+
+.. sourcecode:: ini
+
+ [theme]
+ inherit = base theme
+ stylesheet = main CSS name
+ pygments_style = stylename
+
+ [options]
+ variable = default value
+
+* The **inherit** setting gives the name of a "base theme", or ``none``. The
+ base theme will be used to locate missing templates (most themes will not have
+ to supply most templates if they use ``basic`` as the base theme), its options
+ will be inherited, and all of its static files will be used as well.
+
+* The **stylesheet** setting gives the name of a CSS file which will be
+ referenced in the HTML header. If you need more than one CSS file, either
+ include one from the other via CSS' ``@import``, or use a custom HTML template
+ that adds ``<link rel="stylesheet">`` tags as necessary. Setting the
+ :confval:`html_style` config value will override this setting.
+
+* The **pygments_style** setting gives the name of a Pygments style to use for
+ highlighting. This can be overridden by the user in the
+ :confval:`pygments_style` config value.
+
+* The **options** section contains pairs of variable names and default values.
+ These options can be overridden by the user in :confval:`html_theme_options`
+ and are accessible from all templates as ``theme_<name>``.
+
+
+Templating
+~~~~~~~~~~
+
+The :doc:`guide to templating <templating>` is helpful if you want to write your
+own templates. What is important to keep in mind is the order in which Sphinx
+searches for templates:
+
+* First, in the user's ``templates_path`` directories.
+* Then, in the selected theme.
+* Then, in its base theme, its base's base theme, etc.
+
+When extending a template in the base theme with the same name, use the theme
+name as an explicit directory: ``{% extends "basic/layout.html" %}``. From a
+user ``templates_path`` template, you can still use the "exclamation mark"
+syntax as described in the templating document.
+
+
+Static templates
+~~~~~~~~~~~~~~~~
+
+Since theme options are meant for the user to configure a theme more easily,
+without having to write a custom stylesheet, it is necessary to be able to
+template static files as well as HTML files. Therefore, Sphinx supports
+so-called "static templates", like this:
+
+If the name of a file in the ``static/`` directory of a theme (or in the user's
+static path, for that matter) ends with ``_t``, it will be processed by the
+template engine. The ``_t`` will be left from the final file name. For
+example, the *default* theme has a file ``static/default.css_t`` which uses
+templating to put the color options into the stylesheet. When a documentation
+is built with the default theme, the output directory will contain a
+``_static/default.css`` file where all template tags have been processed.
+
+
+.. [1] It is not an executable Python file, as opposed to :file:`conf.py`,
+ because that would pose an unnecessary security risk if themes are
+ shared.
+
diff --git a/doc/translation.png b/doc/translation.png
new file mode 100644
index 0000000..aa368b6
Binary files /dev/null and b/doc/translation.png differ
diff --git a/doc/tutorial.rst b/doc/tutorial.rst
new file mode 100644
index 0000000..cae4c8d
--- /dev/null
+++ b/doc/tutorial.rst
@@ -0,0 +1,309 @@
+.. highlight:: rst
+
+First Steps with Sphinx
+=======================
+
+This document is meant to give a tutorial-like overview of all common tasks
+while using Sphinx.
+
+The green arrows designate "more info" links leading to advanced sections about
+the described task.
+
+
+Setting up the documentation sources
+------------------------------------
+
+The root directory of a Sphinx collection of reStructuredText document sources
+is called the :term:`source directory`. This directory also contains the Sphinx
+configuration file :file:`conf.py`, where you can configure all aspects of how
+Sphinx reads your sources and builds your documentation. [#]_
+
+Sphinx comes with a script called :program:`sphinx-quickstart` that sets up a
+source directory and creates a default :file:`conf.py` with the most useful
+configuration values from a few questions it asks you. Just run ::
+
+ $ sphinx-quickstart
+
+and answer its questions. (Be sure to say yes to the "autodoc" extension.)
+
+There is also an automatic "API documentation" generator called
+:program:`sphinx-apidoc`; see :ref:`invocation-apidoc` for details.
+
+
+Defining document structure
+---------------------------
+
+Let's assume you've run :program:`sphinx-quickstart`. It created a source
+directory with :file:`conf.py` and a master document, :file:`index.rst` (if you
+accepted the defaults). The main function of the :term:`master document` is to
+serve as a welcome page, and to contain the root of the "table of contents tree"
+(or *toctree*). This is one of the main things that Sphinx adds to
+reStructuredText, a way to connect multiple files to a single hierarchy of
+documents.
+
+.. sidebar:: reStructuredText directives
+
+ ``toctree`` is a reStructuredText :dfn:`directive`, a very versatile piece of
+ markup. Directives can have arguments, options and content.
+
+ *Arguments* are given directly after the double colon following the
+ directive's name. Each directive decides whether it can have arguments, and
+ how many.
+
+ *Options* are given after the arguments, in form of a "field list". The
+ ``maxdepth`` is such an option for the ``toctree`` directive.
+
+ *Content* follows the options or arguments after a blank line. Each
+ directive decides whether to allow content, and what to do with it.
+
+ A common gotcha with directives is that **the first line of the content must
+ be indented to the same level as the options are**.
+
+
+The toctree directive initially is empty, and looks like this::
+
+ .. toctree::
+ :maxdepth: 2
+
+You add documents listing them in the *content* of the directive::
+
+ .. toctree::
+ :maxdepth: 2
+
+ intro
+ tutorial
+ ...
+
+This is exactly how the toctree for this documentation looks. The documents to
+include are given as :term:`document name`\ s, which in short means that you
+leave off the file name extension and use slashes as directory separators.
+
+|more| Read more about :ref:`the toctree directive <toctree-directive>`.
+
+You can now create the files you listed in the toctree and add content, and
+their section titles will be inserted (up to the "maxdepth" level) at the place
+where the toctree directive is placed. Also, Sphinx now knows about the order
+and hierarchy of your documents. (They may contain ``toctree`` directives
+themselves, which means you can create deeply nested hierarchies if necessary.)
+
+
+Adding content
+--------------
+
+In Sphinx source files, you can use most features of standard reStructuredText.
+There are also several features added by Sphinx. For example, you can add
+cross-file references in a portable way (which works for all output types) using
+the :rst:role:`ref` role.
+
+For an example, if you are viewing the HTML version you can look at the source
+for this document -- use the "Show Source" link in the sidebar.
+
+|more| See :ref:`rst-primer` for a more in-depth introduction to
+reStructuredText and :ref:`sphinxmarkup` for a full list of markup added by
+Sphinx.
+
+
+Running the build
+-----------------
+
+Now that you have added some files and content, let's make a first build of the
+docs. A build is started with the :program:`sphinx-build` program, called like
+this::
+
+ $ sphinx-build -b html sourcedir builddir
+
+where *sourcedir* is the :term:`source directory`, and *builddir* is the
+directory in which you want to place the built documentation. The :option:`-b`
+option selects a builder; in this example Sphinx will build HTML files.
+
+|more| See :ref:`invocation` for all options that :program:`sphinx-build`
+supports.
+
+However, :program:`sphinx-quickstart` script creates a :file:`Makefile` and a
+:file:`make.bat` which make life even easier for you: with them you only need
+to run ::
+
+ $ make html
+
+to build HTML docs in the build directory you chose. Execute ``make`` without
+an argument to see which targets are available.
+
+.. admonition:: How do I generate PDF documents?
+
+ ``make latexpdf`` runs the :mod:`LaTeX builder
+ <sphinx.builders.latex.LaTeXBuilder>` and readily invokes the pdfTeX
+ toolchain for you.
+
+
+Documenting objects
+-------------------
+
+One of Sphinx' main objectives is easy documentation of :dfn:`objects` (in a
+very general sense) in any :dfn:`domain`. A domain is a collection of object
+types that belong together, complete with markup to create and reference
+descriptions of these objects.
+
+The most prominent domain is the Python domain. To e.g. document the Python
+built-in function ``enumerate()``, you would add this to one of your source
+files::
+
+ .. py:function:: enumerate(sequence[, start=0])
+
+ Return an iterator that yields tuples of an index and an item of the
+ *sequence*. (And so on.)
+
+This is rendered like this:
+
+.. py:function:: enumerate(sequence[, start=0])
+
+ Return an iterator that yields tuples of an index and an item of the
+ *sequence*. (And so on.)
+
+The argument of the directive is the :dfn:`signature` of the object you
+describe, the content is the documentation for it. Multiple signatures can be
+given, each in its own line.
+
+The Python domain also happens to be the default domain, so you don't need to
+prefix the markup with the domain name::
+
+ .. function:: enumerate(sequence[, start=0])
+
+ ...
+
+does the same job if you keep the default setting for the default domain.
+
+There are several more directives for documenting other types of Python objects,
+for example :rst:dir:`py:class` or :rst:dir:`py:method`. There is also a
+cross-referencing :dfn:`role` for each of these object types. This markup will
+create a link to the documentation of ``enumerate()``::
+
+ The :py:func:`enumerate` function can be used for ...
+
+And here is the proof: A link to :func:`enumerate`.
+
+Again, the ``py:`` can be left out if the Python domain is the default one. It
+doesn't matter which file contains the actual documentation for ``enumerate()``;
+Sphinx will find it and create a link to it.
+
+Each domain will have special rules for how the signatures can look like, and
+make the formatted output look pretty, or add specific features like links to
+parameter types, e.g. in the C/C++ domains.
+
+|more| See :ref:`domains` for all the available domains and their
+directives/roles.
+
+
+Basic configuration
+-------------------
+
+Earlier we mentioned that the :file:`conf.py` file controls how Sphinx processes
+your documents. In that file, which is executed as a Python source file, you
+assign configuration values. For advanced users: since it is executed by
+Sphinx, you can do non-trivial tasks in it, like extending :data:`sys.path` or
+importing a module to find out the version your are documenting.
+
+The config values that you probably want to change are already put into the
+:file:`conf.py` by :program:`sphinx-quickstart` and initially commented out
+(with standard Python syntax: a ``#`` comments the rest of the line). To change
+the default value, remove the hash sign and modify the value. To customize a
+config value that is not automatically added by :program:`sphinx-quickstart`,
+just add an additional assignment.
+
+Keep in mind that the file uses Python syntax for strings, numbers, lists and so
+on. The file is saved in UTF-8 by default, as indicated by the encoding
+declaration in the first line. If you use non-ASCII characters in any string
+value, you need to use Python Unicode strings (like ``project = u'Exposé'``).
+
+|more| See :ref:`build-config` for documentation of all available config values.
+
+
+Autodoc
+-------
+
+When documenting Python code, it is common to put a lot of documentation in the
+source files, in documentation strings. Sphinx supports the inclusion of
+docstrings from your modules with an :dfn:`extension` (an extension is a Python
+module that provides additional features for Sphinx projects) called "autodoc".
+
+In order to use autodoc, you need to activate it in :file:`conf.py` by putting
+the string ``'sphinx.ext.autodoc'`` into the list assigned to the
+:confval:`extensions` config value. Then, you have a few additional directives
+at your disposal.
+
+For example, to document the function ``io.open()``, reading its
+signature and docstring from the source file, you'd write this::
+
+ .. autofunction:: io.open
+
+You can also document whole classes or even modules automatically, using member
+options for the auto directives, like ::
+
+ .. automodule:: io
+ :members:
+
+autodoc needs to import your modules in order to extract the docstrings.
+Therefore, you must add the appropriate path to :py:data:`sys.path` in your
+:file:`conf.py`.
+
+.. warning::
+
+ :mod:`~sphinx.ext.autodoc` **imports** the modules to be documented. If any
+ modules have side effects on import, these will be executed by ``autodoc``
+ when ``sphinx-build`` is run.
+
+ If you document scripts (as opposed to library modules), make sure their main
+ routine is protected by a ``if __name__ == '__main__'`` condition.
+
+|more| See :mod:`sphinx.ext.autodoc` for the complete description of the
+features of autodoc.
+
+Intersphinx
+-----------
+
+Many Sphinx documents including the `Python documentation`_ are published on the
+internet. When you want to make links to such documents from your
+documentation, you can do it with :mod:`sphinx.ext.intersphinx`.
+
+.. _Python documentation: http://docs.python.org/3
+
+In order to use intersphinx, you need to activate it in :file:`conf.py` by
+putting the string ``'sphinx.ext.intersphinx'`` into the :confval:`extensions`
+list and set up the :confval:`intersphinx_mapping` config value.
+
+For example, to link to ``io.open()`` in the Python library manual, you need to
+setup your :confval:`intersphinx_mapping` like::
+
+ intersphinx_mapping = {'python': ('http://docs.python.org/3', None)}
+
+And now, you can write a cross-reference like ``:py:func:`io.open```. Any
+cross-reference that has no matching target in the current documentation set,
+will be looked up in the documentation sets configured in
+:confval:`intersphinx_mapping` (this needs access to the URL in order to
+download the list of valid targets). Intersphinx also works for some other
+:ref:`domains' <domains>` roles including ``:ref:``, however it doesn't work for
+``:doc:`` as that is non-domain role.
+
+|more| See :mod:`sphinx.ext.intersphinx` for the complete description of the
+features of intersphinx.
+
+
+More topics to be covered
+-------------------------
+
+- Other extensions (math, viewcode, doctest)
+- Static files
+- Selecting a theme
+- Templating
+- Using extensions
+- Writing extensions
+
+
+.. rubric:: Footnotes
+
+.. [#] This is the usual lay-out. However, :file:`conf.py` can also live in
+ another directory, the :term:`configuration directory`. See
+ :ref:`invocation`.
+
+.. |more| image:: more.png
+ :align: middle
+ :alt: more info
diff --git a/doc/web/api.rst b/doc/web/api.rst
new file mode 100644
index 0000000..070cd3a
--- /dev/null
+++ b/doc/web/api.rst
@@ -0,0 +1,65 @@
+.. _websupportapi:
+
+.. currentmodule:: sphinx.websupport
+
+The WebSupport Class
+====================
+
+.. class:: WebSupport
+
+ The main API class for the web support package. All interactions with the
+ web support package should occur through this class.
+
+ The class takes the following keyword arguments:
+
+ srcdir
+ The directory containing reStructuredText source files.
+
+ builddir
+ The directory that build data and static files should be placed in. This
+ should be used when creating a :class:`WebSupport` object that will be
+ used to build data.
+
+ datadir
+ The directory that the web support data is in. This should be used when
+ creating a :class:`WebSupport` object that will be used to retrieve data.
+
+ search
+ This may contain either a string (e.g. 'xapian') referencing a built-in
+ search adapter to use, or an instance of a subclass of
+ :class:`~.search.BaseSearch`.
+
+ storage
+ This may contain either a string representing a database uri, or an
+ instance of a subclass of :class:`~.storage.StorageBackend`. If this is
+ not provided, a new sqlite database will be created.
+
+ moderation_callback
+ A callable to be called when a new comment is added that is not
+ displayed. It must accept one argument: a dictionary representing the
+ comment that was added.
+
+ staticdir
+ If static files are served from a location besides ``'/static'``, this
+ should be a string with the name of that location
+ (e.g. ``'/static_files'``).
+
+ docroot
+ If the documentation is not served from the base path of a URL, this
+ should be a string specifying that path (e.g. ``'docs'``).
+
+
+Methods
+~~~~~~~
+
+.. automethod:: sphinx.websupport.WebSupport.build
+
+.. automethod:: sphinx.websupport.WebSupport.get_document
+
+.. automethod:: sphinx.websupport.WebSupport.get_data
+
+.. automethod:: sphinx.websupport.WebSupport.add_comment
+
+.. automethod:: sphinx.websupport.WebSupport.process_vote
+
+.. automethod:: sphinx.websupport.WebSupport.get_search_results
diff --git a/doc/web/quickstart.rst b/doc/web/quickstart.rst
new file mode 100644
index 0000000..1bcd217
--- /dev/null
+++ b/doc/web/quickstart.rst
@@ -0,0 +1,254 @@
+.. _websupportquickstart:
+
+Web Support Quick Start
+=======================
+
+Building Documentation Data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To make use of the web support package in your application you'll need to build
+the data it uses. This data includes pickle files representing documents,
+search indices, and node data that is used to track where comments and other
+things are in a document. To do this you will need to create an instance of the
+:class:`~.WebSupport` class and call its :meth:`~.WebSupport.build` method::
+
+ from sphinx.websupport import WebSupport
+
+ support = WebSupport(srcdir='/path/to/rst/sources/',
+ builddir='/path/to/build/outdir',
+ search='xapian')
+
+ support.build()
+
+This will read reStructuredText sources from `srcdir` and place the necessary
+data in `builddir`. The `builddir` will contain two sub-directories: one named
+"data" that contains all the data needed to display documents, search through
+documents, and add comments to documents. The other directory will be called
+"static" and contains static files that should be served from "/static".
+
+.. note::
+
+ If you wish to serve static files from a path other than "/static", you can
+ do so by providing the *staticdir* keyword argument when creating the
+ :class:`~.WebSupport` object.
+
+
+Integrating Sphinx Documents Into Your Webapp
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Now that the data is built, it's time to do something useful with it. Start off
+by creating a :class:`~.WebSupport` object for your application::
+
+ from sphinx.websupport import WebSupport
+
+ support = WebSupport(datadir='/path/to/the/data',
+ search='xapian')
+
+You'll only need one of these for each set of documentation you will be working
+with. You can then call it's :meth:`~.WebSupport.get_document` method to access
+individual documents::
+
+ contents = support.get_document('contents')
+
+This will return a dictionary containing the following items:
+
+* **body**: The main body of the document as HTML
+* **sidebar**: The sidebar of the document as HTML
+* **relbar**: A div containing links to related documents
+* **title**: The title of the document
+* **css**: Links to css files used by Sphinx
+* **js**: Javascript containing comment options
+
+This dict can then be used as context for templates. The goal is to be easy to
+integrate with your existing templating system. An example using `Jinja2
+<http://jinja.pocoo.org/>`_ is:
+
+.. sourcecode:: html+jinja
+
+ {%- extends "layout.html" %}
+
+ {%- block title %}
+ {{ document.title }}
+ {%- endblock %}
+
+ {% block css %}
+ {{ super() }}
+ {{ document.css|safe }}
+ <link rel="stylesheet" href="/static/websupport-custom.css" type="text/css">
+ {% endblock %}
+
+ {%- block js %}
+ {{ super() }}
+ {{ document.js|safe }}
+ {%- endblock %}
+
+ {%- block relbar %}
+ {{ document.relbar|safe }}
+ {%- endblock %}
+
+ {%- block body %}
+ {{ document.body|safe }}
+ {%- endblock %}
+
+ {%- block sidebar %}
+ {{ document.sidebar|safe }}
+ {%- endblock %}
+
+
+Authentication
+--------------
+
+To use certain features such as voting, it must be possible to authenticate
+users. The details of the authentication are left to your application. Once a
+user has been authenticated you can pass the user's details to certain
+:class:`~.WebSupport` methods using the *username* and *moderator* keyword
+arguments. The web support package will store the username with comments and
+votes. The only caveat is that if you allow users to change their username you
+must update the websupport package's data::
+
+ support.update_username(old_username, new_username)
+
+*username* should be a unique string which identifies a user, and *moderator*
+should be a boolean representing whether the user has moderation privilieges.
+The default value for *moderator* is *False*.
+
+An example `Flask <http://flask.pocoo.org/>`_ function that checks whether a
+user is logged in and then retrieves a document is::
+
+ from sphinx.websupport.errors import *
+
+ @app.route('/<path:docname>')
+ def doc(docname):
+ username = g.user.name if g.user else ''
+ moderator = g.user.moderator if g.user else False
+ try:
+ document = support.get_document(docname, username, moderator)
+ except DocumentNotFoundError:
+ abort(404)
+ return render_template('doc.html', document=document)
+
+The first thing to notice is that the *docname* is just the request path. This
+makes accessing the correct document easy from a single view. If the user is
+authenticated, then the username and moderation status are passed along with the
+docname to :meth:`~.WebSupport.get_document`. The web support package will then
+add this data to the ``COMMENT_OPTIONS`` that are used in the template.
+
+.. note::
+
+ This only works works if your documentation is served from your
+ document root. If it is served from another directory, you will
+ need to prefix the url route with that directory, and give the `docroot`
+ keyword argument when creating the web support object::
+
+ support = WebSupport(..., docroot='docs')
+
+ @app.route('/docs/<path:docname>')
+
+
+Performing Searches
+~~~~~~~~~~~~~~~~~~~
+
+To use the search form built-in to the Sphinx sidebar, create a function to
+handle requests to the url 'search' relative to the documentation root. The
+user's search query will be in the GET parameters, with the key `q`. Then use
+the :meth:`~sphinx.websupport.WebSupport.get_search_results` method to retrieve
+search results. In `Flask <http://flask.pocoo.org/>`_ that would be like this::
+
+ @app.route('/search')
+ def search():
+ q = request.args.get('q')
+ document = support.get_search_results(q)
+ return render_template('doc.html', document=document)
+
+Note that we used the same template to render our search results as we did to
+render our documents. That's because :meth:`~.WebSupport.get_search_results`
+returns a context dict in the same format that :meth:`~.WebSupport.get_document`
+does.
+
+
+Comments & Proposals
+~~~~~~~~~~~~~~~~~~~~
+
+Now that this is done it's time to define the functions that handle the AJAX
+calls from the script. You will need three functions. The first function is
+used to add a new comment, and will call the web support method
+:meth:`~.WebSupport.add_comment`::
+
+ @app.route('/docs/add_comment', methods=['POST'])
+ def add_comment():
+ parent_id = request.form.get('parent', '')
+ node_id = request.form.get('node', '')
+ text = request.form.get('text', '')
+ proposal = request.form.get('proposal', '')
+ username = g.user.name if g.user is not None else 'Anonymous'
+ comment = support.add_comment(text, node_id='node_id',
+ parent_id='parent_id',
+ username=username, proposal=proposal)
+ return jsonify(comment=comment)
+
+You'll notice that both a `parent_id` and `node_id` are sent with the
+request. If the comment is being attached directly to a node, `parent_id`
+will be empty. If the comment is a child of another comment, then `node_id`
+will be empty. Then next function handles the retrieval of comments for a
+specific node, and is aptly named
+:meth:`~sphinx.websupport.WebSupport.get_data`::
+
+ @app.route('/docs/get_comments')
+ def get_comments():
+ username = g.user.name if g.user else None
+ moderator = g.user.moderator if g.user else False
+ node_id = request.args.get('node', '')
+ data = support.get_data(node_id, username, moderator)
+ return jsonify(**data)
+
+The final function that is needed will call :meth:`~.WebSupport.process_vote`,
+and will handle user votes on comments::
+
+ @app.route('/docs/process_vote', methods=['POST'])
+ def process_vote():
+ if g.user is None:
+ abort(401)
+ comment_id = request.form.get('comment_id')
+ value = request.form.get('value')
+ if value is None or comment_id is None:
+ abort(400)
+ support.process_vote(comment_id, g.user.id, value)
+ return "success"
+
+
+Comment Moderation
+~~~~~~~~~~~~~~~~~~
+
+By default, all comments added through :meth:`~.WebSupport.add_comment` are
+automatically displayed. If you wish to have some form of moderation, you can
+pass the `displayed` keyword argument::
+
+ comment = support.add_comment(text, node_id='node_id',
+ parent_id='parent_id',
+ username=username, proposal=proposal,
+ displayed=False)
+
+You can then create a new view to handle the moderation of comments. It
+will be called when a moderator decides a comment should be accepted and
+displayed::
+
+ @app.route('/docs/accept_comment', methods=['POST'])
+ def accept_comment():
+ moderator = g.user.moderator if g.user else False
+ comment_id = request.form.get('id')
+ support.accept_comment(comment_id, moderator=moderator)
+ return 'OK'
+
+Rejecting comments happens via comment deletion.
+
+To perform a custom action (such as emailing a moderator) when a new comment is
+added but not displayed, you can pass callable to the :class:`~.WebSupport`
+class when instantiating your support object::
+
+ def moderation_callback(comment):
+ """Do something..."""
+
+ support = WebSupport(..., moderation_callback=moderation_callback)
+
+The moderation callback must take one argument, which will be the same comment
+dict that is returned by :meth:`add_comment`.
diff --git a/doc/web/searchadapters.rst b/doc/web/searchadapters.rst
new file mode 100644
index 0000000..7d8634f
--- /dev/null
+++ b/doc/web/searchadapters.rst
@@ -0,0 +1,45 @@
+.. _searchadapters:
+
+.. currentmodule:: sphinx.websupport.search
+
+Search Adapters
+===============
+
+To create a custom search adapter you will need to subclass the
+:class:`BaseSearch` class. Then create an instance of the new class and pass
+that as the `search` keyword argument when you create the :class:`~.WebSupport`
+object::
+
+ support = WebSupport(srcdir=srcdir,
+ builddir=builddir,
+ search=MySearch())
+
+For more information about creating a custom search adapter, please see the
+documentation of the :class:`BaseSearch` class below.
+
+.. class:: BaseSearch
+
+ Defines an interface for search adapters.
+
+
+BaseSearch Methods
+~~~~~~~~~~~~~~~~~~
+
+ The following methods are defined in the BaseSearch class. Some methods do
+ not need to be overridden, but some (:meth:`~BaseSearch.add_document` and
+ :meth:`~BaseSearch.handle_query`) must be overridden in your subclass. For a
+ working example, look at the built-in adapter for whoosh.
+
+.. automethod:: BaseSearch.init_indexing
+
+.. automethod:: BaseSearch.finish_indexing
+
+.. automethod:: BaseSearch.feed
+
+.. automethod:: BaseSearch.add_document
+
+.. automethod:: BaseSearch.query
+
+.. automethod:: BaseSearch.handle_query
+
+.. automethod:: BaseSearch.extract_context
diff --git a/doc/web/storagebackends.rst b/doc/web/storagebackends.rst
new file mode 100644
index 0000000..d191b43
--- /dev/null
+++ b/doc/web/storagebackends.rst
@@ -0,0 +1,44 @@
+.. _storagebackends:
+
+.. currentmodule:: sphinx.websupport.storage
+
+Storage Backends
+================
+
+To create a custom storage backend you will need to subclass the
+:class:`StorageBackend` class. Then create an instance of the new class and
+pass that as the `storage` keyword argument when you create the
+:class:`~.WebSupport` object::
+
+ support = WebSupport(srcdir=srcdir,
+ builddir=builddir,
+ storage=MyStorage())
+
+For more information about creating a custom storage backend, please see the
+documentation of the :class:`StorageBackend` class below.
+
+.. class:: StorageBackend
+
+ Defines an interface for storage backends.
+
+
+StorageBackend Methods
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. automethod:: StorageBackend.pre_build
+
+.. automethod:: StorageBackend.add_node
+
+.. automethod:: StorageBackend.post_build
+
+.. automethod:: StorageBackend.add_comment
+
+.. automethod:: StorageBackend.delete_comment
+
+.. automethod:: StorageBackend.get_data
+
+.. automethod:: StorageBackend.process_vote
+
+.. automethod:: StorageBackend.update_username
+
+.. automethod:: StorageBackend.accept_comment
diff --git a/doc/websupport.rst b/doc/websupport.rst
new file mode 100644
index 0000000..3ccae24
--- /dev/null
+++ b/doc/websupport.rst
@@ -0,0 +1,16 @@
+.. _websupport:
+
+Sphinx Web Support
+==================
+
+.. versionadded:: 1.1
+
+Sphinx provides a Python API to easily integrate Sphinx documentation into your
+web application. To learn more read the :ref:`websupportquickstart`.
+
+.. toctree::
+
+ web/quickstart
+ web/api
+ web/searchadapters
+ web/storagebackends
diff --git a/ez_setup.py b/ez_setup.py
new file mode 100644
index 0000000..b02f3f1
--- /dev/null
+++ b/ez_setup.py
@@ -0,0 +1,370 @@
+#!python
+"""Bootstrap setuptools installation
+
+If you want to use setuptools in your package's setup.py, just include this
+file in the same directory with it, and add this to the top of your setup.py::
+
+ from ez_setup import use_setuptools
+ use_setuptools()
+
+If you want to require a specific version of setuptools, set a download
+mirror, or use an alternate download directory, you can do so by supplying
+the appropriate options to ``use_setuptools()``.
+
+This file can also be run as a script to install or upgrade setuptools.
+"""
+import os
+import shutil
+import sys
+import tempfile
+import tarfile
+import optparse
+import subprocess
+import platform
+
+from distutils import log
+
+try:
+ from site import USER_SITE
+except ImportError:
+ USER_SITE = None
+
+DEFAULT_VERSION = "1.1.6"
+DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
+
+def _python_cmd(*args):
+ args = (sys.executable,) + args
+ return subprocess.call(args) == 0
+
+def _check_call_py24(cmd, *args, **kwargs):
+ res = subprocess.call(cmd, *args, **kwargs)
+ class CalledProcessError(Exception):
+ pass
+ if not res == 0:
+ msg = "Command '%s' return non-zero exit status %d" % (cmd, res)
+ raise CalledProcessError(msg)
+vars(subprocess).setdefault('check_call', _check_call_py24)
+
+def _install(tarball, install_args=()):
+ # extracting the tarball
+ tmpdir = tempfile.mkdtemp()
+ log.warn('Extracting in %s', tmpdir)
+ old_wd = os.getcwd()
+ try:
+ os.chdir(tmpdir)
+ tar = tarfile.open(tarball)
+ _extractall(tar)
+ tar.close()
+
+ # going in the directory
+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
+ os.chdir(subdir)
+ log.warn('Now working in %s', subdir)
+
+ # installing
+ log.warn('Installing Setuptools')
+ if not _python_cmd('setup.py', 'install', *install_args):
+ log.warn('Something went wrong during the installation.')
+ log.warn('See the error message above.')
+ # exitcode will be 2
+ return 2
+ finally:
+ os.chdir(old_wd)
+ shutil.rmtree(tmpdir)
+
+
+def _build_egg(egg, tarball, to_dir):
+ # extracting the tarball
+ tmpdir = tempfile.mkdtemp()
+ log.warn('Extracting in %s', tmpdir)
+ old_wd = os.getcwd()
+ try:
+ os.chdir(tmpdir)
+ tar = tarfile.open(tarball)
+ _extractall(tar)
+ tar.close()
+
+ # going in the directory
+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
+ os.chdir(subdir)
+ log.warn('Now working in %s', subdir)
+
+ # building an egg
+ log.warn('Building a Setuptools egg in %s', to_dir)
+ _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
+
+ finally:
+ os.chdir(old_wd)
+ shutil.rmtree(tmpdir)
+ # returning the result
+ log.warn(egg)
+ if not os.path.exists(egg):
+ raise IOError('Could not build the egg.')
+
+
+def _do_download(version, download_base, to_dir, download_delay):
+ egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg'
+ % (version, sys.version_info[0], sys.version_info[1]))
+ if not os.path.exists(egg):
+ tarball = download_setuptools(version, download_base,
+ to_dir, download_delay)
+ _build_egg(egg, tarball, to_dir)
+ sys.path.insert(0, egg)
+
+ # Remove previously-imported pkg_resources if present (see
+ # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
+ if 'pkg_resources' in sys.modules:
+ del sys.modules['pkg_resources']
+
+ import setuptools
+ setuptools.bootstrap_install_from = egg
+
+
+def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+ to_dir=os.curdir, download_delay=15):
+ # making sure we use the absolute path
+ to_dir = os.path.abspath(to_dir)
+ was_imported = 'pkg_resources' in sys.modules or \
+ 'setuptools' in sys.modules
+ try:
+ import pkg_resources
+ except ImportError:
+ return _do_download(version, download_base, to_dir, download_delay)
+ try:
+ pkg_resources.require("setuptools>=" + version)
+ return
+ except pkg_resources.VersionConflict:
+ e = sys.exc_info()[1]
+ if was_imported:
+ sys.stderr.write(
+ "The required version of setuptools (>=%s) is not available,\n"
+ "and can't be installed while this script is running. Please\n"
+ "install a more recent version first, using\n"
+ "'easy_install -U setuptools'."
+ "\n\n(Currently using %r)\n" % (version, e.args[0]))
+ sys.exit(2)
+ else:
+ del pkg_resources, sys.modules['pkg_resources'] # reload ok
+ return _do_download(version, download_base, to_dir,
+ download_delay)
+ except pkg_resources.DistributionNotFound:
+ return _do_download(version, download_base, to_dir,
+ download_delay)
+
+def download_file_powershell(url, target):
+ """
+ Download the file at url to target using Powershell (which will validate
+ trust). Raise an exception if the command cannot complete.
+ """
+ target = os.path.abspath(target)
+ cmd = [
+ 'powershell',
+ '-Command',
+ "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)" % vars(),
+ ]
+ subprocess.check_call(cmd)
+
+def has_powershell():
+ if platform.system() != 'Windows':
+ return False
+ cmd = ['powershell', '-Command', 'echo test']
+ devnull = open(os.path.devnull, 'wb')
+ try:
+ try:
+ subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
+ except:
+ return False
+ finally:
+ devnull.close()
+ return True
+
+download_file_powershell.viable = has_powershell
+
+def download_file_curl(url, target):
+ cmd = ['curl', url, '--silent', '--output', target]
+ subprocess.check_call(cmd)
+
+def has_curl():
+ cmd = ['curl', '--version']
+ devnull = open(os.path.devnull, 'wb')
+ try:
+ try:
+ subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
+ except:
+ return False
+ finally:
+ devnull.close()
+ return True
+
+download_file_curl.viable = has_curl
+
+def download_file_wget(url, target):
+ cmd = ['wget', url, '--quiet', '--output-document', target]
+ subprocess.check_call(cmd)
+
+def has_wget():
+ cmd = ['wget', '--version']
+ devnull = open(os.path.devnull, 'wb')
+ try:
+ try:
+ subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
+ except:
+ return False
+ finally:
+ devnull.close()
+ return True
+
+download_file_wget.viable = has_wget
+
+def download_file_insecure(url, target):
+ """
+ Use Python to download the file, even though it cannot authenticate the
+ connection.
+ """
+ try:
+ from urllib.request import urlopen
+ except ImportError:
+ from urllib2 import urlopen
+ src = dst = None
+ try:
+ src = urlopen(url)
+ # Read/write all in one block, so we don't create a corrupt file
+ # if the download is interrupted.
+ data = src.read()
+ dst = open(target, "wb")
+ dst.write(data)
+ finally:
+ if src:
+ src.close()
+ if dst:
+ dst.close()
+
+download_file_insecure.viable = lambda: True
+
+def get_best_downloader():
+ downloaders = [
+ download_file_powershell,
+ download_file_curl,
+ download_file_wget,
+ download_file_insecure,
+ ]
+
+ for dl in downloaders:
+ if dl.viable():
+ return dl
+
+def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+ to_dir=os.curdir, delay=15,
+ downloader_factory=get_best_downloader):
+ """Download setuptools from a specified location and return its filename
+
+ `version` should be a valid setuptools version number that is available
+ as an egg for download under the `download_base` URL (which should end
+ with a '/'). `to_dir` is the directory where the egg will be downloaded.
+ `delay` is the number of seconds to pause before an actual download
+ attempt.
+
+ ``downloader_factory`` should be a function taking no arguments and
+ returning a function for downloading a URL to a target.
+ """
+ # making sure we use the absolute path
+ to_dir = os.path.abspath(to_dir)
+ tgz_name = "setuptools-%s.tar.gz" % version
+ url = download_base + tgz_name
+ saveto = os.path.join(to_dir, tgz_name)
+ if not os.path.exists(saveto): # Avoid repeated downloads
+ log.warn("Downloading %s", url)
+ downloader = downloader_factory()
+ downloader(url, saveto)
+ return os.path.realpath(saveto)
+
+
+def _extractall(self, path=".", members=None):
+ """Extract all members from the archive to the current working
+ directory and set owner, modification time and permissions on
+ directories afterwards. `path' specifies a different directory
+ to extract to. `members' is optional and must be a subset of the
+ list returned by getmembers().
+ """
+ import copy
+ import operator
+ from tarfile import ExtractError
+ directories = []
+
+ if members is None:
+ members = self
+
+ for tarinfo in members:
+ if tarinfo.isdir():
+ # Extract directories with a safe mode.
+ directories.append(tarinfo)
+ tarinfo = copy.copy(tarinfo)
+ tarinfo.mode = 448 # decimal for oct 0700
+ self.extract(tarinfo, path)
+
+ # Reverse sort directories.
+ if sys.version_info < (2, 4):
+ def sorter(dir1, dir2):
+ return cmp(dir1.name, dir2.name)
+ directories.sort(sorter)
+ directories.reverse()
+ else:
+ directories.sort(key=operator.attrgetter('name'), reverse=True)
+
+ # Set correct owner, mtime and filemode on directories.
+ for tarinfo in directories:
+ dirpath = os.path.join(path, tarinfo.name)
+ try:
+ self.chown(tarinfo, dirpath)
+ self.utime(tarinfo, dirpath)
+ self.chmod(tarinfo, dirpath)
+ except ExtractError:
+ e = sys.exc_info()[1]
+ if self.errorlevel > 1:
+ raise
+ else:
+ self._dbg(1, "tarfile: %s" % e)
+
+
+def _build_install_args(options):
+ """
+ Build the arguments to 'python setup.py install' on the setuptools package
+ """
+ install_args = []
+ if options.user_install:
+ if sys.version_info < (2, 6):
+ log.warn("--user requires Python 2.6 or later")
+ raise SystemExit(1)
+ install_args.append('--user')
+ return install_args
+
+def _parse_args():
+ """
+ Parse the command line for options
+ """
+ parser = optparse.OptionParser()
+ parser.add_option(
+ '--user', dest='user_install', action='store_true', default=False,
+ help='install in user site package (requires Python 2.6 or later)')
+ parser.add_option(
+ '--download-base', dest='download_base', metavar="URL",
+ default=DEFAULT_URL,
+ help='alternative URL from where to download the setuptools package')
+ parser.add_option(
+ '--insecure', dest='downloader_factory', action='store_const',
+ const=lambda: download_file_insecure, default=get_best_downloader,
+ help='Use internal, non-validating downloader'
+ )
+ options, args = parser.parse_args()
+ # positional arguments are ignored
+ return options
+
+def main(version=DEFAULT_VERSION):
+ """Install or upgrade setuptools and EasyInstall"""
+ options = _parse_args()
+ tarball = download_setuptools(download_base=options.download_base,
+ downloader_factory=options.downloader_factory)
+ return _install(tarball, _build_install_args(options))
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..5ddbe81
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,23 @@
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
+[aliases]
+release = egg_info -RDb ''
+upload = upload --sign --identity=5EBA0E07
+
+[extract_messages]
+mapping_file = babel.cfg
+output_file = sphinx/locale/sphinx.pot
+keywords = _ l_ lazy_gettext
+
+[update_catalog]
+input_file = sphinx/locale/sphinx.pot
+domain = sphinx
+output_dir = sphinx/locale/
+
+[compile_catalog]
+domain = sphinx
+directory = sphinx/locale/
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..9872226
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,204 @@
+# -*- coding: utf-8 -*-
+try:
+ from setuptools import setup, find_packages
+except ImportError:
+ import ez_setup
+ ez_setup.use_setuptools()
+ from setuptools import setup, find_packages
+
+import os
+import sys
+from distutils import log
+
+import sphinx
+
+long_desc = '''
+Sphinx is a tool that makes it easy to create intelligent and beautiful
+documentation for Python projects (or other documents consisting of multiple
+reStructuredText sources), written by Georg Brandl. It was originally created
+for the new Python documentation, and has excellent facilities for Python
+project documentation, but C/C++ is supported as well, and more languages are
+planned.
+
+Sphinx uses reStructuredText as its markup language, and many of its strengths
+come from the power and straightforwardness of reStructuredText and its parsing
+and translating suite, the Docutils.
+
+Among its features are the following:
+
+* Output formats: HTML (including derivative formats such as HTML Help, Epub
+ and Qt Help), plain text, manual pages and LaTeX or direct PDF output
+ using rst2pdf
+* Extensive cross-references: semantic markup and automatic links
+ for functions, classes, glossary terms and similar pieces of information
+* Hierarchical structure: easy definition of a document tree, with automatic
+ links to siblings, parents and children
+* Automatic indices: general index as well as a module index
+* Code handling: automatic highlighting using the Pygments highlighter
+* Flexible HTML output using the Jinja 2 templating engine
+* Various extensions are available, e.g. for automatic testing of snippets
+ and inclusion of appropriately formatted docstrings
+* Setuptools integration
+'''
+
+requires = ['Pygments>=1.2', 'docutils>=0.7']
+
+if sys.version_info[:3] >= (3, 3, 0):
+ requires[1] = 'docutils>=0.10'
+
+if sys.version_info < (2, 6) or (3, 0) <= sys.version_info < (3, 3):
+ requires.append('Jinja2>=2.3,<2.7')
+else:
+ requires.append('Jinja2>=2.3')
+
+if sys.version_info < (2, 5):
+ print('ERROR: Sphinx requires at least Python 2.5 to run.')
+ sys.exit(1)
+
+# tell distribute to use 2to3 with our own fixers
+extra = {}
+if sys.version_info >= (3, 0):
+ extra.update(
+ use_2to3=True,
+ use_2to3_fixers=['custom_fixers']
+ )
+
+# Provide a "compile_catalog" command that also creates the translated
+# JavaScript files if Babel is available.
+
+cmdclass = {}
+
+try:
+ from babel.messages.pofile import read_po
+ from babel.messages.frontend import compile_catalog
+ try:
+ from simplejson import dump
+ except ImportError:
+ from json import dump
+except ImportError:
+ pass
+else:
+ class compile_catalog_plusjs(compile_catalog):
+ """
+ An extended command that writes all message strings that occur in
+ JavaScript files to a JavaScript file along with the .mo file.
+
+ Unfortunately, babel's setup command isn't built very extensible, so
+ most of the run() code is duplicated here.
+ """
+
+ def run(self):
+ compile_catalog.run(self)
+
+ po_files = []
+ js_files = []
+
+ if not self.input_file:
+ if self.locale:
+ po_files.append((self.locale,
+ os.path.join(self.directory, self.locale,
+ 'LC_MESSAGES',
+ self.domain + '.po')))
+ js_files.append(os.path.join(self.directory, self.locale,
+ 'LC_MESSAGES',
+ self.domain + '.js'))
+ else:
+ for locale in os.listdir(self.directory):
+ po_file = os.path.join(self.directory, locale,
+ 'LC_MESSAGES',
+ self.domain + '.po')
+ if os.path.exists(po_file):
+ po_files.append((locale, po_file))
+ js_files.append(os.path.join(self.directory, locale,
+ 'LC_MESSAGES',
+ self.domain + '.js'))
+ else:
+ po_files.append((self.locale, self.input_file))
+ if self.output_file:
+ js_files.append(self.output_file)
+ else:
+ js_files.append(os.path.join(self.directory, self.locale,
+ 'LC_MESSAGES',
+ self.domain + '.js'))
+
+ for js_file, (locale, po_file) in zip(js_files, po_files):
+ infile = open(po_file, 'r')
+ try:
+ catalog = read_po(infile, locale)
+ finally:
+ infile.close()
+
+ if catalog.fuzzy and not self.use_fuzzy:
+ continue
+
+ log.info('writing JavaScript strings in catalog %r to %r',
+ po_file, js_file)
+
+ jscatalog = {}
+ for message in catalog:
+ if any(x[0].endswith(('.js', '.js_t', '.html'))
+ for x in message.locations):
+ msgid = message.id
+ if isinstance(msgid, (list, tuple)):
+ msgid = msgid[0]
+ jscatalog[msgid] = message.string
+
+ outfile = open(js_file, 'wb')
+ try:
+ outfile.write('Documentation.addTranslations(');
+ dump(dict(
+ messages=jscatalog,
+ plural_expr=catalog.plural_expr,
+ locale=str(catalog.locale)
+ ), outfile)
+ outfile.write(');')
+ finally:
+ outfile.close()
+
+ cmdclass['compile_catalog'] = compile_catalog_plusjs
+
+
+setup(
+ name='Sphinx',
+ version=sphinx.__version__,
+ url='http://sphinx-doc.org/',
+ download_url='http://pypi.python.org/pypi/Sphinx',
+ license='BSD',
+ author='Georg Brandl',
+ author_email='georg at python.org',
+ description='Python documentation generator',
+ long_description=long_desc,
+ zip_safe=False,
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Console',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Education',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 3',
+ 'Topic :: Documentation',
+ 'Topic :: Text Processing',
+ 'Topic :: Utilities',
+ ],
+ platforms='any',
+ packages=find_packages(exclude=['custom_fixers', 'test']),
+ include_package_data=True,
+ entry_points={
+ 'console_scripts': [
+ 'sphinx-build = sphinx:main',
+ 'sphinx-quickstart = sphinx.quickstart:main',
+ 'sphinx-apidoc = sphinx.apidoc:main',
+ 'sphinx-autogen = sphinx.ext.autosummary.generate:main',
+ ],
+ 'distutils.commands': [
+ 'build_sphinx = sphinx.setup_command:BuildDoc',
+ ],
+ },
+ install_requires=requires,
+ cmdclass=cmdclass,
+ **extra
+)
diff --git a/sphinx-apidoc.py b/sphinx-apidoc.py
new file mode 100755
index 0000000..02bf8b8
--- /dev/null
+++ b/sphinx-apidoc.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ Sphinx - Python documentation toolchain
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+
+if __name__ == '__main__':
+ from sphinx.apidoc import main
+ sys.exit(main(sys.argv))
diff --git a/sphinx-autogen.py b/sphinx-autogen.py
new file mode 100755
index 0000000..ba3f0f4
--- /dev/null
+++ b/sphinx-autogen.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ Sphinx - Python documentation toolchain
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+
+if __name__ == '__main__':
+ from sphinx.ext.autosummary.generate import main
+ sys.exit(main(sys.argv))
diff --git a/sphinx-build.py b/sphinx-build.py
new file mode 100755
index 0000000..8dd21a7
--- /dev/null
+++ b/sphinx-build.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ Sphinx - Python documentation toolchain
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+
+if __name__ == '__main__':
+ from sphinx import main
+ sys.exit(main(sys.argv))
diff --git a/sphinx-quickstart.py b/sphinx-quickstart.py
new file mode 100755
index 0000000..5d2b01d
--- /dev/null
+++ b/sphinx-quickstart.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ Sphinx - Python documentation toolchain
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+
+if __name__ == '__main__':
+ from sphinx.quickstart import main
+ sys.exit(main(sys.argv))
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
new file mode 100644
index 0000000..acee982
--- /dev/null
+++ b/sphinx/__init__.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+"""
+ Sphinx
+ ~~~~~~
+
+ The Sphinx documentation toolchain.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+# Keep this file executable as-is in Python 3!
+# (Otherwise getting the version out of it from setup.py is impossible.)
+
+import sys
+from os import path
+
+__version__ = '1.2.3'
+__released__ = '1.2.3' # used when Sphinx builds its own docs
+# version info for better programmatic use
+# possible values for 3rd element: 'alpha', 'beta', 'rc', 'final'
+# 'final' has 0 as the last element
+version_info = (1, 2, 3, 'final', 0)
+
+package_dir = path.abspath(path.dirname(__file__))
+
+if '+' in __version__ or 'pre' in __version__:
+ # try to find out the changeset hash if checked out from hg, and append
+ # it to __version__ (since we use this value from setup.py, it gets
+ # automatically propagated to an installed copy as well)
+ try:
+ import subprocess
+ p = subprocess.Popen(['hg', 'id', '-i', '-R',
+ path.join(package_dir, '..')],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ if out:
+ __version__ += '/' + out.strip()
+ except Exception:
+ pass
+
+
+def main(argv=sys.argv):
+ if sys.argv[1:2] == ['-M']:
+ sys.exit(make_main(argv))
+ else:
+ sys.exit(build_main(argv))
+
+
+def build_main(argv=sys.argv):
+ """Sphinx build "main" command-line entry."""
+ if sys.version_info[:3] < (2, 5, 0):
+ sys.stderr.write('Error: Sphinx requires at least Python 2.5 to run.\n')
+ return 1
+ try:
+ from sphinx import cmdline
+ except ImportError:
+ err = sys.exc_info()[1]
+ errstr = str(err)
+ if errstr.lower().startswith('no module named'):
+ whichmod = errstr[16:]
+ hint = ''
+ if whichmod.startswith('docutils'):
+ whichmod = 'Docutils library'
+ elif whichmod.startswith('jinja'):
+ whichmod = 'Jinja2 library'
+ elif whichmod == 'roman':
+ whichmod = 'roman module (which is distributed with Docutils)'
+ hint = ('This can happen if you upgraded docutils using\n'
+ 'easy_install without uninstalling the old version'
+ 'first.\n')
+ else:
+ whichmod += ' module'
+ sys.stderr.write('Error: The %s cannot be found. '
+ 'Did you install Sphinx and its dependencies '
+ 'correctly?\n' % whichmod)
+ if hint:
+ sys.stderr.write(hint)
+ return 1
+ raise
+ if sys.version_info[:3] >= (3, 3, 0):
+ from sphinx.util.compat import docutils_version
+ if docutils_version < (0, 10):
+ sys.stderr.write('Error: Sphinx requires at least '
+ 'Docutils 0.10 for Python 3.3 and above.\n')
+ return 1
+ return cmdline.main(argv)
+
+
+def make_main(argv=sys.argv):
+ """Sphinx build "make mode" entry."""
+ from sphinx import make_mode
+ return make_mode.run_make_mode(argv[2:])
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py
new file mode 100644
index 0000000..365efa7
--- /dev/null
+++ b/sphinx/addnodes.py
@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.addnodes
+ ~~~~~~~~~~~~~~~
+
+ Additional docutils nodes.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+
+class toctree(nodes.General, nodes.Element):
+ """Node for inserting a "TOC tree"."""
+
+
+# domain-specific object descriptions (class, function etc.)
+
+class desc(nodes.Admonition, nodes.Element):
+ """Node for object descriptions.
+
+ This node is similar to a "definition list" with one definition. It
+ contains one or more ``desc_signature`` and a ``desc_content``.
+ """
+
+class desc_signature(nodes.Part, nodes.Inline, nodes.TextElement):
+ """Node for object signatures.
+
+ The "term" part of the custom Sphinx definition list.
+ """
+
+
+# nodes to use within a desc_signature
+
+class desc_addname(nodes.Part, nodes.Inline, nodes.TextElement):
+ """Node for additional name parts (module name, class name)."""
+# compatibility alias
+desc_classname = desc_addname
+
+class desc_type(nodes.Part, nodes.Inline, nodes.TextElement):
+ """Node for return types or object type names."""
+
+class desc_returns(desc_type):
+ """Node for a "returns" annotation (a la -> in Python)."""
+ def astext(self):
+ return ' -> ' + nodes.TextElement.astext(self)
+
+class desc_name(nodes.Part, nodes.Inline, nodes.TextElement):
+ """Node for the main object name."""
+
+class desc_parameterlist(nodes.Part, nodes.Inline, nodes.TextElement):
+ """Node for a general parameter list."""
+ child_text_separator = ', '
+
+class desc_parameter(nodes.Part, nodes.Inline, nodes.TextElement):
+ """Node for a single parameter."""
+
+class desc_optional(nodes.Part, nodes.Inline, nodes.TextElement):
+ """Node for marking optional parts of the parameter list."""
+ child_text_separator = ', '
+ def astext(self):
+ return '[' + nodes.TextElement.astext(self) + ']'
+
+class desc_annotation(nodes.Part, nodes.Inline, nodes.TextElement):
+ """Node for signature annotations (not Python 3-style annotations)."""
+
+class desc_content(nodes.General, nodes.Element):
+ """Node for object description content.
+
+ This is the "definition" part of the custom Sphinx definition list.
+ """
+
+
+# new admonition-like constructs
+
+class versionmodified(nodes.Admonition, nodes.TextElement):
+ """Node for version change entries.
+
+ Currently used for "versionadded", "versionchanged" and "deprecated"
+ directives.
+ """
+
+class seealso(nodes.Admonition, nodes.Element):
+ """Custom "see also" admonition."""
+
+class productionlist(nodes.Admonition, nodes.Element):
+ """Node for grammar production lists.
+
+ Contains ``production`` nodes.
+ """
+
+class production(nodes.Part, nodes.Inline, nodes.TextElement):
+ """Node for a single grammar production rule."""
+
+
+# other directive-level nodes
+
+class index(nodes.Invisible, nodes.Inline, nodes.TextElement):
+ """Node for index entries.
+
+ This node is created by the ``index`` directive and has one attribute,
+ ``entries``. Its value is a list of 4-tuples of ``(entrytype, entryname,
+ target, ignored)``.
+
+ *entrytype* is one of "single", "pair", "double", "triple".
+ """
+
+class centered(nodes.Part, nodes.Element):
+ """Deprecated."""
+
+class acks(nodes.Element):
+ """Special node for "acks" lists."""
+
+class hlist(nodes.Element):
+ """Node for "horizontal lists", i.e. lists that should be compressed to
+ take up less vertical space.
+ """
+
+class hlistcol(nodes.Element):
+ """Node for one column in a horizontal list."""
+
+class compact_paragraph(nodes.paragraph):
+ """Node for a compact paragraph (which never makes a <p> node)."""
+
+class glossary(nodes.Element):
+ """Node to insert a glossary."""
+
+class only(nodes.Element):
+ """Node for "only" directives (conditional inclusion based on tags)."""
+
+
+# meta-information nodes
+
+class start_of_file(nodes.Element):
+ """Node to mark start of a new file, used in the LaTeX builder only."""
+
+class highlightlang(nodes.Element):
+ """Inserted to set the highlight language and line number options for
+ subsequent code blocks.
+ """
+
+class tabular_col_spec(nodes.Element):
+ """Node for specifying tabular columns, used for LaTeX output."""
+
+class meta(nodes.Special, nodes.PreBibliographic, nodes.Element):
+ """Node for meta directive -- same as docutils' standard meta node,
+ but pickleable.
+ """
+
+
+# inline nodes
+
+class pending_xref(nodes.Inline, nodes.Element):
+ """Node for cross-references that cannot be resolved without complete
+ information about all documents.
+
+ These nodes are resolved before writing output, in
+ BuildEnvironment.resolve_references.
+ """
+
+class download_reference(nodes.reference):
+ """Node for download references, similar to pending_xref."""
+
+class literal_emphasis(nodes.emphasis):
+ """Node that behaves like `emphasis`, but further text processors are not
+ applied (e.g. smartypants for HTML output).
+ """
+
+class abbreviation(nodes.Inline, nodes.TextElement):
+ """Node for abbreviations with explanations."""
+
+class termsep(nodes.Structural, nodes.Element):
+ """Separates two terms within a <term> node."""
+
+
+# make the new nodes known to docutils; needed because the HTML writer will
+# choke at some point if these are not added
+nodes._add_node_class_names(k for k in globals().keys()
+ if k != 'nodes' and k[0] != '_')
diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py
new file mode 100644
index 0000000..755ea5e
--- /dev/null
+++ b/sphinx/apidoc.py
@@ -0,0 +1,363 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.apidoc
+ ~~~~~~~~~~~~~
+
+ Parses a directory tree looking for Python modules and packages and creates
+ ReST files appropriately to create code documentation with Sphinx. It also
+ creates a modules index (named modules.<suffix>).
+
+ This is derived from the "sphinx-autopackage" script, which is:
+ Copyright 2008 Société des arts technologiques (SAT),
+ http://www.sat.qc.ca/
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import os
+import sys
+import optparse
+from os import path
+
+from sphinx.util.osutil import walk
+from sphinx import __version__
+
+# automodule options
+if 'SPHINX_APIDOC_OPTIONS' in os.environ:
+ OPTIONS = os.environ['SPHINX_APIDOC_OPTIONS'].split(',')
+else:
+ OPTIONS = [
+ 'members',
+ 'undoc-members',
+ # 'inherited-members', # disabled because there's a bug in sphinx
+ 'show-inheritance',
+ ]
+
+INITPY = '__init__.py'
+PY_SUFFIXES = set(['.py', '.pyx'])
+
+
+def makename(package, module):
+ """Join package and module with a dot."""
+ # Both package and module can be None/empty.
+ if package:
+ name = package
+ if module:
+ name += '.' + module
+ else:
+ name = module
+ return name
+
+
+def write_file(name, text, opts):
+ """Write the output file for module/package <name>."""
+ fname = path.join(opts.destdir, '%s.%s' % (name, opts.suffix))
+ if opts.dryrun:
+ print 'Would create file %s.' % fname
+ return
+ if not opts.force and path.isfile(fname):
+ print 'File %s already exists, skipping.' % fname
+ else:
+ print 'Creating file %s.' % fname
+ f = open(fname, 'w')
+ try:
+ f.write(text)
+ finally:
+ f.close()
+
+
+def format_heading(level, text):
+ """Create a heading of <level> [1, 2 or 3 supported]."""
+ underlining = ['=', '-', '~', ][level - 1] * len(text)
+ return '%s\n%s\n\n' % (text, underlining)
+
+
+def format_directive(module, package=None):
+ """Create the automodule directive and add the options."""
+ directive = '.. automodule:: %s\n' % makename(package, module)
+ for option in OPTIONS:
+ directive += ' :%s:\n' % option
+ return directive
+
+
+def create_module_file(package, module, opts):
+ """Build the text of the file and write the file."""
+ if not opts.noheadings:
+ text = format_heading(1, '%s module' % module)
+ else:
+ text = ''
+ #text += format_heading(2, ':mod:`%s` Module' % module)
+ text += format_directive(module, package)
+ write_file(makename(package, module), text, opts)
+
+
+def create_package_file(root, master_package, subroot, py_files, opts, subs):
+ """Build the text of the file and write the file."""
+ text = format_heading(1, '%s package' % makename(master_package, subroot))
+
+ # build a list of directories that are szvpackages (contain an INITPY file)
+ subs = [sub for sub in subs if path.isfile(path.join(root, sub, INITPY))]
+ # if there are some package directories, add a TOC for theses subpackages
+ if subs:
+ text += format_heading(2, 'Subpackages')
+ text += '.. toctree::\n\n'
+ for sub in subs:
+ text += ' %s.%s\n' % (makename(master_package, subroot), sub)
+ text += '\n'
+
+ submods = [path.splitext(sub)[0] for sub in py_files
+ if not shall_skip(path.join(root, sub), opts)
+ and sub != INITPY]
+ if submods:
+ text += format_heading(2, 'Submodules')
+ if opts.separatemodules:
+ text += '.. toctree::\n\n'
+ for submod in submods:
+ modfile = makename(master_package, makename(subroot, submod))
+ text += ' %s\n' % modfile
+
+ # generate separate file for this module
+ if not opts.noheadings:
+ filetext = format_heading(1, '%s module' % modfile)
+ else:
+ filetext = ''
+ filetext += format_directive(makename(subroot, submod),
+ master_package)
+ write_file(modfile, filetext, opts)
+ else:
+ for submod in submods:
+ modfile = makename(master_package, makename(subroot, submod))
+ if not opts.noheadings:
+ text += format_heading(2, '%s module' % modfile)
+ text += format_directive(makename(subroot, submod),
+ master_package)
+ text += '\n'
+ text += '\n'
+
+ text += format_heading(2, 'Module contents')
+ text += format_directive(subroot, master_package)
+
+ write_file(makename(master_package, subroot), text, opts)
+
+
+def create_modules_toc_file(modules, opts, name='modules'):
+ """Create the module's index."""
+ text = format_heading(1, '%s' % opts.header)
+ text += '.. toctree::\n'
+ text += ' :maxdepth: %s\n\n' % opts.maxdepth
+
+ modules.sort()
+ prev_module = ''
+ for module in modules:
+ # look if the module is a subpackage and, if yes, ignore it
+ if module.startswith(prev_module + '.'):
+ continue
+ prev_module = module
+ text += ' %s\n' % module
+
+ write_file(name, text, opts)
+
+
+def shall_skip(module, opts):
+ """Check if we want to skip this module."""
+ # skip it if there is nothing (or just \n or \r\n) in the file
+ if path.getsize(module) <= 2:
+ return True
+ # skip if it has a "private" name and this is selected
+ filename = path.basename(module)
+ if filename != '__init__.py' and filename.startswith('_') and \
+ not opts.includeprivate:
+ return True
+ return False
+
+
+def recurse_tree(rootpath, excludes, opts):
+ """
+ Look for every file in the directory tree and create the corresponding
+ ReST files.
+ """
+ # check if the base directory is a package and get its name
+ if INITPY in os.listdir(rootpath):
+ root_package = rootpath.split(path.sep)[-1]
+ else:
+ # otherwise, the base is a directory with packages
+ root_package = None
+
+ toplevels = []
+ followlinks = getattr(opts, 'followlinks', False)
+ includeprivate = getattr(opts, 'includeprivate', False)
+ for root, subs, files in walk(rootpath, followlinks=followlinks):
+ # document only Python module files (that aren't excluded)
+ py_files = sorted(f for f in files
+ if path.splitext(f)[1] in PY_SUFFIXES and
+ not is_excluded(path.join(root, f), excludes))
+ is_pkg = INITPY in py_files
+ if is_pkg:
+ py_files.remove(INITPY)
+ py_files.insert(0, INITPY)
+ elif root != rootpath:
+ # only accept non-package at toplevel
+ del subs[:]
+ continue
+ # remove hidden ('.') and private ('_') directories, as well as
+ # excluded dirs
+ if includeprivate:
+ exclude_prefixes = ('.',)
+ else:
+ exclude_prefixes = ('.', '_')
+ subs[:] = sorted(sub for sub in subs if not sub.startswith(exclude_prefixes)
+ and not is_excluded(path.join(root, sub), excludes))
+
+ if is_pkg:
+ # we are in a package with something to document
+ if subs or len(py_files) > 1 or not \
+ shall_skip(path.join(root, INITPY), opts):
+ subpackage = root[len(rootpath):].lstrip(path.sep).\
+ replace(path.sep, '.')
+ create_package_file(root, root_package, subpackage,
+ py_files, opts, subs)
+ toplevels.append(makename(root_package, subpackage))
+ else:
+ # if we are at the root level, we don't require it to be a package
+ assert root == rootpath and root_package is None
+ for py_file in py_files:
+ if not shall_skip(path.join(rootpath, py_file), opts):
+ module = path.splitext(py_file)[0]
+ create_module_file(root_package, module, opts)
+ toplevels.append(module)
+
+ return toplevels
+
+
+def normalize_excludes(rootpath, excludes):
+ """Normalize the excluded directory list."""
+ return [path.normpath(path.abspath(exclude)) for exclude in excludes]
+
+
+def is_excluded(root, excludes):
+ """Check if the directory is in the exclude list.
+
+ Note: by having trailing slashes, we avoid common prefix issues, like
+ e.g. an exlude "foo" also accidentally excluding "foobar".
+ """
+ root = path.normpath(root)
+ for exclude in excludes:
+ if root == exclude:
+ return True
+ return False
+
+
+def main(argv=sys.argv):
+ """Parse and check the command line arguments."""
+ parser = optparse.OptionParser(
+ usage="""\
+usage: %prog [options] -o <output_path> <module_path> [exclude_path, ...]
+
+Look recursively in <module_path> for Python modules and packages and create
+one reST file with automodule directives per package in the <output_path>.
+
+The <exclude_path>s can be files and/or directories that will be excluded
+from generation.
+
+Note: By default this script will not overwrite already created files.""")
+
+ parser.add_option('-o', '--output-dir', action='store', dest='destdir',
+ help='Directory to place all output', default='')
+ parser.add_option('-d', '--maxdepth', action='store', dest='maxdepth',
+ help='Maximum depth of submodules to show in the TOC '
+ '(default: 4)', type='int', default=4)
+ parser.add_option('-f', '--force', action='store_true', dest='force',
+ help='Overwrite existing files')
+ parser.add_option('-l', '--follow-links', action='store_true',
+ dest='followlinks', default=False,
+ help='Follow symbolic links. Powerful when combined '
+ 'with collective.recipe.omelette.')
+ parser.add_option('-n', '--dry-run', action='store_true', dest='dryrun',
+ help='Run the script without creating files')
+ parser.add_option('-e', '--separate', action='store_true',
+ dest='separatemodules',
+ help='Put documentation for each module on its own page')
+ parser.add_option('-P', '--private', action='store_true',
+ dest='includeprivate',
+ help='Include "_private" modules')
+ parser.add_option('-T', '--no-toc', action='store_true', dest='notoc',
+ help='Don\'t create a table of contents file')
+ parser.add_option('-E', '--no-headings', action='store_true',
+ dest='noheadings',
+ help='Don\'t create headings for the module/package '
+ 'packages (e.g. when the docstrings already contain '
+ 'them)')
+ parser.add_option('-s', '--suffix', action='store', dest='suffix',
+ help='file suffix (default: rst)', default='rst')
+ parser.add_option('-F', '--full', action='store_true', dest='full',
+ help='Generate a full project with sphinx-quickstart')
+ parser.add_option('-H', '--doc-project', action='store', dest='header',
+ help='Project name (default: root module name)')
+ parser.add_option('-A', '--doc-author', action='store', dest='author',
+ type='str',
+ help='Project author(s), used when --full is given')
+ parser.add_option('-V', '--doc-version', action='store', dest='version',
+ help='Project version, used when --full is given')
+ parser.add_option('-R', '--doc-release', action='store', dest='release',
+ help='Project release, used when --full is given, '
+ 'defaults to --doc-version')
+ parser.add_option('--version', action='store_true', dest='show_version',
+ help='Show version information and exit')
+
+ (opts, args) = parser.parse_args(argv[1:])
+
+ if opts.show_version:
+ print 'Sphinx (sphinx-apidoc) %s' % __version__
+ return 0
+
+ if not args:
+ parser.error('A package path is required.')
+
+ rootpath, excludes = args[0], args[1:]
+ if not opts.destdir:
+ parser.error('An output directory is required.')
+ if opts.header is None:
+ opts.header = path.normpath(rootpath).split(path.sep)[-1]
+ if opts.suffix.startswith('.'):
+ opts.suffix = opts.suffix[1:]
+ if not path.isdir(rootpath):
+ print >>sys.stderr, '%s is not a directory.' % rootpath
+ sys.exit(1)
+ if not path.isdir(opts.destdir):
+ if not opts.dryrun:
+ os.makedirs(opts.destdir)
+ rootpath = path.normpath(path.abspath(rootpath))
+ excludes = normalize_excludes(rootpath, excludes)
+ modules = recurse_tree(rootpath, excludes, opts)
+ if opts.full:
+ from sphinx import quickstart as qs
+ modules.sort()
+ prev_module = ''
+ text = ''
+ for module in modules:
+ if module.startswith(prev_module + '.'):
+ continue
+ prev_module = module
+ text += ' %s\n' % module
+ d = dict(
+ path = opts.destdir,
+ sep = False,
+ dot = '_',
+ project = opts.header,
+ author = opts.author or 'Author',
+ version = opts.version or '',
+ release = opts.release or opts.version or '',
+ suffix = '.' + opts.suffix,
+ master = 'index',
+ epub = True,
+ ext_autodoc = True,
+ ext_viewcode = True,
+ makefile = True,
+ batchfile = True,
+ mastertocmaxdepth = opts.maxdepth,
+ mastertoctree = text,
+ )
+ if not opts.dryrun:
+ qs.generate(d, silent=True, overwrite=opts.force)
+ elif not opts.notoc:
+ create_modules_toc_file(modules, opts)
diff --git a/sphinx/application.py b/sphinx/application.py
new file mode 100644
index 0000000..4fb9eb3
--- /dev/null
+++ b/sphinx/application.py
@@ -0,0 +1,656 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.application
+ ~~~~~~~~~~~~~~~~~~
+
+ Sphinx application object.
+
+ Gracefully adapted from the TextPress system by Armin.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import sys
+import types
+import posixpath
+from os import path
+from cStringIO import StringIO
+
+from docutils import nodes
+from docutils.parsers.rst import convert_directive_function, \
+ directives, roles
+
+import sphinx
+from sphinx import package_dir, locale
+from sphinx.roles import XRefRole
+from sphinx.config import Config
+from sphinx.errors import SphinxError, SphinxWarning, ExtensionError, \
+ VersionRequirementError, ConfigError
+from sphinx.domains import ObjType, BUILTIN_DOMAINS
+from sphinx.domains.std import GenericObject, Target, StandardDomain
+from sphinx.builders import BUILTIN_BUILDERS
+from sphinx.environment import BuildEnvironment, SphinxStandaloneReader
+from sphinx.util import pycompat # imported for side-effects
+from sphinx.util.tags import Tags
+from sphinx.util.osutil import ENOENT
+from sphinx.util.console import bold, lightgray, darkgray
+
+
+# List of all known core events. Maps name to arguments description.
+events = {
+ 'builder-inited': '',
+ 'env-get-outdated': 'env, added, changed, removed',
+ 'env-purge-doc': 'env, docname',
+ 'source-read': 'docname, source text',
+ 'doctree-read': 'the doctree before being pickled',
+ 'missing-reference': 'env, node, contnode',
+ 'doctree-resolved': 'doctree, docname',
+ 'env-updated': 'env',
+ 'html-collect-pages': 'builder',
+ 'html-page-context': 'pagename, context, doctree or None',
+ 'build-finished': 'exception',
+}
+
+CONFIG_FILENAME = 'conf.py'
+ENV_PICKLE_FILENAME = 'environment.pickle'
+
+
+class Sphinx(object):
+
+ def __init__(self, srcdir, confdir, outdir, doctreedir, buildername,
+ confoverrides=None, status=sys.stdout, warning=sys.stderr,
+ freshenv=False, warningiserror=False, tags=None, verbosity=0,
+ parallel=0):
+ self.verbosity = verbosity
+ self.next_listener_id = 0
+ self._extensions = {}
+ self._listeners = {}
+ self.domains = BUILTIN_DOMAINS.copy()
+ self.builderclasses = BUILTIN_BUILDERS.copy()
+ self.builder = None
+ self.env = None
+
+ self.srcdir = srcdir
+ self.confdir = confdir
+ self.outdir = outdir
+ self.doctreedir = doctreedir
+
+ self.parallel = parallel
+
+ if status is None:
+ self._status = StringIO()
+ self.quiet = True
+ else:
+ self._status = status
+ self.quiet = False
+
+ if warning is None:
+ self._warning = StringIO()
+ else:
+ self._warning = warning
+ self._warncount = 0
+ self.warningiserror = warningiserror
+
+ self._events = events.copy()
+
+ # say hello to the world
+ self.info(bold('Running Sphinx v%s' % sphinx.__version__))
+
+ # status code for command-line application
+ self.statuscode = 0
+
+ # read config
+ self.tags = Tags(tags)
+ self.config = Config(confdir, CONFIG_FILENAME,
+ confoverrides or {}, self.tags)
+ self.config.check_unicode(self.warn)
+
+ # set confdir to srcdir if -C given (!= no confdir); a few pieces
+ # of code expect a confdir to be set
+ if self.confdir is None:
+ self.confdir = self.srcdir
+
+ # backwards compatibility: activate old C markup
+ self.setup_extension('sphinx.ext.oldcmarkup')
+ # load all user-given extension modules
+ for extension in self.config.extensions:
+ self.setup_extension(extension)
+ # the config file itself can be an extension
+ if self.config.setup:
+ # py31 doesn't have 'callable' function for bellow check
+ if hasattr(self.config.setup, '__call__'):
+ self.config.setup(self)
+ else:
+ raise ConfigError(
+ "'setup' that is specified in the conf.py has not been " +
+ "callable. Please provide a callable `setup` function " +
+ "in order to behave as a sphinx extension conf.py itself."
+ )
+
+ # now that we know all config values, collect them from conf.py
+ self.config.init_values()
+
+ # check the Sphinx version if requested
+ if self.config.needs_sphinx and \
+ self.config.needs_sphinx > sphinx.__version__[:3]:
+ raise VersionRequirementError(
+ 'This project needs at least Sphinx v%s and therefore cannot '
+ 'be built with this version.' % self.config.needs_sphinx)
+
+ # set up translation infrastructure
+ self._init_i18n()
+ # set up the build environment
+ self._init_env(freshenv)
+ # set up the builder
+ self._init_builder(buildername)
+
+ def _init_i18n(self):
+ """Load translated strings from the configured localedirs if enabled in
+ the configuration.
+ """
+ if self.config.language is not None:
+ self.info(bold('loading translations [%s]... ' %
+ self.config.language), nonl=True)
+ locale_dirs = [None, path.join(package_dir, 'locale')] + \
+ [path.join(self.srcdir, x) for x in self.config.locale_dirs]
+ else:
+ locale_dirs = []
+ self.translator, has_translation = locale.init(locale_dirs,
+ self.config.language)
+ if self.config.language is not None:
+ if has_translation or self.config.language == 'en':
+ # "en" never needs to be translated
+ self.info('done')
+ else:
+ self.info('not available for built-in messages')
+
+ def _init_env(self, freshenv):
+ if freshenv:
+ self.env = BuildEnvironment(self.srcdir, self.doctreedir,
+ self.config)
+ self.env.find_files(self.config)
+ for domain in self.domains.keys():
+ self.env.domains[domain] = self.domains[domain](self.env)
+ else:
+ try:
+ self.info(bold('loading pickled environment... '), nonl=True)
+ self.env = BuildEnvironment.frompickle(self.config,
+ path.join(self.doctreedir, ENV_PICKLE_FILENAME))
+ self.env.domains = {}
+ for domain in self.domains.keys():
+ # this can raise if the data version doesn't fit
+ self.env.domains[domain] = self.domains[domain](self.env)
+ self.info('done')
+ except Exception, err:
+ if type(err) is IOError and err.errno == ENOENT:
+ self.info('not yet created')
+ else:
+ self.info('failed: %s' % err)
+ return self._init_env(freshenv=True)
+
+ self.env.set_warnfunc(self.warn)
+
+ def _init_builder(self, buildername):
+ if buildername is None:
+ print >>self._status, 'No builder selected, using default: html'
+ buildername = 'html'
+ if buildername not in self.builderclasses:
+ raise SphinxError('Builder name %s not registered' % buildername)
+
+ builderclass = self.builderclasses[buildername]
+ if isinstance(builderclass, tuple):
+ # builtin builder
+ mod, cls = builderclass
+ builderclass = getattr(
+ __import__('sphinx.builders.' + mod, None, None, [cls]), cls)
+ self.builder = builderclass(self)
+ self.emit('builder-inited')
+
+ # ---- main "build" method -------------------------------------------------
+
+ def build(self, force_all=False, filenames=None):
+ try:
+ if force_all:
+ self.builder.build_all()
+ elif filenames:
+ self.builder.build_specific(filenames)
+ else:
+ self.builder.build_update()
+ except Exception, err:
+ # delete the saved env to force a fresh build next time
+ envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
+ if path.isfile(envfile):
+ os.unlink(envfile)
+ self.emit('build-finished', err)
+ raise
+ else:
+ self.emit('build-finished', None)
+ self.builder.cleanup()
+
+ # ---- logging handling ----------------------------------------------------
+
+ def _log(self, message, wfile, nonl=False):
+ try:
+ wfile.write(message)
+ except UnicodeEncodeError:
+ encoding = getattr(wfile, 'encoding', 'ascii') or 'ascii'
+ wfile.write(message.encode(encoding, 'replace'))
+ if not nonl:
+ wfile.write('\n')
+ if hasattr(wfile, 'flush'):
+ wfile.flush()
+
+ def warn(self, message, location=None, prefix='WARNING: '):
+ """Emit a warning.
+
+ If *location* is given, it should either be a tuple of (docname, lineno)
+ or a string describing the location of the warning as well as possible.
+
+ *prefix* usually should not be changed.
+
+ .. note::
+
+ For warnings emitted during parsing, you should use
+ :meth:`.BuildEnvironment.warn` since that will collect all
+ warnings during parsing for later output.
+ """
+ if isinstance(location, tuple):
+ docname, lineno = location
+ if docname:
+ location = '%s:%s' % (self.env.doc2path(docname), lineno or '')
+ else:
+ location = None
+ warntext = location and '%s: %s%s\n' % (location, prefix, message) or \
+ '%s%s\n' % (prefix, message)
+ if self.warningiserror:
+ raise SphinxWarning(warntext)
+ self._warncount += 1
+ self._log(warntext, self._warning, True)
+
+ def info(self, message='', nonl=False):
+ """Emit an informational message.
+
+ If *nonl* is true, don't emit a newline at the end (which implies that
+ more info output will follow soon.)
+ """
+ self._log(message, self._status, nonl)
+
+ def verbose(self, message, *args, **kwargs):
+ """Emit a verbose informational message.
+
+ The message will only be emitted for verbosity levels >= 1 (i.e. at
+ least one ``-v`` option was given).
+
+ The message can contain %-style interpolation placeholders, which is
+ formatted with either the ``*args`` or ``**kwargs`` when output.
+ """
+ if self.verbosity < 1:
+ return
+ if args or kwargs:
+ message = message % (args or kwargs)
+ self._log(message, self._status)
+
+ def debug(self, message, *args, **kwargs):
+ """Emit a debug-level informational message.
+
+ The message will only be emitted for verbosity levels >= 2 (i.e. at
+ least two ``-v`` options were given).
+
+ The message can contain %-style interpolation placeholders, which is
+ formatted with either the ``*args`` or ``**kwargs`` when output.
+ """
+ if self.verbosity < 2:
+ return
+ if args or kwargs:
+ message = message % (args or kwargs)
+ self._log(darkgray(message), self._status)
+
+ def debug2(self, message, *args, **kwargs):
+ """Emit a lowlevel debug-level informational message.
+
+ The message will only be emitted for verbosity level 3 (i.e. three
+ ``-v`` options were given).
+
+ The message can contain %-style interpolation placeholders, which is
+ formatted with either the ``*args`` or ``**kwargs`` when output.
+ """
+ if self.verbosity < 3:
+ return
+ if args or kwargs:
+ message = message % (args or kwargs)
+ self._log(lightgray(message), self._status)
+
+ # ---- general extensibility interface -------------------------------------
+
+ def setup_extension(self, extension):
+ """Import and setup a Sphinx extension module. No-op if called twice."""
+ self.debug('[app] setting up extension: %r', extension)
+ if extension in self._extensions:
+ return
+ try:
+ mod = __import__(extension, None, None, ['setup'])
+ except ImportError, err:
+ raise ExtensionError('Could not import extension %s' % extension,
+ err)
+ if not hasattr(mod, 'setup'):
+ self.warn('extension %r has no setup() function; is it really '
+ 'a Sphinx extension module?' % extension)
+ else:
+ try:
+ mod.setup(self)
+ except VersionRequirementError, err:
+ # add the extension name to the version required
+ raise VersionRequirementError(
+ 'The %s extension used by this project needs at least '
+ 'Sphinx v%s; it therefore cannot be built with this '
+ 'version.' % (extension, err))
+ self._extensions[extension] = mod
+
+ def require_sphinx(self, version):
+ # check the Sphinx version if requested
+ if version > sphinx.__version__[:3]:
+ raise VersionRequirementError(version)
+
+ def import_object(self, objname, source=None):
+ """Import an object from a 'module.name' string."""
+ try:
+ module, name = objname.rsplit('.', 1)
+ except ValueError, err:
+ raise ExtensionError('Invalid full object name %s' % objname +
+ (source and ' (needed for %s)' % source or ''),
+ err)
+ try:
+ return getattr(__import__(module, None, None, [name]), name)
+ except ImportError, err:
+ raise ExtensionError('Could not import %s' % module +
+ (source and ' (needed for %s)' % source or ''),
+ err)
+ except AttributeError, err:
+ raise ExtensionError('Could not find %s' % objname +
+ (source and ' (needed for %s)' % source or ''),
+ err)
+
+ # event interface
+
+ def _validate_event(self, event):
+ event = intern(event)
+ if event not in self._events:
+ raise ExtensionError('Unknown event name: %s' % event)
+
+ def connect(self, event, callback):
+ self._validate_event(event)
+ listener_id = self.next_listener_id
+ if event not in self._listeners:
+ self._listeners[event] = {listener_id: callback}
+ else:
+ self._listeners[event][listener_id] = callback
+ self.next_listener_id += 1
+ self.debug('[app] connecting event %r: %r [id=%s]',
+ event, callback, listener_id)
+ return listener_id
+
+ def disconnect(self, listener_id):
+ self.debug('[app] disconnecting event: [id=%s]', listener_id)
+ for event in self._listeners.itervalues():
+ event.pop(listener_id, None)
+
+ def emit(self, event, *args):
+ try:
+ self.debug2('[app] emitting event: %r%s', event, repr(args)[:100])
+ except Exception: # not every object likes to be repr()'d (think
+ # random stuff coming via autodoc)
+ pass
+ results = []
+ if event in self._listeners:
+ for _, callback in self._listeners[event].iteritems():
+ results.append(callback(self, *args))
+ return results
+
+ def emit_firstresult(self, event, *args):
+ for result in self.emit(event, *args):
+ if result is not None:
+ return result
+ return None
+
+ # registering addon parts
+
+ def add_builder(self, builder):
+ self.debug('[app] adding builder: %r', builder)
+ if not hasattr(builder, 'name'):
+ raise ExtensionError('Builder class %s has no "name" attribute'
+ % builder)
+ if builder.name in self.builderclasses:
+ if isinstance(self.builderclasses[builder.name], tuple):
+ raise ExtensionError('Builder %r is a builtin builder' %
+ builder.name)
+ else:
+ raise ExtensionError(
+ 'Builder %r already exists (in module %s)' % (
+ builder.name, self.builderclasses[builder.name].__module__))
+ self.builderclasses[builder.name] = builder
+
+ def add_config_value(self, name, default, rebuild):
+ self.debug('[app] adding config value: %r', (name, default, rebuild))
+ if name in self.config.values:
+ raise ExtensionError('Config value %r already present' % name)
+ if rebuild in (False, True):
+ rebuild = rebuild and 'env' or ''
+ self.config.values[name] = (default, rebuild)
+
+ def add_event(self, name):
+ self.debug('[app] adding event: %r', name)
+ if name in self._events:
+ raise ExtensionError('Event %r already present' % name)
+ self._events[name] = ''
+
+ def add_node(self, node, **kwds):
+ self.debug('[app] adding node: %r', (node, kwds))
+ nodes._add_node_class_names([node.__name__])
+ for key, val in kwds.iteritems():
+ try:
+ visit, depart = val
+ except ValueError:
+ raise ExtensionError('Value for key %r must be a '
+ '(visit, depart) function tuple' % key)
+ if key == 'html':
+ from sphinx.writers.html import HTMLTranslator as translator
+ elif key == 'latex':
+ from sphinx.writers.latex import LaTeXTranslator as translator
+ elif key == 'text':
+ from sphinx.writers.text import TextTranslator as translator
+ elif key == 'man':
+ from sphinx.writers.manpage import ManualPageTranslator \
+ as translator
+ elif key == 'texinfo':
+ from sphinx.writers.texinfo import TexinfoTranslator \
+ as translator
+ else:
+ # ignore invalid keys for compatibility
+ continue
+ setattr(translator, 'visit_'+node.__name__, visit)
+ if depart:
+ setattr(translator, 'depart_'+node.__name__, depart)
+
+ def _directive_helper(self, obj, content=None, arguments=None, **options):
+ if isinstance(obj, (types.FunctionType, types.MethodType)):
+ obj.content = content
+ obj.arguments = arguments or (0, 0, False)
+ obj.options = options
+ return convert_directive_function(obj)
+ else:
+ if content or arguments or options:
+ raise ExtensionError('when adding directive classes, no '
+ 'additional arguments may be given')
+ return obj
+
+ def add_directive(self, name, obj, content=None, arguments=None, **options):
+ self.debug('[app] adding directive: %r',
+ (name, obj, content, arguments, options))
+ directives.register_directive(
+ name, self._directive_helper(obj, content, arguments, **options))
+
+ def add_role(self, name, role):
+ self.debug('[app] adding role: %r', (name, role))
+ roles.register_local_role(name, role)
+
+ def add_generic_role(self, name, nodeclass):
+ # don't use roles.register_generic_role because it uses
+ # register_canonical_role
+ self.debug('[app] adding generic role: %r', (name, nodeclass))
+ role = roles.GenericRole(name, nodeclass)
+ roles.register_local_role(name, role)
+
+ def add_domain(self, domain):
+ self.debug('[app] adding domain: %r', domain)
+ if domain.name in self.domains:
+ raise ExtensionError('domain %s already registered' % domain.name)
+ self.domains[domain.name] = domain
+
+ def override_domain(self, domain):
+ self.debug('[app] overriding domain: %r', domain)
+ if domain.name not in self.domains:
+ raise ExtensionError('domain %s not yet registered' % domain.name)
+ if not issubclass(domain, self.domains[domain.name]):
+ raise ExtensionError('new domain not a subclass of registered %s '
+ 'domain' % domain.name)
+ self.domains[domain.name] = domain
+
+ def add_directive_to_domain(self, domain, name, obj,
+ content=None, arguments=None, **options):
+ self.debug('[app] adding directive to domain: %r',
+ (domain, name, obj, content, arguments, options))
+ if domain not in self.domains:
+ raise ExtensionError('domain %s not yet registered' % domain)
+ self.domains[domain].directives[name] = \
+ self._directive_helper(obj, content, arguments, **options)
+
+ def add_role_to_domain(self, domain, name, role):
+ self.debug('[app] adding role to domain: %r', (domain, name, role))
+ if domain not in self.domains:
+ raise ExtensionError('domain %s not yet registered' % domain)
+ self.domains[domain].roles[name] = role
+
+ def add_index_to_domain(self, domain, index):
+ self.debug('[app] adding index to domain: %r', (domain, index))
+ if domain not in self.domains:
+ raise ExtensionError('domain %s not yet registered' % domain)
+ self.domains[domain].indices.append(index)
+
+ def add_object_type(self, directivename, rolename, indextemplate='',
+ parse_node=None, ref_nodeclass=None, objname='',
+ doc_field_types=[]):
+ self.debug('[app] adding object type: %r',
+ (directivename, rolename, indextemplate, parse_node,
+ ref_nodeclass, objname, doc_field_types))
+ StandardDomain.object_types[directivename] = \
+ ObjType(objname or directivename, rolename)
+ # create a subclass of GenericObject as the new directive
+ new_directive = type(directivename, (GenericObject, object),
+ {'indextemplate': indextemplate,
+ 'parse_node': staticmethod(parse_node),
+ 'doc_field_types': doc_field_types})
+ StandardDomain.directives[directivename] = new_directive
+ # XXX support more options?
+ StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
+
+ # backwards compatible alias
+ add_description_unit = add_object_type
+
+ def add_crossref_type(self, directivename, rolename, indextemplate='',
+ ref_nodeclass=None, objname=''):
+ self.debug('[app] adding crossref type: %r',
+ (directivename, rolename, indextemplate, ref_nodeclass,
+ objname))
+ StandardDomain.object_types[directivename] = \
+ ObjType(objname or directivename, rolename)
+ # create a subclass of Target as the new directive
+ new_directive = type(directivename, (Target, object),
+ {'indextemplate': indextemplate})
+ StandardDomain.directives[directivename] = new_directive
+ # XXX support more options?
+ StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
+
+ def add_transform(self, transform):
+ self.debug('[app] adding transform: %r', transform)
+ SphinxStandaloneReader.transforms.append(transform)
+
+ def add_javascript(self, filename):
+ self.debug('[app] adding javascript: %r', filename)
+ from sphinx.builders.html import StandaloneHTMLBuilder
+ if '://' in filename:
+ StandaloneHTMLBuilder.script_files.append(filename)
+ else:
+ StandaloneHTMLBuilder.script_files.append(
+ posixpath.join('_static', filename))
+
+ def add_stylesheet(self, filename):
+ self.debug('[app] adding stylesheet: %r', filename)
+ from sphinx.builders.html import StandaloneHTMLBuilder
+ if '://' in filename:
+ StandaloneHTMLBuilder.css_files.append(filename)
+ else:
+ StandaloneHTMLBuilder.css_files.append(
+ posixpath.join('_static', filename))
+
+ def add_lexer(self, alias, lexer):
+ self.debug('[app] adding lexer: %r', (alias, lexer))
+ from sphinx.highlighting import lexers
+ if lexers is None:
+ return
+ lexers[alias] = lexer
+
+ def add_autodocumenter(self, cls):
+ self.debug('[app] adding autodocumenter: %r', cls)
+ from sphinx.ext import autodoc
+ autodoc.add_documenter(cls)
+ self.add_directive('auto' + cls.objtype, autodoc.AutoDirective)
+
+ def add_autodoc_attrgetter(self, type, getter):
+ self.debug('[app] adding autodoc attrgetter: %r', (type, getter))
+ from sphinx.ext import autodoc
+ autodoc.AutoDirective._special_attrgetters[type] = getter
+
+ def add_search_language(self, cls):
+ self.debug('[app] adding search language: %r', cls)
+ from sphinx.search import languages, SearchLanguage
+ assert isinstance(cls, SearchLanguage)
+ languages[cls.lang] = cls
+
+
+class TemplateBridge(object):
+ """
+ This class defines the interface for a "template bridge", that is, a class
+ that renders templates given a template name and a context.
+ """
+
+ def init(self, builder, theme=None, dirs=None):
+ """Called by the builder to initialize the template system.
+
+ *builder* is the builder object; you'll probably want to look at the
+ value of ``builder.config.templates_path``.
+
+ *theme* is a :class:`sphinx.theming.Theme` object or None; in the latter
+ case, *dirs* can be list of fixed directories to look for templates.
+ """
+ raise NotImplementedError('must be implemented in subclasses')
+
+ def newest_template_mtime(self):
+ """Called by the builder to determine if output files are outdated
+ because of template changes. Return the mtime of the newest template
+ file that was changed. The default implementation returns ``0``.
+ """
+ return 0
+
+ def render(self, template, context):
+ """Called by the builder to render a template given as a filename with
+ a specified context (a Python dictionary).
+ """
+ raise NotImplementedError('must be implemented in subclasses')
+
+ def render_string(self, template, context):
+ """Called by the builder to render a template given as a string with a
+ specified context (a Python dictionary).
+ """
+ raise NotImplementedError('must be implemented in subclasses')
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py
new file mode 100644
index 0000000..44c76fa
--- /dev/null
+++ b/sphinx/builders/__init__.py
@@ -0,0 +1,459 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders
+ ~~~~~~~~~~~~~~~
+
+ Builder superclass for all builders.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+from os import path
+
+try:
+ import multiprocessing
+ import threading
+except ImportError:
+ multiprocessing = threading = None
+
+from docutils import nodes
+
+from sphinx.util.osutil import SEP, relative_uri
+from sphinx.util.console import bold, purple, darkgreen, term_width_line
+
+# side effect: registers roles and directives
+from sphinx import roles
+from sphinx import directives
+
+
+class Builder(object):
+ """
+ Builds target formats from the reST sources.
+ """
+
+ # builder's name, for the -b command line options
+ name = ''
+ # builder's output format, or '' if no document output is produced
+ format = ''
+ # doctree versioning method
+ versioning_method = 'none'
+ # allow parallel write_doc() calls
+ allow_parallel = False
+
+ def __init__(self, app):
+ self.env = app.env
+ self.env.set_versioning_method(self.versioning_method)
+ self.srcdir = app.srcdir
+ self.confdir = app.confdir
+ self.outdir = app.outdir
+ self.doctreedir = app.doctreedir
+ if not path.isdir(self.doctreedir):
+ os.makedirs(self.doctreedir)
+
+ self.app = app
+ self.warn = app.warn
+ self.info = app.info
+ self.config = app.config
+ self.tags = app.tags
+ self.tags.add(self.format)
+ self.tags.add(self.name)
+ self.tags.add("format_%s" % self.format)
+ self.tags.add("builder_%s" % self.name)
+
+ # images that need to be copied over (source -> dest)
+ self.images = {}
+
+ self.init()
+
+ # helper methods
+ def init(self):
+ """Load necessary templates and perform initialization. The default
+ implementation does nothing.
+ """
+ pass
+
+ def create_template_bridge(self):
+ """Return the template bridge configured."""
+ if self.config.template_bridge:
+ self.templates = self.app.import_object(
+ self.config.template_bridge, 'template_bridge setting')()
+ else:
+ from sphinx.jinja2glue import BuiltinTemplateLoader
+ self.templates = BuiltinTemplateLoader()
+
+ def get_target_uri(self, docname, typ=None):
+ """Return the target URI for a document name.
+
+ *typ* can be used to qualify the link characteristic for individual
+ builders.
+ """
+ raise NotImplementedError
+
+ def get_relative_uri(self, from_, to, typ=None):
+ """Return a relative URI between two source filenames.
+
+ May raise environment.NoUri if there's no way to return a sensible URI.
+ """
+ return relative_uri(self.get_target_uri(from_),
+ self.get_target_uri(to, typ))
+
+ def get_outdated_docs(self):
+ """Return an iterable of output files that are outdated, or a string
+ describing what an update build will build.
+
+ If the builder does not output individual files corresponding to
+ source files, return a string here. If it does, return an iterable
+ of those files that need to be written.
+ """
+ raise NotImplementedError
+
+ def old_status_iterator(self, iterable, summary, colorfunc=darkgreen,
+ stringify_func=lambda x: x):
+ l = 0
+ for item in iterable:
+ if l == 0:
+ self.info(bold(summary), nonl=1)
+ l = 1
+ self.info(colorfunc(stringify_func(item)) + ' ', nonl=1)
+ yield item
+ if l == 1:
+ self.info()
+
+ # new version with progress info
+ def status_iterator(self, iterable, summary, colorfunc=darkgreen, length=0,
+ stringify_func=lambda x: x):
+ if length == 0:
+ for item in self.old_status_iterator(iterable, summary, colorfunc,
+ stringify_func):
+ yield item
+ return
+ l = 0
+ summary = bold(summary)
+ for item in iterable:
+ l += 1
+ s = '%s[%3d%%] %s' % (summary, 100*l/length,
+ colorfunc(stringify_func(item)))
+ if self.app.verbosity:
+ s += '\n'
+ else:
+ s = term_width_line(s)
+ self.info(s, nonl=1)
+ yield item
+ if l > 0:
+ self.info()
+
+ supported_image_types = []
+
+ def post_process_images(self, doctree):
+ """Pick the best candidate for all image URIs."""
+ for node in doctree.traverse(nodes.image):
+ if '?' in node['candidates']:
+ # don't rewrite nonlocal image URIs
+ continue
+ if '*' not in node['candidates']:
+ for imgtype in self.supported_image_types:
+ candidate = node['candidates'].get(imgtype, None)
+ if candidate:
+ break
+ else:
+ self.warn(
+ 'no matching candidate for image URI %r' % node['uri'],
+ '%s:%s' % (node.source, getattr(node, 'line', '')))
+ continue
+ node['uri'] = candidate
+ else:
+ candidate = node['uri']
+ if candidate not in self.env.images:
+ # non-existing URI; let it alone
+ continue
+ self.images[candidate] = self.env.images[candidate][1]
+
+ # build methods
+
+ def build_all(self):
+ """Build all source files."""
+ self.build(None, summary='all source files', method='all')
+
+ def build_specific(self, filenames):
+ """Only rebuild as much as needed for changes in the *filenames*."""
+ # bring the filenames to the canonical format, that is,
+ # relative to the source directory and without source_suffix.
+ dirlen = len(self.srcdir) + 1
+ to_write = []
+ suffix = self.config.source_suffix
+ for filename in filenames:
+ filename = path.normpath(path.abspath(filename))
+ if not filename.startswith(self.srcdir):
+ self.warn('file %r given on command line is not under the '
+ 'source directory, ignoring' % filename)
+ continue
+ if not (path.isfile(filename) or path.isfile(filename + suffix)):
+ self.warn('file %r given on command line does not exist, '
+ 'ignoring' % filename)
+ continue
+ filename = filename[dirlen:]
+ if filename.endswith(suffix):
+ filename = filename[:-len(suffix)]
+ filename = filename.replace(path.sep, SEP)
+ to_write.append(filename)
+ self.build(to_write, method='specific',
+ summary='%d source files given on command '
+ 'line' % len(to_write))
+
+ def build_update(self):
+ """Only rebuild what was changed or added since last build."""
+ to_build = self.get_outdated_docs()
+ if isinstance(to_build, str):
+ self.build(['__all__'], to_build)
+ else:
+ to_build = list(to_build)
+ self.build(to_build,
+ summary='targets for %d source files that are '
+ 'out of date' % len(to_build))
+
+ def build(self, docnames, summary=None, method='update'):
+ """Main build method.
+
+ First updates the environment, and then calls :meth:`write`.
+ """
+ if summary:
+ self.info(bold('building [%s]: ' % self.name), nonl=1)
+ self.info(summary)
+
+ updated_docnames = set()
+ # while reading, collect all warnings from docutils
+ warnings = []
+ self.env.set_warnfunc(lambda *args: warnings.append(args))
+ self.info(bold('updating environment: '), nonl=1)
+ msg, length, iterator = self.env.update(self.config, self.srcdir,
+ self.doctreedir, self.app)
+ self.info(msg)
+ for docname in self.status_iterator(iterator, 'reading sources... ',
+ purple, length):
+ updated_docnames.add(docname)
+ # nothing further to do, the environment has already
+ # done the reading
+ for warning in warnings:
+ self.warn(*warning)
+ self.env.set_warnfunc(self.warn)
+
+ doccount = len(updated_docnames)
+ self.info(bold('looking for now-outdated files... '), nonl=1)
+ for docname in self.env.check_dependents(updated_docnames):
+ updated_docnames.add(docname)
+ outdated = len(updated_docnames) - doccount
+ if outdated:
+ self.info('%d found' % outdated)
+ else:
+ self.info('none found')
+
+ if updated_docnames:
+ # save the environment
+ from sphinx.application import ENV_PICKLE_FILENAME
+ self.info(bold('pickling environment... '), nonl=True)
+ self.env.topickle(path.join(self.doctreedir, ENV_PICKLE_FILENAME))
+ self.info('done')
+
+ # global actions
+ self.info(bold('checking consistency... '), nonl=True)
+ self.env.check_consistency()
+ self.info('done')
+ else:
+ if method == 'update' and not docnames:
+ self.info(bold('no targets are out of date.'))
+ return
+
+ # filter "docnames" (list of outdated files) by the updated
+ # found_docs of the environment; this will remove docs that
+ # have since been removed
+ if docnames and docnames != ['__all__']:
+ docnames = set(docnames) & self.env.found_docs
+
+ # another indirection to support builders that don't build
+ # files individually
+ self.write(docnames, list(updated_docnames), method)
+
+ # finish (write static files etc.)
+ self.finish()
+ status = (self.app.statuscode == 0 and 'succeeded'
+ or 'finished with problems')
+ if self.app._warncount:
+ self.info(bold('build %s, %s warning%s.' %
+ (status, self.app._warncount,
+ self.app._warncount != 1 and 's' or '')))
+ else:
+ self.info(bold('build %s.' % status))
+
+ def write(self, build_docnames, updated_docnames, method='update'):
+ if build_docnames is None or build_docnames == ['__all__']:
+ # build_all
+ build_docnames = self.env.found_docs
+ if method == 'update':
+ # build updated ones as well
+ docnames = set(build_docnames) | set(updated_docnames)
+ else:
+ docnames = set(build_docnames)
+ self.app.debug('docnames to write: %s', ', '.join(sorted(docnames)))
+
+ # add all toctree-containing files that may have changed
+ for docname in list(docnames):
+ for tocdocname in self.env.files_to_rebuild.get(docname, []):
+ if tocdocname in self.env.found_docs:
+ docnames.add(tocdocname)
+ docnames.add(self.config.master_doc)
+
+ self.info(bold('preparing documents... '), nonl=True)
+ self.prepare_writing(docnames)
+ self.info('done')
+
+ warnings = []
+ self.env.set_warnfunc(lambda *args: warnings.append(args))
+ # check for prerequisites to parallel build
+ # (parallel only works on POSIX, because the forking impl of
+ # multiprocessing is required)
+ if not (multiprocessing and
+ self.app.parallel > 1 and
+ self.allow_parallel and
+ os.name == 'posix'):
+ self._write_serial(sorted(docnames), warnings)
+ else:
+ # number of subprocesses is parallel-1 because the main process
+ # is busy loading doctrees and doing write_doc_serialized()
+ self._write_parallel(sorted(docnames), warnings,
+ nproc=self.app.parallel - 1)
+ self.env.set_warnfunc(self.warn)
+
+ def _write_serial(self, docnames, warnings):
+ for docname in self.status_iterator(
+ docnames, 'writing output... ', darkgreen, len(docnames)):
+ doctree = self.env.get_and_resolve_doctree(docname, self)
+ self.write_doc_serialized(docname, doctree)
+ self.write_doc(docname, doctree)
+ for warning in warnings:
+ self.warn(*warning)
+
+ def _write_parallel(self, docnames, warnings, nproc):
+ def write_process(docs):
+ try:
+ for docname, doctree in docs:
+ self.write_doc(docname, doctree)
+ except KeyboardInterrupt:
+ pass # do not print a traceback on Ctrl-C
+ finally:
+ for warning in warnings:
+ self.warn(*warning)
+
+ def process_thread(docs):
+ p = multiprocessing.Process(target=write_process, args=(docs,))
+ p.start()
+ p.join()
+ semaphore.release()
+
+ # allow only "nproc" worker processes at once
+ semaphore = threading.Semaphore(nproc)
+ # list of threads to join when waiting for completion
+ threads = []
+
+ # warm up caches/compile templates using the first document
+ firstname, docnames = docnames[0], docnames[1:]
+ doctree = self.env.get_and_resolve_doctree(firstname, self)
+ self.write_doc_serialized(firstname, doctree)
+ self.write_doc(firstname, doctree)
+ # for the rest, determine how many documents to write in one go
+ ndocs = len(docnames)
+ chunksize = min(ndocs // nproc, 10)
+ if chunksize == 0:
+ chunksize = 1
+ nchunks, rest = divmod(ndocs, chunksize)
+ if rest:
+ nchunks += 1
+ # partition documents in "chunks" that will be written by one Process
+ chunks = [docnames[i*chunksize:(i+1)*chunksize] for i in range(nchunks)]
+ for docnames in self.status_iterator(
+ chunks, 'writing output... ', darkgreen, len(chunks),
+ lambda chk: '%s .. %s' % (chk[0], chk[-1])):
+ docs = []
+ for docname in docnames:
+ doctree = self.env.get_and_resolve_doctree(docname, self)
+ self.write_doc_serialized(docname, doctree)
+ docs.append((docname, doctree))
+ # start a new thread to oversee the completion of this chunk
+ semaphore.acquire()
+ t = threading.Thread(target=process_thread, args=(docs,))
+ t.setDaemon(True)
+ t.start()
+ threads.append(t)
+
+ # make sure all threads have finished
+ self.info(bold('waiting for workers... '))#, nonl=True)
+ for t in threads:
+ t.join()
+
+ def prepare_writing(self, docnames):
+ """A place where you can add logic before :meth:`write_doc` is run"""
+ raise NotImplementedError
+
+ def write_doc(self, docname, doctree):
+ """Where you actually write something to the filesystem."""
+ raise NotImplementedError
+
+ def write_doc_serialized(self, docname, doctree):
+ """Handle parts of write_doc that must be called in the main process
+ if parallel build is active.
+ """
+ pass
+
+ def finish(self):
+ """Finish the building process.
+
+ The default implementation does nothing.
+ """
+ pass
+
+ def cleanup(self):
+ """Cleanup any resources.
+
+ The default implementation does nothing.
+ """
+ pass
+
+ def get_builder_config(self, option, default):
+ """Return a builder specific option.
+
+ This method allows customization of common builder settings by
+ inserting the name of the current builder in the option key.
+ If the key does not exist, use default as builder name.
+ """
+ # At the moment, only XXX_use_index is looked up this way.
+ # Every new builder variant must be registered in Config.config_values.
+ try:
+ optname = '%s_%s' % (self.name, option)
+ return getattr(self.config, optname)
+ except AttributeError:
+ optname = '%s_%s' % (default, option)
+ return getattr(self.config, optname)
+
+BUILTIN_BUILDERS = {
+ 'html': ('html', 'StandaloneHTMLBuilder'),
+ 'dirhtml': ('html', 'DirectoryHTMLBuilder'),
+ 'singlehtml': ('html', 'SingleFileHTMLBuilder'),
+ 'pickle': ('html', 'PickleHTMLBuilder'),
+ 'json': ('html', 'JSONHTMLBuilder'),
+ 'web': ('html', 'PickleHTMLBuilder'),
+ 'htmlhelp': ('htmlhelp', 'HTMLHelpBuilder'),
+ 'devhelp': ('devhelp', 'DevhelpBuilder'),
+ 'qthelp': ('qthelp', 'QtHelpBuilder'),
+ 'epub': ('epub', 'EpubBuilder'),
+ 'latex': ('latex', 'LaTeXBuilder'),
+ 'text': ('text', 'TextBuilder'),
+ 'man': ('manpage', 'ManualPageBuilder'),
+ 'texinfo': ('texinfo', 'TexinfoBuilder'),
+ 'changes': ('changes', 'ChangesBuilder'),
+ 'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
+ 'websupport': ('websupport', 'WebSupportBuilder'),
+ 'gettext': ('gettext', 'MessageCatalogBuilder'),
+ 'xml': ('xml', 'XMLBuilder'),
+ 'pseudoxml': ('xml', 'PseudoXMLBuilder'),
+}
diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py
new file mode 100644
index 0000000..c9317af
--- /dev/null
+++ b/sphinx/builders/changes.py
@@ -0,0 +1,162 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.changes
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Changelog builder.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import codecs
+from os import path
+
+from sphinx import package_dir
+from sphinx.util import copy_static_entry
+from sphinx.locale import _
+from sphinx.theming import Theme
+from sphinx.builders import Builder
+from sphinx.util.osutil import ensuredir, os_path
+from sphinx.util.console import bold
+from sphinx.util.pycompat import htmlescape
+
+
+class ChangesBuilder(Builder):
+ """
+ Write a summary with all versionadded/changed directives.
+ """
+ name = 'changes'
+
+ def init(self):
+ self.create_template_bridge()
+ Theme.init_themes(self.confdir, self.config.html_theme_path,
+ warn=self.warn)
+ self.theme = Theme('default')
+ self.templates.init(self, self.theme)
+
+ def get_outdated_docs(self):
+ return self.outdir
+
+ typemap = {
+ 'versionadded': 'added',
+ 'versionchanged': 'changed',
+ 'deprecated': 'deprecated',
+ }
+
+ def write(self, *ignored):
+ version = self.config.version
+ libchanges = {}
+ apichanges = []
+ otherchanges = {}
+ if version not in self.env.versionchanges:
+ self.info(bold('no changes in version %s.' % version))
+ return
+ self.info(bold('writing summary file...'))
+ for type, docname, lineno, module, descname, content in \
+ self.env.versionchanges[version]:
+ if isinstance(descname, tuple):
+ descname = descname[0]
+ ttext = self.typemap[type]
+ context = content.replace('\n', ' ')
+ if descname and docname.startswith('c-api'):
+ if not descname:
+ continue
+ if context:
+ entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext,
+ context)
+ else:
+ entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
+ apichanges.append((entry, docname, lineno))
+ elif descname or module:
+ if not module:
+ module = _('Builtins')
+ if not descname:
+ descname = _('Module level')
+ if context:
+ entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext,
+ context)
+ else:
+ entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
+ libchanges.setdefault(module, []).append((entry, docname,
+ lineno))
+ else:
+ if not context:
+ continue
+ entry = '<i>%s:</i> %s' % (ttext.capitalize(), context)
+ title = self.env.titles[docname].astext()
+ otherchanges.setdefault((docname, title), []).append(
+ (entry, docname, lineno))
+
+ ctx = {
+ 'project': self.config.project,
+ 'version': version,
+ 'docstitle': self.config.html_title,
+ 'shorttitle': self.config.html_short_title,
+ 'libchanges': sorted(libchanges.iteritems()),
+ 'apichanges': sorted(apichanges),
+ 'otherchanges': sorted(otherchanges.iteritems()),
+ 'show_copyright': self.config.html_show_copyright,
+ 'show_sphinx': self.config.html_show_sphinx,
+ }
+ f = codecs.open(path.join(self.outdir, 'index.html'), 'w', 'utf8')
+ try:
+ f.write(self.templates.render('changes/frameset.html', ctx))
+ finally:
+ f.close()
+ f = codecs.open(path.join(self.outdir, 'changes.html'), 'w', 'utf8')
+ try:
+ f.write(self.templates.render('changes/versionchanges.html', ctx))
+ finally:
+ f.close()
+
+ hltext = ['.. versionadded:: %s' % version,
+ '.. versionchanged:: %s' % version,
+ '.. deprecated:: %s' % version]
+
+ def hl(no, line):
+ line = '<a name="L%s"> </a>' % no + htmlescape(line)
+ for x in hltext:
+ if x in line:
+ line = '<span class="hl">%s</span>' % line
+ break
+ return line
+
+ self.info(bold('copying source files...'))
+ for docname in self.env.all_docs:
+ f = codecs.open(self.env.doc2path(docname), 'r',
+ self.env.config.source_encoding)
+ try:
+ lines = f.readlines()
+ finally:
+ f.close()
+ targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
+ ensuredir(path.dirname(targetfn))
+ f = codecs.open(targetfn, 'w', 'utf-8')
+ try:
+ text = ''.join(hl(i+1, line) for (i, line) in enumerate(lines))
+ ctx = {
+ 'filename': self.env.doc2path(docname, None),
+ 'text': text
+ }
+ f.write(self.templates.render('changes/rstsource.html', ctx))
+ finally:
+ f.close()
+ themectx = dict(('theme_' + key, val) for (key, val) in
+ self.theme.get_options({}).iteritems())
+ copy_static_entry(path.join(package_dir, 'themes', 'default',
+ 'static', 'default.css_t'),
+ self.outdir, self, themectx)
+ copy_static_entry(path.join(package_dir, 'themes', 'basic',
+ 'static', 'basic.css'),
+ self.outdir, self)
+
+ def hl(self, text, version):
+ text = htmlescape(text)
+ for directive in ['versionchanged', 'versionadded', 'deprecated']:
+ text = text.replace('.. %s:: %s' % (directive, version),
+ '<b>.. %s:: %s</b>' % (directive, version))
+ return text
+
+ def finish(self):
+ pass
diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py
new file mode 100644
index 0000000..61482fd
--- /dev/null
+++ b/sphinx/builders/devhelp.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.devhelp
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Build HTML documentation and Devhelp_ support files.
+
+ .. _Devhelp: http://live.gnome.org/devhelp
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from __future__ import absolute_import
+
+import re
+from os import path
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.builders.html import StandaloneHTMLBuilder
+
+try:
+ import xml.etree.ElementTree as etree
+except ImportError:
+ try:
+ import lxml.etree as etree
+ except ImportError:
+ try:
+ import elementtree.ElementTree as etree
+ except ImportError:
+ import cElementTree as etree
+
+try:
+ import gzip
+ def comp_open(filename, mode='rb'):
+ return gzip.open(filename + '.gz', mode)
+except ImportError:
+ def comp_open(filename, mode='rb'):
+ return open(filename, mode)
+
+
+class DevhelpBuilder(StandaloneHTMLBuilder):
+ """
+ Builder that also outputs GNOME Devhelp file.
+ """
+ name = 'devhelp'
+
+ # don't copy the reST source
+ copysource = False
+ supported_image_types = ['image/png', 'image/gif', 'image/jpeg']
+
+ # don't add links
+ add_permalinks = False
+ # don't add sidebar etc.
+ embedded = True
+
+ def init(self):
+ StandaloneHTMLBuilder.init(self)
+ self.out_suffix = '.html'
+
+ def handle_finish(self):
+ self.build_devhelp(self.outdir, self.config.devhelp_basename)
+
+ def build_devhelp(self, outdir, outname):
+ self.info('dumping devhelp index...')
+
+ # Basic info
+ root = etree.Element('book',
+ title=self.config.html_title,
+ name=self.config.project,
+ link="index.html",
+ version=self.config.version)
+ tree = etree.ElementTree(root)
+
+ # TOC
+ chapters = etree.SubElement(root, 'chapters')
+
+ tocdoc = self.env.get_and_resolve_doctree(
+ self.config.master_doc, self, prune_toctrees=False)
+
+ def write_toc(node, parent):
+ if isinstance(node, addnodes.compact_paragraph) or \
+ isinstance(node, nodes.bullet_list):
+ for subnode in node:
+ write_toc(subnode, parent)
+ elif isinstance(node, nodes.list_item):
+ item = etree.SubElement(parent, 'sub')
+ for subnode in node:
+ write_toc(subnode, item)
+ elif isinstance(node, nodes.reference):
+ parent.attrib['link'] = node['refuri']
+ parent.attrib['name'] = node.astext().encode('utf-8')
+
+ def istoctree(node):
+ return isinstance(node, addnodes.compact_paragraph) and \
+ node.has_key('toctree')
+
+ for node in tocdoc.traverse(istoctree):
+ write_toc(node, chapters)
+
+ # Index
+ functions = etree.SubElement(root, 'functions')
+ index = self.env.create_index(self)
+
+ def write_index(title, refs, subitems):
+ if len(refs) == 0:
+ pass
+ elif len(refs) == 1:
+ etree.SubElement(functions, 'function',
+ name=title, link=refs[0][1])
+ else:
+ for i, ref in enumerate(refs):
+ etree.SubElement(functions, 'function',
+ name="[%d] %s" % (i, title),
+ link=ref[1])
+
+ if subitems:
+ parent_title = re.sub(r'\s*\(.*\)\s*$', '', title)
+ for subitem in subitems:
+ write_index("%s %s" % (parent_title, subitem[0]),
+ subitem[1], [])
+
+ for (key, group) in index:
+ for title, (refs, subitems) in group:
+ write_index(title, refs, subitems)
+
+ # Dump the XML file
+ f = comp_open(path.join(outdir, outname + '.devhelp'), 'w')
+ try:
+ tree.write(f)
+ finally:
+ f.close()
diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py
new file mode 100644
index 0000000..a73679c
--- /dev/null
+++ b/sphinx/builders/epub.py
@@ -0,0 +1,761 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.epub
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Build epub files.
+ Originally derived from qthelp.py.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import sys
+import time
+import codecs
+import zipfile
+from os import path
+
+try:
+ from PIL import Image
+except ImportError:
+ try:
+ import Image
+ except ImportError:
+ Image = None
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.util.osutil import ensuredir, copyfile, EEXIST
+from sphinx.util.smartypants import sphinx_smarty_pants as ssp
+from sphinx.util.console import brown
+
+
+# (Fragment) templates from which the metainfo files content.opf, toc.ncx,
+# mimetype, and META-INF/container.xml are created.
+# This template section also defines strings that are embedded in the html
+# output but that may be customized by (re-)setting module attributes,
+# e.g. from conf.py.
+
+_mimetype_template = 'application/epub+zip' # no EOL!
+
+_container_template = u'''\
+<?xml version="1.0" encoding="UTF-8"?>
+<container version="1.0"
+ xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
+ <rootfiles>
+ <rootfile full-path="content.opf"
+ media-type="application/oebps-package+xml"/>
+ </rootfiles>
+</container>
+'''
+
+_toc_template = u'''\
+<?xml version="1.0"?>
+<ncx version="2005-1" xmlns="http://www.daisy.org/z3986/2005/ncx/">
+ <head>
+ <meta name="dtb:uid" content="%(uid)s"/>
+ <meta name="dtb:depth" content="%(level)d"/>
+ <meta name="dtb:totalPageCount" content="0"/>
+ <meta name="dtb:maxPageNumber" content="0"/>
+ </head>
+ <docTitle>
+ <text>%(title)s</text>
+ </docTitle>
+ <navMap>
+%(navpoints)s
+ </navMap>
+</ncx>
+'''
+
+_navpoint_template = u'''\
+%(indent)s <navPoint id="%(navpoint)s" playOrder="%(playorder)d">
+%(indent)s <navLabel>
+%(indent)s <text>%(text)s</text>
+%(indent)s </navLabel>
+%(indent)s <content src="%(refuri)s" />
+%(indent)s </navPoint>'''
+
+_navpoint_indent = ' '
+_navPoint_template = 'navPoint%d'
+
+_content_template = u'''\
+<?xml version="1.0" encoding="UTF-8"?>
+<package xmlns="http://www.idpf.org/2007/opf" version="2.0"
+ unique-identifier="%(uid)s">
+ <metadata xmlns:opf="http://www.idpf.org/2007/opf"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:language>%(lang)s</dc:language>
+ <dc:title>%(title)s</dc:title>
+ <dc:creator opf:role="aut">%(author)s</dc:creator>
+ <dc:publisher>%(publisher)s</dc:publisher>
+ <dc:rights>%(copyright)s</dc:rights>
+ <dc:identifier id="%(uid)s" opf:scheme="%(scheme)s">%(id)s</dc:identifier>
+ <dc:date>%(date)s</dc:date>
+ </metadata>
+ <manifest>
+ <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" />
+%(files)s
+ </manifest>
+ <spine toc="ncx">
+%(spine)s
+ </spine>
+ <guide>
+%(guide)s
+ </guide>
+</package>
+'''
+
+_cover_template = u'''\
+ <meta name="cover" content="%(cover)s"/>
+'''
+
+_coverpage_name = u'epub-cover.html'
+
+_file_template = u'''\
+ <item id="%(id)s"
+ href="%(href)s"
+ media-type="%(media_type)s" />'''
+
+_spine_template = u'''\
+ <itemref idref="%(idref)s" />'''
+
+_guide_template = u'''\
+ <reference type="%(type)s" title="%(title)s" href="%(uri)s" />'''
+
+_toctree_template = u'toctree-l%d'
+
+_link_target_template = u' [%(uri)s]'
+
+_footnote_label_template = u'#%d'
+
+_footnotes_rubric_name = u'Footnotes'
+
+_css_link_target_class = u'link-target'
+
+# XXX These strings should be localized according to epub_language
+_guide_titles = {
+ 'toc': u'Table of Contents',
+ 'cover': u'Cover'
+}
+
+_media_types = {
+ '.html': 'application/xhtml+xml',
+ '.css': 'text/css',
+ '.png': 'image/png',
+ '.gif': 'image/gif',
+ '.svg': 'image/svg+xml',
+ '.jpg': 'image/jpeg',
+ '.jpeg': 'image/jpeg',
+ '.otf': 'application/x-font-otf',
+ '.ttf': 'application/x-font-ttf',
+}
+
+_vector_graphics_extensions = ('.svg',)
+
+# Regular expression to match colons only in local fragment identifiers.
+# If the URI contains a colon before the #,
+# it is an external link that should not change.
+_refuri_re = re.compile("([^#:]*#)(.*)")
+
+
+# The epub publisher
+
+class EpubBuilder(StandaloneHTMLBuilder):
+ """
+ Builder that outputs epub files.
+
+ It creates the metainfo files container.opf, toc.ncx, mimetype, and
+ META-INF/container.xml. Afterwards, all necessary files are zipped to an
+ epub file.
+ """
+ name = 'epub'
+
+ # don't copy the reST source
+ copysource = False
+ supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
+ 'image/jpeg']
+
+ # don't add links
+ add_permalinks = False
+ # don't add sidebar etc.
+ embedded = True
+
+ def init(self):
+ StandaloneHTMLBuilder.init(self)
+ # the output files for epub must be .html only
+ self.out_suffix = '.html'
+ self.playorder = 0
+ self.tocid = 0
+
+ def get_theme_config(self):
+ return self.config.epub_theme, self.config.epub_theme_options
+
+ # generic support functions
+ def make_id(self, name, id_cache={}):
+ # id_cache is intentionally mutable
+ """Return a unique id for name."""
+ id = id_cache.get(name)
+ if not id:
+ id = 'epub-%d' % self.env.new_serialno('epub')
+ id_cache[name] = id
+ return id
+
+ def esc(self, name):
+ """Replace all characters not allowed in text an attribute values."""
+ # Like cgi.escape, but also replace apostrophe
+ name = name.replace('&', '&')
+ name = name.replace('<', '<')
+ name = name.replace('>', '>')
+ name = name.replace('"', '"')
+ name = name.replace('\'', ''')
+ return name
+
+ def get_refnodes(self, doctree, result):
+ """Collect section titles, their depth in the toc and the refuri."""
+ # XXX: is there a better way than checking the attribute
+ # toctree-l[1-8] on the parent node?
+ if isinstance(doctree, nodes.reference) and doctree.has_key('refuri'):
+ refuri = doctree['refuri']
+ if refuri.startswith('http://') or refuri.startswith('https://') \
+ or refuri.startswith('irc:') or refuri.startswith('mailto:'):
+ return result
+ classes = doctree.parent.attributes['classes']
+ for level in range(8, 0, -1): # or range(1, 8)?
+ if (_toctree_template % level) in classes:
+ result.append({
+ 'level': level,
+ 'refuri': self.esc(refuri),
+ 'text': ssp(self.esc(doctree.astext()))
+ })
+ break
+ else:
+ for elem in doctree.children:
+ result = self.get_refnodes(elem, result)
+ return result
+
+ def get_toc(self):
+ """Get the total table of contents, containing the master_doc
+ and pre and post files not managed by sphinx.
+ """
+ doctree = self.env.get_and_resolve_doctree(self.config.master_doc,
+ self, prune_toctrees=False, includehidden=True)
+ self.refnodes = self.get_refnodes(doctree, [])
+ master_dir = path.dirname(self.config.master_doc)
+ if master_dir:
+ master_dir += '/' # XXX or os.sep?
+ for item in self.refnodes:
+ item['refuri'] = master_dir + item['refuri']
+ self.toc_add_files(self.refnodes)
+
+ def toc_add_files(self, refnodes):
+ """Add the master_doc, pre and post files to a list of refnodes.
+ """
+ refnodes.insert(0, {
+ 'level': 1,
+ 'refuri': self.esc(self.config.master_doc + '.html'),
+ 'text': ssp(self.esc(
+ self.env.titles[self.config.master_doc].astext()))
+ })
+ for file, text in reversed(self.config.epub_pre_files):
+ refnodes.insert(0, {
+ 'level': 1,
+ 'refuri': self.esc(file),
+ 'text': ssp(self.esc(text))
+ })
+ for file, text in self.config.epub_post_files:
+ refnodes.append({
+ 'level': 1,
+ 'refuri': self.esc(file),
+ 'text': ssp(self.esc(text))
+ })
+
+ def fix_fragment(self, prefix, fragment):
+ """Return a href/id attribute with colons replaced by hyphens."""
+ return prefix + fragment.replace(':', '-')
+
+ def fix_ids(self, tree):
+ """Replace colons with hyphens in href and id attributes.
+
+ Some readers crash because they interpret the part as a
+ transport protocol specification.
+ """
+ for node in tree.traverse(nodes.reference):
+ if 'refuri' in node:
+ m = _refuri_re.match(node['refuri'])
+ if m:
+ node['refuri'] = self.fix_fragment(m.group(1), m.group(2))
+ if 'refid' in node:
+ node['refid'] = self.fix_fragment('', node['refid'])
+ for node in tree.traverse(addnodes.desc_signature):
+ ids = node.attributes['ids']
+ newids = []
+ for id in ids:
+ newids.append(self.fix_fragment('', id))
+ node.attributes['ids'] = newids
+
+ def add_visible_links(self, tree, show_urls='inline'):
+ """Add visible link targets for external links"""
+
+ def make_footnote_ref(doc, label):
+ """Create a footnote_reference node with children"""
+ footnote_ref = nodes.footnote_reference('[#]_')
+ footnote_ref.append(nodes.Text(label))
+ doc.note_autofootnote_ref(footnote_ref)
+ return footnote_ref
+
+ def make_footnote(doc, label, uri):
+ """Create a footnote node with children"""
+ footnote = nodes.footnote(uri)
+ para = nodes.paragraph()
+ para.append(nodes.Text(uri))
+ footnote.append(para)
+ footnote.insert(0, nodes.label('', label))
+ doc.note_autofootnote(footnote)
+ return footnote
+
+ def footnote_spot(tree):
+ """Find or create a spot to place footnotes.
+
+ The function returns the tuple (parent, index)."""
+ # The code uses the following heuristic:
+ # a) place them after the last existing footnote
+ # b) place them after an (empty) Footnotes rubric
+ # c) create an empty Footnotes rubric at the end of the document
+ fns = tree.traverse(nodes.footnote)
+ if fns:
+ fn = fns[-1]
+ return fn.parent, fn.parent.index(fn) + 1
+ for node in tree.traverse(nodes.rubric):
+ if len(node.children) == 1 and \
+ node.children[0].astext() == _footnotes_rubric_name:
+ return node.parent, node.parent.index(node) + 1
+ doc = tree.traverse(nodes.document)[0]
+ rub = nodes.rubric()
+ rub.append(nodes.Text(_footnotes_rubric_name))
+ doc.append(rub)
+ return doc, doc.index(rub) + 1
+
+ if show_urls == 'no':
+ return
+ if show_urls == 'footnote':
+ doc = tree.traverse(nodes.document)[0]
+ fn_spot, fn_idx = footnote_spot(tree)
+ nr = 1
+ for node in tree.traverse(nodes.reference):
+ uri = node.get('refuri', '')
+ if (uri.startswith('http:') or uri.startswith('https:') or
+ uri.startswith('ftp:')) and uri not in node.astext():
+ idx = node.parent.index(node) + 1
+ if show_urls == 'inline':
+ uri = _link_target_template % {'uri': uri}
+ link = nodes.inline(uri, uri)
+ link['classes'].append(_css_link_target_class)
+ node.parent.insert(idx, link)
+ elif show_urls == 'footnote':
+ label = _footnote_label_template % nr
+ nr += 1
+ footnote_ref = make_footnote_ref(doc, label)
+ node.parent.insert(idx, footnote_ref)
+ footnote = make_footnote(doc, label, uri)
+ fn_spot.insert(fn_idx, footnote)
+ footnote_ref['refid'] = footnote['ids'][0]
+ footnote.add_backref(footnote_ref['ids'][0])
+ fn_idx += 1
+
+ def write_doc(self, docname, doctree):
+ """Write one document file.
+
+ This method is overwritten in order to fix fragment identifiers
+ and to add visible external links.
+ """
+ self.fix_ids(doctree)
+ self.add_visible_links(doctree, self.config.epub_show_urls)
+ return StandaloneHTMLBuilder.write_doc(self, docname, doctree)
+
+ def fix_genindex(self, tree):
+ """Fix href attributes for genindex pages."""
+ # XXX: modifies tree inline
+ # Logic modeled from themes/basic/genindex.html
+ for key, columns in tree:
+ for entryname, (links, subitems) in columns:
+ for (i, (ismain, link)) in enumerate(links):
+ m = _refuri_re.match(link)
+ if m:
+ links[i] = (ismain,
+ self.fix_fragment(m.group(1), m.group(2)))
+ for subentryname, subentrylinks in subitems:
+ for (i, (ismain, link)) in enumerate(subentrylinks):
+ m = _refuri_re.match(link)
+ if m:
+ subentrylinks[i] = (ismain,
+ self.fix_fragment(m.group(1), m.group(2)))
+
+ def is_vector_graphics(self, filename):
+ """Does the filename extension indicate a vector graphic format?"""
+ ext = path.splitext(filename)[-1]
+ return ext in _vector_graphics_extensions
+
+ def copy_image_files_pil(self):
+ """Copy images using the PIL.
+ The method tries to read and write the files with the PIL,
+ converting the format and resizing the image if necessary/possible.
+ """
+ ensuredir(path.join(self.outdir, '_images'))
+ for src in self.status_iterator(self.images, 'copying images... ',
+ brown, len(self.images)):
+ dest = self.images[src]
+ try:
+ img = Image.open(path.join(self.srcdir, src))
+ except IOError:
+ if not self.is_vector_graphics(src):
+ self.warn('cannot read image file %r: copying it instead' %
+ (path.join(self.srcdir, src), ))
+ try:
+ copyfile(path.join(self.srcdir, src),
+ path.join(self.outdir, '_images', dest))
+ except (IOError, OSError), err:
+ self.warn('cannot copy image file %r: %s' %
+ (path.join(self.srcdir, src), err))
+ continue
+ if self.config.epub_fix_images:
+ if img.mode in ('P',):
+ # See PIL documentation for Image.convert()
+ img = img.convert()
+ if self.config.epub_max_image_width > 0:
+ (width, height) = img.size
+ nw = self.config.epub_max_image_width
+ if width > nw:
+ nh = (height * nw) / width
+ img = img.resize((nw, nh), Image.BICUBIC)
+ try:
+ img.save(path.join(self.outdir, '_images', dest))
+ except (IOError, OSError), err:
+ self.warn('cannot write image file %r: %s' %
+ (path.join(self.srcdir, src), err))
+
+ def copy_image_files(self):
+ """Copy image files to destination directory.
+ This overwritten method can use the PIL to convert image files.
+ """
+ if self.images:
+ if self.config.epub_fix_images or self.config.epub_max_image_width:
+ if not Image:
+ self.warn('PIL not found - copying image files')
+ super(EpubBuilder, self).copy_image_files()
+ else:
+ self.copy_image_files_pil()
+ else:
+ super(EpubBuilder, self).copy_image_files()
+
+ def handle_page(self, pagename, addctx, templatename='page.html',
+ outfilename=None, event_arg=None):
+ """Create a rendered page.
+
+ This method is overwritten for genindex pages in order to fix href link
+ attributes.
+ """
+ if pagename.startswith('genindex'):
+ self.fix_genindex(addctx['genindexentries'])
+ StandaloneHTMLBuilder.handle_page(self, pagename, addctx, templatename,
+ outfilename, event_arg)
+
+
+ # Finish by building the epub file
+ def handle_finish(self):
+ """Create the metainfo files and finally the epub."""
+ self.get_toc()
+ self.build_mimetype(self.outdir, 'mimetype')
+ self.build_container(self.outdir, 'META-INF/container.xml')
+ self.build_content(self.outdir, 'content.opf')
+ self.build_toc(self.outdir, 'toc.ncx')
+ self.build_epub(self.outdir, self.config.epub_basename + '.epub')
+
+ def build_mimetype(self, outdir, outname):
+ """Write the metainfo file mimetype."""
+ self.info('writing %s file...' % outname)
+ f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
+ try:
+ f.write(_mimetype_template)
+ finally:
+ f.close()
+
+ def build_container(self, outdir, outname):
+ """Write the metainfo file META-INF/cointainer.xml."""
+ self.info('writing %s file...' % outname)
+ fn = path.join(outdir, outname)
+ try:
+ os.mkdir(path.dirname(fn))
+ except OSError, err:
+ if err.errno != EEXIST:
+ raise
+ f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
+ try:
+ f.write(_container_template)
+ finally:
+ f.close()
+
+ def content_metadata(self, files, spine, guide):
+ """Create a dictionary with all metadata for the content.opf
+ file properly escaped.
+ """
+ metadata = {}
+ metadata['title'] = self.esc(self.config.epub_title)
+ metadata['author'] = self.esc(self.config.epub_author)
+ metadata['uid'] = self.esc(self.config.epub_uid)
+ metadata['lang'] = self.esc(self.config.epub_language)
+ metadata['publisher'] = self.esc(self.config.epub_publisher)
+ metadata['copyright'] = self.esc(self.config.epub_copyright)
+ metadata['scheme'] = self.esc(self.config.epub_scheme)
+ metadata['id'] = self.esc(self.config.epub_identifier)
+ metadata['date'] = self.esc(time.strftime('%Y-%m-%d'))
+ metadata['files'] = files
+ metadata['spine'] = spine
+ metadata['guide'] = guide
+ return metadata
+
+ def build_content(self, outdir, outname):
+ """Write the metainfo file content.opf It contains bibliographic data,
+ a file list and the spine (the reading order).
+ """
+ self.info('writing %s file...' % outname)
+
+ # files
+ if not outdir.endswith(os.sep):
+ outdir += os.sep
+ olen = len(outdir)
+ projectfiles = []
+ self.files = []
+ self.ignored_files = ['.buildinfo',
+ 'mimetype', 'content.opf', 'toc.ncx', 'META-INF/container.xml',
+ self.config.epub_basename + '.epub'] + \
+ self.config.epub_exclude_files
+ for root, dirs, files in os.walk(outdir):
+ for fn in files:
+ filename = path.join(root, fn)[olen:]
+ if filename in self.ignored_files:
+ continue
+ ext = path.splitext(filename)[-1]
+ if ext not in _media_types:
+ # we always have JS and potentially OpenSearch files, don't
+ # always warn about them
+ if ext not in ('.js', '.xml'):
+ self.warn('unknown mimetype for %s, ignoring' % filename)
+ continue
+ filename = filename.replace(os.sep, '/')
+ projectfiles.append(_file_template % {
+ 'href': self.esc(filename),
+ 'id': self.esc(self.make_id(filename)),
+ 'media_type': self.esc(_media_types[ext])
+ })
+ self.files.append(filename)
+
+ # spine
+ spine = []
+ for item in self.refnodes:
+ if '#' in item['refuri']:
+ continue
+ if item['refuri'] in self.ignored_files:
+ continue
+ spine.append(_spine_template % {
+ 'idref': self.esc(self.make_id(item['refuri']))
+ })
+ for info in self.domain_indices:
+ spine.append(_spine_template % {
+ 'idref': self.esc(self.make_id(info[0] + self.out_suffix))
+ })
+ if self.get_builder_config('use_index', 'epub'):
+ spine.append(_spine_template % {
+ 'idref': self.esc(self.make_id('genindex' + self.out_suffix))
+ })
+
+ # add the optional cover
+ content_tmpl = _content_template
+ html_tmpl = None
+ if self.config.epub_cover:
+ image, html_tmpl = self.config.epub_cover
+ image = image.replace(os.sep, '/')
+ mpos = content_tmpl.rfind('</metadata>')
+ cpos = content_tmpl.rfind('\n', 0 , mpos) + 1
+ content_tmpl = content_tmpl[:cpos] + \
+ _cover_template % {'cover': self.esc(self.make_id(image))} + \
+ content_tmpl[cpos:]
+ if html_tmpl:
+ spine.insert(0, _spine_template % {
+ 'idref': self.esc(self.make_id(_coverpage_name))})
+ if _coverpage_name not in self.files:
+ ext = path.splitext(_coverpage_name)[-1]
+ self.files.append(_coverpage_name)
+ projectfiles.append(_file_template % {
+ 'href': self.esc(_coverpage_name),
+ 'id': self.esc(self.make_id(_coverpage_name)),
+ 'media_type': self.esc(_media_types[ext])
+ })
+ ctx = {'image': self.esc(image), 'title': self.config.project}
+ self.handle_page(
+ path.splitext(_coverpage_name)[0], ctx, html_tmpl)
+
+ guide = []
+ auto_add_cover = True
+ auto_add_toc = True
+ if self.config.epub_guide:
+ for type, uri, title in self.config.epub_guide:
+ file = uri.split('#')[0]
+ if file not in self.files:
+ self.files.append(file)
+ if type == 'cover':
+ auto_add_cover = False
+ if type == 'toc':
+ auto_add_toc = False
+ guide.append(_guide_template % {
+ 'type': self.esc(type),
+ 'title': self.esc(title),
+ 'uri': self.esc(uri)
+ })
+ if auto_add_cover and html_tmpl:
+ guide.append(_guide_template % {
+ 'type': 'cover',
+ 'title': _guide_titles['cover'],
+ 'uri': self.esc(_coverpage_name)
+ })
+ if auto_add_toc and self.refnodes:
+ guide.append(_guide_template % {
+ 'type': 'toc',
+ 'title': _guide_titles['toc'],
+ 'uri': self.esc(self.refnodes[0]['refuri'])
+ })
+ projectfiles = '\n'.join(projectfiles)
+ spine = '\n'.join(spine)
+ guide = '\n'.join(guide)
+
+ # write the project file
+ f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
+ try:
+ f.write(content_tmpl % \
+ self.content_metadata(projectfiles, spine, guide))
+ finally:
+ f.close()
+
+ def new_navpoint(self, node, level, incr=True):
+ """Create a new entry in the toc from the node at given level."""
+ # XXX Modifies the node
+ if incr:
+ self.playorder += 1
+ self.tocid += 1
+ node['indent'] = _navpoint_indent * level
+ node['navpoint'] = self.esc(_navPoint_template % self.tocid)
+ node['playorder'] = self.playorder
+ return _navpoint_template % node
+
+ def insert_subnav(self, node, subnav):
+ """Insert nested navpoints for given node.
+
+ The node and subnav are already rendered to text.
+ """
+ nlist = node.rsplit('\n', 1)
+ nlist.insert(-1, subnav)
+ return '\n'.join(nlist)
+
+ def build_navpoints(self, nodes):
+ """Create the toc navigation structure.
+
+ Subelements of a node are nested inside the navpoint. For nested nodes
+ the parent node is reinserted in the subnav.
+ """
+ navstack = []
+ navlist = []
+ level = 1
+ lastnode = None
+ for node in nodes:
+ if not node['text']:
+ continue
+ file = node['refuri'].split('#')[0]
+ if file in self.ignored_files:
+ continue
+ if node['level'] > self.config.epub_tocdepth:
+ continue
+ if node['level'] == level:
+ navlist.append(self.new_navpoint(node, level))
+ elif node['level'] == level + 1:
+ navstack.append(navlist)
+ navlist = []
+ level += 1
+ if lastnode and self.config.epub_tocdup:
+ # Insert starting point in subtoc with same playOrder
+ navlist.append(self.new_navpoint(lastnode, level, False))
+ navlist.append(self.new_navpoint(node, level))
+ else:
+ while node['level'] < level:
+ subnav = '\n'.join(navlist)
+ navlist = navstack.pop()
+ navlist[-1] = self.insert_subnav(navlist[-1], subnav)
+ level -= 1
+ navlist.append(self.new_navpoint(node, level))
+ lastnode = node
+ while level != 1:
+ subnav = '\n'.join(navlist)
+ navlist = navstack.pop()
+ navlist[-1] = self.insert_subnav(navlist[-1], subnav)
+ level -= 1
+ return '\n'.join(navlist)
+
+ def toc_metadata(self, level, navpoints):
+ """Create a dictionary with all metadata for the toc.ncx file
+ properly escaped.
+ """
+ metadata = {}
+ metadata['uid'] = self.config.epub_uid
+ metadata['title'] = self.config.epub_title
+ metadata['level'] = level
+ metadata['navpoints'] = navpoints
+ return metadata
+
+ def build_toc(self, outdir, outname):
+ """Write the metainfo file toc.ncx."""
+ self.info('writing %s file...' % outname)
+
+ if self.config.epub_tocscope == 'default':
+ doctree = self.env.get_and_resolve_doctree(self.config.master_doc,
+ self, prune_toctrees=False, includehidden=False)
+ refnodes = self.get_refnodes(doctree, [])
+ self.toc_add_files(refnodes)
+ else:
+ # 'includehidden'
+ refnodes = self.refnodes
+ navpoints = self.build_navpoints(refnodes)
+ level = max(item['level'] for item in self.refnodes)
+ level = min(level, self.config.epub_tocdepth)
+ f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
+ try:
+ f.write(_toc_template % self.toc_metadata(level, navpoints))
+ finally:
+ f.close()
+
+ def build_epub(self, outdir, outname):
+ """Write the epub file.
+
+ It is a zip file with the mimetype file stored uncompressed as the first
+ entry.
+ """
+ self.info('writing %s file...' % outname)
+ projectfiles = ['META-INF/container.xml', 'content.opf', 'toc.ncx'] \
+ + self.files
+ epub = zipfile.ZipFile(path.join(outdir, outname), 'w', \
+ zipfile.ZIP_DEFLATED)
+ epub.write(path.join(outdir, 'mimetype'), 'mimetype', \
+ zipfile.ZIP_STORED)
+ for file in projectfiles:
+ fp = path.join(outdir, file)
+ if sys.version_info < (2, 6):
+ # When zipile.ZipFile.write call with unicode filename, ZipFile
+ # encode filename to 'utf-8' (only after Python-2.6).
+ if isinstance(file, unicode):
+ # OEBPS Container Format (OCF) 2.0.1 specification require
+ # "File Names MUST be UTF-8 encoded".
+ file = file.encode('utf-8')
+ epub.write(fp, file, zipfile.ZIP_DEFLATED)
+ epub.close()
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
new file mode 100644
index 0000000..250bef8
--- /dev/null
+++ b/sphinx/builders/gettext.py
@@ -0,0 +1,218 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.gettext
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ The MessageCatalogBuilder class.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from __future__ import with_statement
+
+from os import path, walk
+from codecs import open
+from time import time
+from datetime import datetime, tzinfo, timedelta
+from collections import defaultdict
+from uuid import uuid4
+
+from sphinx.builders import Builder
+from sphinx.util import split_index_msg
+from sphinx.util.nodes import extract_messages, traverse_translatable_index
+from sphinx.util.osutil import safe_relpath, ensuredir, find_catalog, SEP
+from sphinx.util.console import darkgreen, purple, bold
+from sphinx.locale import pairindextypes
+
+POHEADER = ur"""
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) %(copyright)s
+# This file is distributed under the same license as the %(project)s package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: %(project)s %(version)s\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: %(ctime)s\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+"""[1:]
+
+
+class Catalog(object):
+ """Catalog of translatable messages."""
+
+ def __init__(self):
+ self.messages = [] # retain insertion order, a la OrderedDict
+ self.metadata = {} # msgid -> file, line, uid
+
+ def add(self, msg, origin):
+ if not hasattr(origin, 'uid'):
+ # Nodes that are replicated like todo don't have a uid,
+ # however i18n is also unnecessary.
+ return
+ if msg not in self.metadata: # faster lookup in hash
+ self.messages.append(msg)
+ self.metadata[msg] = []
+ self.metadata[msg].append((origin.source, origin.line, origin.uid))
+
+
+class MsgOrigin(object):
+ """
+ Origin holder for Catalog message origin.
+ """
+
+ def __init__(self, source, line):
+ self.source = source
+ self.line = line
+ self.uid = uuid4().hex
+
+
+class I18nBuilder(Builder):
+ """
+ General i18n builder.
+ """
+ name = 'i18n'
+ versioning_method = 'text'
+
+ def init(self):
+ Builder.init(self)
+ self.catalogs = defaultdict(Catalog)
+
+ def get_target_uri(self, docname, typ=None):
+ return ''
+
+ def get_outdated_docs(self):
+ return self.env.found_docs
+
+ def prepare_writing(self, docnames):
+ return
+
+ def write_doc(self, docname, doctree):
+ catalog = self.catalogs[find_catalog(docname,
+ self.config.gettext_compact)]
+
+ for node, msg in extract_messages(doctree):
+ catalog.add(msg, node)
+
+ # Extract translatable messages from index entries.
+ for node, entries in traverse_translatable_index(doctree):
+ for typ, msg, tid, main in entries:
+ for m in split_index_msg(typ, msg):
+ if typ == 'pair' and m in pairindextypes.values():
+ # avoid built-in translated message was incorporated
+ # in 'sphinx.util.nodes.process_index_entry'
+ continue
+ catalog.add(m, node)
+
+
+# determine tzoffset once to remain unaffected by DST change during build
+timestamp = time()
+tzdelta = datetime.fromtimestamp(timestamp) - \
+ datetime.utcfromtimestamp(timestamp)
+
+class LocalTimeZone(tzinfo):
+
+ def __init__(self, *args, **kw):
+ super(LocalTimeZone, self).__init__(*args, **kw)
+ self.tzdelta = tzdelta
+
+ def utcoffset(self, dt):
+ return self.tzdelta
+
+ def dst(self, dt):
+ return timedelta(0)
+
+ltz = LocalTimeZone()
+
+
+class MessageCatalogBuilder(I18nBuilder):
+ """
+ Builds gettext-style message catalogs (.pot files).
+ """
+ name = 'gettext'
+
+ def init(self):
+ I18nBuilder.init(self)
+ self.create_template_bridge()
+ self.templates.init(self)
+
+ def _collect_templates(self):
+ template_files = set()
+ for template_path in self.config.templates_path:
+ tmpl_abs_path = path.join(self.app.srcdir, template_path)
+ for dirpath, dirs, files in walk(tmpl_abs_path):
+ for fn in files:
+ if fn.endswith('.html'):
+ filename = path.join(dirpath, fn)
+ filename = filename.replace(path.sep, SEP)
+ template_files.add(filename)
+ return template_files
+
+ def _extract_from_template(self):
+ files = self._collect_templates()
+ self.info(bold('building [%s]: ' % self.name), nonl=1)
+ self.info('targets for %d template files' % len(files))
+
+ extract_translations = self.templates.environment.extract_translations
+
+ for template in self.status_iterator(files,
+ 'reading templates... ', purple, len(files)):
+ with open(template, 'r', encoding='utf-8') as f:
+ context = f.read()
+ for line, meth, msg in extract_translations(context):
+ origin = MsgOrigin(template, line)
+ self.catalogs['sphinx'].add(msg, origin)
+
+ def build(self, docnames, summary=None, method='update'):
+ self._extract_from_template()
+ I18nBuilder.build(self, docnames, summary, method)
+
+ def finish(self):
+ I18nBuilder.finish(self)
+ data = dict(
+ version = self.config.version,
+ copyright = self.config.copyright,
+ project = self.config.project,
+ ctime = datetime.fromtimestamp(
+ timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
+ )
+ for textdomain, catalog in self.status_iterator(
+ self.catalogs.iteritems(), "writing message catalogs... ",
+ darkgreen, len(self.catalogs),
+ lambda (textdomain, _): textdomain):
+ # noop if config.gettext_compact is set
+ ensuredir(path.join(self.outdir, path.dirname(textdomain)))
+
+ pofn = path.join(self.outdir, textdomain + '.pot')
+ pofile = open(pofn, 'w', encoding='utf-8')
+ try:
+ pofile.write(POHEADER % data)
+
+ for message in catalog.messages:
+ positions = catalog.metadata[message]
+
+ # generate "#: file1:line1\n#: file2:line2 ..."
+ pofile.write(u"#: %s\n" % "\n#: ".join("%s:%s" %
+ (safe_relpath(source, self.outdir), line)
+ for source, line, _ in positions))
+ # generate "# uuid1\n# uuid2\n ..."
+ pofile.write(u"# %s\n" % "\n# ".join(uid for _, _, uid
+ in positions))
+
+ # message contains *one* line of text ready for translation
+ message = message.replace(u'\\', ur'\\'). \
+ replace(u'"', ur'\"'). \
+ replace(u'\n', u'\\n"\n"')
+ pofile.write(u'msgid "%s"\nmsgstr ""\n\n' % message)
+
+ finally:
+ pofile.close()
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
new file mode 100644
index 0000000..9c039e3
--- /dev/null
+++ b/sphinx/builders/html.py
@@ -0,0 +1,1107 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.html
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Several HTML builders.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import sys
+import zlib
+import codecs
+import posixpath
+import cPickle as pickle
+from os import path
+try:
+ from hashlib import md5
+except ImportError:
+ # 2.4 compatibility
+ from md5 import md5
+
+from docutils import nodes
+from docutils.io import DocTreeInput, StringOutput
+from docutils.core import Publisher
+from docutils.utils import new_document
+from docutils.frontend import OptionParser
+from docutils.readers.doctree import Reader as DoctreeReader
+
+from sphinx import package_dir, __version__
+from sphinx.util import jsonimpl, copy_static_entry
+from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \
+ movefile, ustrftime, copyfile
+from sphinx.util.nodes import inline_all_toctrees
+from sphinx.util.matching import patmatch, compile_matchers
+from sphinx.util.pycompat import any, b
+from sphinx.errors import SphinxError
+from sphinx.locale import _
+from sphinx.search import js_index
+from sphinx.theming import Theme
+from sphinx.builders import Builder
+from sphinx.application import ENV_PICKLE_FILENAME
+from sphinx.highlighting import PygmentsBridge
+from sphinx.util.console import bold, darkgreen, brown
+from sphinx.writers.html import HTMLWriter, HTMLTranslator, \
+ SmartyPantsHTMLTranslator
+
+#: the filename for the inventory of objects
+INVENTORY_FILENAME = 'objects.inv'
+#: the filename for the "last build" file (for serializing builders)
+LAST_BUILD_FILENAME = 'last_build'
+
+
+def get_stable_hash(obj):
+ """
+ Return a stable hash for a Python data structure. We can't just use
+ the md5 of str(obj) since for example dictionary items are enumerated
+ in unpredictable order due to hash randomization in newer Pythons.
+ """
+ if isinstance(obj, dict):
+ return get_stable_hash(list(obj.items()))
+ elif isinstance(obj, (list, tuple)):
+ obj = sorted(get_stable_hash(o) for o in obj)
+ return md5(unicode(obj).encode('utf8')).hexdigest()
+
+
+class StandaloneHTMLBuilder(Builder):
+ """
+ Builds standalone HTML docs.
+ """
+ name = 'html'
+ format = 'html'
+ copysource = True
+ allow_parallel = True
+ out_suffix = '.html'
+ link_suffix = '.html' # defaults to matching out_suffix
+ indexer_format = js_index
+ indexer_dumps_unicode = True
+ supported_image_types = ['image/svg+xml', 'image/png',
+ 'image/gif', 'image/jpeg']
+ searchindex_filename = 'searchindex.js'
+ add_permalinks = True
+ embedded = False # for things like HTML help or Qt help: suppresses sidebar
+
+ # This is a class attribute because it is mutated by Sphinx.add_javascript.
+ script_files = ['_static/jquery.js', '_static/underscore.js',
+ '_static/doctools.js']
+ # Dito for this one.
+ css_files = []
+
+ default_sidebars = ['localtoc.html', 'relations.html',
+ 'sourcelink.html', 'searchbox.html']
+
+ # cached publisher object for snippets
+ _publisher = None
+
+ def init(self):
+ # a hash of all config values that, if changed, cause a full rebuild
+ self.config_hash = ''
+ self.tags_hash = ''
+ # section numbers for headings in the currently visited document
+ self.secnumbers = {}
+ # currently written docname
+ self.current_docname = None
+
+ self.init_templates()
+ self.init_highlighter()
+ self.init_translator_class()
+ if self.config.html_file_suffix is not None:
+ self.out_suffix = self.config.html_file_suffix
+
+ if self.config.html_link_suffix is not None:
+ self.link_suffix = self.config.html_link_suffix
+ else:
+ self.link_suffix = self.out_suffix
+
+ if self.config.language is not None:
+ if self._get_translations_js():
+ self.script_files.append('_static/translations.js')
+
+ def _get_translations_js(self):
+ candidates = [path.join(package_dir, 'locale', self.config.language,
+ 'LC_MESSAGES', 'sphinx.js'),
+ path.join(sys.prefix, 'share/sphinx/locale',
+ self.config.language, 'sphinx.js')] + \
+ [path.join(dir, self.config.language,
+ 'LC_MESSAGES', 'sphinx.js')
+ for dir in self.config.locale_dirs]
+ for jsfile in candidates:
+ if path.isfile(jsfile):
+ return jsfile
+ return None
+
+ def get_theme_config(self):
+ return self.config.html_theme, self.config.html_theme_options
+
+ def init_templates(self):
+ Theme.init_themes(self.confdir, self.config.html_theme_path,
+ warn=self.warn)
+ themename, themeoptions = self.get_theme_config()
+ self.theme = Theme(themename)
+ self.theme_options = themeoptions.copy()
+ self.create_template_bridge()
+ self.templates.init(self, self.theme)
+
+ def init_highlighter(self):
+ # determine Pygments style and create the highlighter
+ if self.config.pygments_style is not None:
+ style = self.config.pygments_style
+ elif self.theme:
+ style = self.theme.get_confstr('theme', 'pygments_style', 'none')
+ else:
+ style = 'sphinx'
+ self.highlighter = PygmentsBridge('html', style,
+ self.config.trim_doctest_flags)
+
+ def init_translator_class(self):
+ if self.config.html_translator_class:
+ self.translator_class = self.app.import_object(
+ self.config.html_translator_class,
+ 'html_translator_class setting')
+ elif self.config.html_use_smartypants:
+ self.translator_class = SmartyPantsHTMLTranslator
+ else:
+ self.translator_class = HTMLTranslator
+
+ def get_outdated_docs(self):
+ cfgdict = dict((name, self.config[name])
+ for (name, desc) in self.config.values.iteritems()
+ if desc[1] == 'html')
+ self.config_hash = get_stable_hash(cfgdict)
+ self.tags_hash = get_stable_hash(sorted(self.tags))
+ old_config_hash = old_tags_hash = ''
+ try:
+ fp = open(path.join(self.outdir, '.buildinfo'))
+ try:
+ version = fp.readline()
+ if version.rstrip() != '# Sphinx build info version 1':
+ raise ValueError
+ fp.readline() # skip commentary
+ cfg, old_config_hash = fp.readline().strip().split(': ')
+ if cfg != 'config':
+ raise ValueError
+ tag, old_tags_hash = fp.readline().strip().split(': ')
+ if tag != 'tags':
+ raise ValueError
+ finally:
+ fp.close()
+ except ValueError:
+ self.warn('unsupported build info format in %r, building all' %
+ path.join(self.outdir, '.buildinfo'))
+ except Exception:
+ pass
+ if old_config_hash != self.config_hash or \
+ old_tags_hash != self.tags_hash:
+ for docname in self.env.found_docs:
+ yield docname
+ return
+
+ if self.templates:
+ template_mtime = self.templates.newest_template_mtime()
+ else:
+ template_mtime = 0
+ for docname in self.env.found_docs:
+ if docname not in self.env.all_docs:
+ yield docname
+ continue
+ targetname = self.get_outfilename(docname)
+ try:
+ targetmtime = path.getmtime(targetname)
+ except Exception:
+ targetmtime = 0
+ try:
+ srcmtime = max(path.getmtime(self.env.doc2path(docname)),
+ template_mtime)
+ if srcmtime > targetmtime:
+ yield docname
+ except EnvironmentError:
+ # source doesn't exist anymore
+ pass
+
+ def render_partial(self, node):
+ """Utility: Render a lone doctree node."""
+ if node is None:
+ return {'fragment': ''}
+ doc = new_document(b('<partial node>'))
+ doc.append(node)
+
+ if self._publisher is None:
+ self._publisher = Publisher(
+ source_class = DocTreeInput,
+ destination_class=StringOutput)
+ self._publisher.set_components('standalone',
+ 'restructuredtext', 'pseudoxml')
+
+ pub = self._publisher
+
+ pub.reader = DoctreeReader()
+ pub.writer = HTMLWriter(self)
+ pub.process_programmatic_settings(
+ None, {'output_encoding': 'unicode'}, None)
+ pub.set_source(doc, None)
+ pub.set_destination(None, None)
+ pub.publish()
+ return pub.writer.parts
+
+ def prepare_writing(self, docnames):
+ # create the search indexer
+ from sphinx.search import IndexBuilder, languages
+ lang = self.config.html_search_language or self.config.language
+ if not lang or lang not in languages:
+ lang = 'en'
+ self.indexer = IndexBuilder(self.env, lang,
+ self.config.html_search_options,
+ self.config.html_search_scorer)
+ self.load_indexer(docnames)
+
+ self.docwriter = HTMLWriter(self)
+ self.docsettings = OptionParser(
+ defaults=self.env.settings,
+ components=(self.docwriter,),
+ read_config_files=True).get_default_values()
+ self.docsettings.compact_lists = bool(self.config.html_compact_lists)
+
+ # determine the additional indices to include
+ self.domain_indices = []
+ # html_domain_indices can be False/True or a list of index names
+ indices_config = self.config.html_domain_indices
+ if indices_config:
+ for domain in self.env.domains.itervalues():
+ for indexcls in domain.indices:
+ indexname = '%s-%s' % (domain.name, indexcls.name)
+ if isinstance(indices_config, list):
+ if indexname not in indices_config:
+ continue
+ # deprecated config value
+ if indexname == 'py-modindex' and \
+ not self.config.html_use_modindex:
+ continue
+ content, collapse = indexcls(domain).generate()
+ if content:
+ self.domain_indices.append(
+ (indexname, indexcls, content, collapse))
+
+ # format the "last updated on" string, only once is enough since it
+ # typically doesn't include the time of day
+ lufmt = self.config.html_last_updated_fmt
+ if lufmt is not None:
+ self.last_updated = ustrftime(lufmt or _('%b %d, %Y'))
+ else:
+ self.last_updated = None
+
+ logo = self.config.html_logo and \
+ path.basename(self.config.html_logo) or ''
+
+ favicon = self.config.html_favicon and \
+ path.basename(self.config.html_favicon) or ''
+ if favicon and os.path.splitext(favicon)[1] != '.ico':
+ self.warn('html_favicon is not an .ico file')
+
+ if not isinstance(self.config.html_use_opensearch, basestring):
+ self.warn('html_use_opensearch config value must now be a string')
+
+ self.relations = self.env.collect_relations()
+
+ rellinks = []
+ if self.get_builder_config('use_index', 'html'):
+ rellinks.append(('genindex', _('General Index'), 'I', _('index')))
+ for indexname, indexcls, content, collapse in self.domain_indices:
+ # if it has a short name
+ if indexcls.shortname:
+ rellinks.append((indexname, indexcls.localname,
+ '', indexcls.shortname))
+
+ if self.config.html_style is not None:
+ stylename = self.config.html_style
+ elif self.theme:
+ stylename = self.theme.get_confstr('theme', 'stylesheet')
+ else:
+ stylename = 'default.css'
+
+ self.globalcontext = dict(
+ embedded = self.embedded,
+ project = self.config.project,
+ release = self.config.release,
+ version = self.config.version,
+ last_updated = self.last_updated,
+ copyright = self.config.copyright,
+ master_doc = self.config.master_doc,
+ use_opensearch = self.config.html_use_opensearch,
+ docstitle = self.config.html_title,
+ shorttitle = self.config.html_short_title,
+ show_copyright = self.config.html_show_copyright,
+ show_sphinx = self.config.html_show_sphinx,
+ has_source = self.config.html_copy_source,
+ show_source = self.config.html_show_sourcelink,
+ file_suffix = self.out_suffix,
+ script_files = self.script_files,
+ css_files = self.css_files,
+ sphinx_version = __version__,
+ style = stylename,
+ rellinks = rellinks,
+ builder = self.name,
+ parents = [],
+ logo = logo,
+ favicon = favicon,
+ )
+ if self.theme:
+ self.globalcontext.update(
+ ('theme_' + key, val) for (key, val) in
+ self.theme.get_options(self.theme_options).iteritems())
+ self.globalcontext.update(self.config.html_context)
+
+ def get_doc_context(self, docname, body, metatags):
+ """Collect items for the template context of a page."""
+ # find out relations
+ prev = next = None
+ parents = []
+ rellinks = self.globalcontext['rellinks'][:]
+ related = self.relations.get(docname)
+ titles = self.env.titles
+ if related and related[2]:
+ try:
+ next = {
+ 'link': self.get_relative_uri(docname, related[2]),
+ 'title': self.render_partial(titles[related[2]])['title']
+ }
+ rellinks.append((related[2], next['title'], 'N', _('next')))
+ except KeyError:
+ next = None
+ if related and related[1]:
+ try:
+ prev = {
+ 'link': self.get_relative_uri(docname, related[1]),
+ 'title': self.render_partial(titles[related[1]])['title']
+ }
+ rellinks.append((related[1], prev['title'], 'P', _('previous')))
+ except KeyError:
+ # the relation is (somehow) not in the TOC tree, handle
+ # that gracefully
+ prev = None
+ while related and related[0]:
+ try:
+ parents.append(
+ {'link': self.get_relative_uri(docname, related[0]),
+ 'title': self.render_partial(titles[related[0]])['title']})
+ except KeyError:
+ pass
+ related = self.relations.get(related[0])
+ if parents:
+ parents.pop() # remove link to the master file; we have a generic
+ # "back to index" link already
+ parents.reverse()
+
+ # title rendered as HTML
+ title = self.env.longtitles.get(docname)
+ title = title and self.render_partial(title)['title'] or ''
+ # the name for the copied source
+ sourcename = self.config.html_copy_source and docname + '.txt' or ''
+
+ # metadata for the document
+ meta = self.env.metadata.get(docname)
+
+ # local TOC and global TOC tree
+ self_toc = self.env.get_toc_for(docname, self)
+ toc = self.render_partial(self_toc)['fragment']
+
+ return dict(
+ parents = parents,
+ prev = prev,
+ next = next,
+ title = title,
+ meta = meta,
+ body = body,
+ metatags = metatags,
+ rellinks = rellinks,
+ sourcename = sourcename,
+ toc = toc,
+ # only display a TOC if there's more than one item to show
+ display_toc = (self.env.toc_num_entries[docname] > 1),
+ )
+
+ def write_doc(self, docname, doctree):
+ destination = StringOutput(encoding='utf-8')
+ doctree.settings = self.docsettings
+
+ self.secnumbers = self.env.toc_secnumbers.get(docname, {})
+ self.imgpath = relative_uri(self.get_target_uri(docname), '_images')
+ self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads')
+ self.current_docname = docname
+ self.docwriter.write(doctree, destination)
+ self.docwriter.assemble_parts()
+ body = self.docwriter.parts['fragment']
+ metatags = self.docwriter.clean_meta
+
+ ctx = self.get_doc_context(docname, body, metatags)
+ self.handle_page(docname, ctx, event_arg=doctree)
+
+ def write_doc_serialized(self, docname, doctree):
+ self.imgpath = relative_uri(self.get_target_uri(docname), '_images')
+ self.post_process_images(doctree)
+ title = self.env.longtitles.get(docname)
+ title = title and self.render_partial(title)['title'] or ''
+ self.index_page(docname, doctree, title)
+
+ def finish(self):
+ self.info(bold('writing additional files...'), nonl=1)
+
+ # pages from extensions
+ for pagelist in self.app.emit('html-collect-pages'):
+ for pagename, context, template in pagelist:
+ self.handle_page(pagename, context, template)
+
+ # the global general index
+ if self.get_builder_config('use_index', 'html'):
+ self.write_genindex()
+
+ # the global domain-specific indices
+ self.write_domain_indices()
+
+ # the search page
+ if self.name != 'htmlhelp':
+ self.info(' search', nonl=1)
+ self.handle_page('search', {}, 'search.html')
+
+ # additional pages from conf.py
+ for pagename, template in self.config.html_additional_pages.items():
+ self.info(' '+pagename, nonl=1)
+ self.handle_page(pagename, {}, template)
+
+ if self.config.html_use_opensearch and self.name != 'htmlhelp':
+ self.info(' opensearch', nonl=1)
+ fn = path.join(self.outdir, '_static', 'opensearch.xml')
+ self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
+
+ self.info()
+
+ self.copy_image_files()
+ self.copy_download_files()
+ self.copy_static_files()
+ self.copy_extra_files()
+ self.write_buildinfo()
+
+ # dump the search index
+ self.handle_finish()
+
+ def write_genindex(self):
+ # the total count of lines for each index letter, used to distribute
+ # the entries into two columns
+ genindex = self.env.create_index(self)
+ indexcounts = []
+ for _, entries in genindex:
+ indexcounts.append(sum(1 + len(subitems)
+ for _, (_, subitems) in entries))
+
+ genindexcontext = dict(
+ genindexentries = genindex,
+ genindexcounts = indexcounts,
+ split_index = self.config.html_split_index,
+ )
+ self.info(' genindex', nonl=1)
+
+ if self.config.html_split_index:
+ self.handle_page('genindex', genindexcontext,
+ 'genindex-split.html')
+ self.handle_page('genindex-all', genindexcontext,
+ 'genindex.html')
+ for (key, entries), count in zip(genindex, indexcounts):
+ ctx = {'key': key, 'entries': entries, 'count': count,
+ 'genindexentries': genindex}
+ self.handle_page('genindex-' + key, ctx,
+ 'genindex-single.html')
+ else:
+ self.handle_page('genindex', genindexcontext, 'genindex.html')
+
+ def write_domain_indices(self):
+ for indexname, indexcls, content, collapse in self.domain_indices:
+ indexcontext = dict(
+ indextitle = indexcls.localname,
+ content = content,
+ collapse_index = collapse,
+ )
+ self.info(' ' + indexname, nonl=1)
+ self.handle_page(indexname, indexcontext, 'domainindex.html')
+
+ def copy_image_files(self):
+ # copy image files
+ if self.images:
+ ensuredir(path.join(self.outdir, '_images'))
+ for src in self.status_iterator(self.images, 'copying images... ',
+ brown, len(self.images)):
+ dest = self.images[src]
+ try:
+ copyfile(path.join(self.srcdir, src),
+ path.join(self.outdir, '_images', dest))
+ except Exception, err:
+ self.warn('cannot copy image file %r: %s' %
+ (path.join(self.srcdir, src), err))
+
+ def copy_download_files(self):
+ # copy downloadable files
+ if self.env.dlfiles:
+ ensuredir(path.join(self.outdir, '_downloads'))
+ for src in self.status_iterator(self.env.dlfiles,
+ 'copying downloadable files... ',
+ brown, len(self.env.dlfiles)):
+ dest = self.env.dlfiles[src][1]
+ try:
+ copyfile(path.join(self.srcdir, src),
+ path.join(self.outdir, '_downloads', dest))
+ except Exception, err:
+ self.warn('cannot copy downloadable file %r: %s' %
+ (path.join(self.srcdir, src), err))
+
+ def copy_static_files(self):
+ # copy static files
+ self.info(bold('copying static files... '), nonl=True)
+ ensuredir(path.join(self.outdir, '_static'))
+ # first, create pygments style file
+ f = open(path.join(self.outdir, '_static', 'pygments.css'), 'w')
+ f.write(self.highlighter.get_stylesheet())
+ f.close()
+ # then, copy translations JavaScript file
+ if self.config.language is not None:
+ jsfile = self._get_translations_js()
+ if jsfile:
+ copyfile(jsfile, path.join(self.outdir, '_static',
+ 'translations.js'))
+
+ # add context items for search function used in searchtools.js_t
+ ctx = self.globalcontext.copy()
+ ctx.update(self.indexer.context_for_searchtool())
+
+ # then, copy over theme-supplied static files
+ if self.theme:
+ themeentries = [path.join(themepath, 'static')
+ for themepath in self.theme.get_dirchain()[::-1]]
+ for entry in themeentries:
+ copy_static_entry(entry, path.join(self.outdir, '_static'),
+ self, ctx)
+ # then, copy over all user-supplied static files
+ staticentries = [path.join(self.confdir, spath)
+ for spath in self.config.html_static_path]
+ matchers = compile_matchers(
+ self.config.exclude_patterns +
+ ['**/' + d for d in self.config.exclude_dirnames]
+ )
+ for entry in staticentries:
+ if not path.exists(entry):
+ self.warn('html_static_path entry %r does not exist' % entry)
+ continue
+ copy_static_entry(entry, path.join(self.outdir, '_static'), self,
+ ctx, exclude_matchers=matchers)
+ # copy logo and favicon files if not already in static path
+ if self.config.html_logo:
+ logobase = path.basename(self.config.html_logo)
+ logotarget = path.join(self.outdir, '_static', logobase)
+ if not path.isfile(path.join(self.confdir, self.config.html_logo)):
+ self.warn('logo file %r does not exist' % self.config.html_logo)
+ elif not path.isfile(logotarget):
+ copyfile(path.join(self.confdir, self.config.html_logo),
+ logotarget)
+ if self.config.html_favicon:
+ iconbase = path.basename(self.config.html_favicon)
+ icontarget = path.join(self.outdir, '_static', iconbase)
+ if not path.isfile(path.join(self.confdir, self.config.html_favicon)):
+ self.warn('favicon file %r does not exist' % self.config.html_favicon)
+ elif not path.isfile(icontarget):
+ copyfile(path.join(self.confdir, self.config.html_favicon),
+ icontarget)
+ self.info('done')
+
+ def copy_extra_files(self):
+ # copy html_extra_path files
+ self.info(bold('copying extra files... '), nonl=True)
+ extraentries = [path.join(self.confdir, epath)
+ for epath in self.config.html_extra_path]
+ for entry in extraentries:
+ if not path.exists(entry):
+ self.warn('html_extra_path entry %r does not exist' % entry)
+ continue
+ copy_static_entry(entry, self.outdir, self)
+ self.info('done')
+
+ def write_buildinfo(self):
+ # write build info file
+ fp = open(path.join(self.outdir, '.buildinfo'), 'w')
+ try:
+ fp.write('# Sphinx build info version 1\n'
+ '# This file hashes the configuration used when building'
+ ' these files. When it is not found, a full rebuild will'
+ ' be done.\nconfig: %s\ntags: %s\n' %
+ (self.config_hash, self.tags_hash))
+ finally:
+ fp.close()
+
+ def cleanup(self):
+ # clean up theme stuff
+ if self.theme:
+ self.theme.cleanup()
+
+ def post_process_images(self, doctree):
+ """Pick the best candidate for an image and link down-scaled images to
+ their high res version.
+ """
+ Builder.post_process_images(self, doctree)
+ for node in doctree.traverse(nodes.image):
+ scale_keys = ('scale', 'width', 'height')
+ if not any((key in node) for key in scale_keys) or \
+ isinstance(node.parent, nodes.reference):
+ # docutils does unfortunately not preserve the
+ # ``target`` attribute on images, so we need to check
+ # the parent node here.
+ continue
+ uri = node['uri']
+ reference = nodes.reference('', '', internal=True)
+ if uri in self.images:
+ reference['refuri'] = posixpath.join(self.imgpath,
+ self.images[uri])
+ else:
+ reference['refuri'] = uri
+ node.replace_self(reference)
+ reference.append(node)
+
+ def load_indexer(self, docnames):
+ keep = set(self.env.all_docs) - set(docnames)
+ try:
+ searchindexfn = path.join(self.outdir, self.searchindex_filename)
+ if self.indexer_dumps_unicode:
+ f = codecs.open(searchindexfn, 'r', encoding='utf-8')
+ else:
+ f = open(searchindexfn, 'rb')
+ try:
+ self.indexer.load(f, self.indexer_format)
+ finally:
+ f.close()
+ except (IOError, OSError, ValueError):
+ if keep:
+ self.warn('search index couldn\'t be loaded, but not all '
+ 'documents will be built: the index will be '
+ 'incomplete.')
+ # delete all entries for files that will be rebuilt
+ self.indexer.prune(keep)
+
+ def index_page(self, pagename, doctree, title):
+ # only index pages with title
+ if self.indexer is not None and title:
+ self.indexer.feed(pagename, title, doctree)
+
+ def _get_local_toctree(self, docname, collapse=True, **kwds):
+ if 'includehidden' not in kwds:
+ kwds['includehidden'] = False
+ return self.render_partial(self.env.get_toctree_for(
+ docname, self, collapse, **kwds))['fragment']
+
+ def get_outfilename(self, pagename):
+ return path.join(self.outdir, os_path(pagename) + self.out_suffix)
+
+ def add_sidebars(self, pagename, ctx):
+ def has_wildcard(pattern):
+ return any(char in pattern for char in '*?[')
+ sidebars = None
+ matched = None
+ customsidebar = None
+ for pattern, patsidebars in self.config.html_sidebars.iteritems():
+ if patmatch(pagename, pattern):
+ if matched:
+ if has_wildcard(pattern):
+ # warn if both patterns contain wildcards
+ if has_wildcard(matched):
+ self.warn('page %s matches two patterns in '
+ 'html_sidebars: %r and %r' %
+ (pagename, matched, pattern))
+ # else the already matched pattern is more specific
+ # than the present one, because it contains no wildcard
+ continue
+ matched = pattern
+ sidebars = patsidebars
+ if sidebars is None:
+ # keep defaults
+ pass
+ elif isinstance(sidebars, basestring):
+ # 0.x compatible mode: insert custom sidebar before searchbox
+ customsidebar = sidebars
+ sidebars = None
+ ctx['sidebars'] = sidebars
+ ctx['customsidebar'] = customsidebar
+
+ # --------- these are overwritten by the serialization builder
+
+ def get_target_uri(self, docname, typ=None):
+ return docname + self.link_suffix
+
+ def handle_page(self, pagename, addctx, templatename='page.html',
+ outfilename=None, event_arg=None):
+ ctx = self.globalcontext.copy()
+ # current_page_name is backwards compatibility
+ ctx['pagename'] = ctx['current_page_name'] = pagename
+ default_baseuri = self.get_target_uri(pagename)
+ # in the singlehtml builder, default_baseuri still contains an #anchor
+ # part, which relative_uri doesn't really like...
+ default_baseuri = default_baseuri.rsplit('#', 1)[0]
+
+ def pathto(otheruri, resource=False, baseuri=default_baseuri):
+ if resource and '://' in otheruri:
+ # allow non-local resources given by scheme
+ return otheruri
+ elif not resource:
+ otheruri = self.get_target_uri(otheruri)
+ uri = relative_uri(baseuri, otheruri) or '#'
+ return uri
+ ctx['pathto'] = pathto
+ ctx['hasdoc'] = lambda name: name in self.env.all_docs
+ if self.name != 'htmlhelp':
+ ctx['encoding'] = encoding = self.config.html_output_encoding
+ else:
+ ctx['encoding'] = encoding = self.encoding
+ ctx['toctree'] = lambda **kw: self._get_local_toctree(pagename, **kw)
+ self.add_sidebars(pagename, ctx)
+ ctx.update(addctx)
+
+ self.app.emit('html-page-context', pagename, templatename,
+ ctx, event_arg)
+
+ try:
+ output = self.templates.render(templatename, ctx)
+ except UnicodeError:
+ self.warn("a Unicode error occurred when rendering the page %s. "
+ "Please make sure all config values that contain "
+ "non-ASCII content are Unicode strings." % pagename)
+ return
+
+ if not outfilename:
+ outfilename = self.get_outfilename(pagename)
+ # outfilename's path is in general different from self.outdir
+ ensuredir(path.dirname(outfilename))
+ try:
+ f = codecs.open(outfilename, 'w', encoding, 'xmlcharrefreplace')
+ try:
+ f.write(output)
+ finally:
+ f.close()
+ except (IOError, OSError), err:
+ self.warn("error writing file %s: %s" % (outfilename, err))
+ if self.copysource and ctx.get('sourcename'):
+ # copy the source file for the "show source" link
+ source_name = path.join(self.outdir, '_sources',
+ os_path(ctx['sourcename']))
+ ensuredir(path.dirname(source_name))
+ copyfile(self.env.doc2path(pagename), source_name)
+
+ def handle_finish(self):
+ self.dump_search_index()
+ self.dump_inventory()
+
+ def dump_inventory(self):
+ self.info(bold('dumping object inventory... '), nonl=True)
+ f = open(path.join(self.outdir, INVENTORY_FILENAME), 'wb')
+ try:
+ f.write((u'# Sphinx inventory version 2\n'
+ u'# Project: %s\n'
+ u'# Version: %s\n'
+ u'# The remainder of this file is compressed using zlib.\n'
+ % (self.config.project, self.config.version)
+ ).encode('utf-8'))
+ compressor = zlib.compressobj(9)
+ for domainname, domain in self.env.domains.iteritems():
+ for name, dispname, type, docname, anchor, prio in \
+ domain.get_objects():
+ if anchor.endswith(name):
+ # this can shorten the inventory by as much as 25%
+ anchor = anchor[:-len(name)] + '$'
+ uri = self.get_target_uri(docname) + '#' + anchor
+ if dispname == name:
+ dispname = u'-'
+ f.write(compressor.compress(
+ (u'%s %s:%s %s %s %s\n' % (name, domainname, type,
+ prio, uri, dispname)
+ ).encode('utf-8')))
+ f.write(compressor.flush())
+ finally:
+ f.close()
+ self.info('done')
+
+ def dump_search_index(self):
+ self.info(bold('dumping search index... '), nonl=True)
+ self.indexer.prune(self.env.all_docs)
+ searchindexfn = path.join(self.outdir, self.searchindex_filename)
+ # first write to a temporary file, so that if dumping fails,
+ # the existing index won't be overwritten
+ if self.indexer_dumps_unicode:
+ f = codecs.open(searchindexfn + '.tmp', 'w', encoding='utf-8')
+ else:
+ f = open(searchindexfn + '.tmp', 'wb')
+ try:
+ self.indexer.dump(f, self.indexer_format)
+ finally:
+ f.close()
+ movefile(searchindexfn + '.tmp', searchindexfn)
+ self.info('done')
+
+
+class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
+ """
+ A StandaloneHTMLBuilder that creates all HTML pages as "index.html" in
+ a directory given by their pagename, so that generated URLs don't have
+ ``.html`` in them.
+ """
+ name = 'dirhtml'
+
+ def get_target_uri(self, docname, typ=None):
+ if docname == 'index':
+ return ''
+ if docname.endswith(SEP + 'index'):
+ return docname[:-5] # up to sep
+ return docname + SEP
+
+ def get_outfilename(self, pagename):
+ if pagename == 'index' or pagename.endswith(SEP + 'index'):
+ outfilename = path.join(self.outdir, os_path(pagename)
+ + self.out_suffix)
+ else:
+ outfilename = path.join(self.outdir, os_path(pagename),
+ 'index' + self.out_suffix)
+
+ return outfilename
+
+ def prepare_writing(self, docnames):
+ StandaloneHTMLBuilder.prepare_writing(self, docnames)
+ self.globalcontext['no_search_suffix'] = True
+
+
+class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
+ """
+ A StandaloneHTMLBuilder subclass that puts the whole document tree on one
+ HTML page.
+ """
+ name = 'singlehtml'
+ copysource = False
+
+ def get_outdated_docs(self):
+ return 'all documents'
+
+ def get_target_uri(self, docname, typ=None):
+ if docname in self.env.all_docs:
+ # all references are on the same page...
+ return self.config.master_doc + self.out_suffix + \
+ '#document-' + docname
+ else:
+ # chances are this is a html_additional_page
+ return docname + self.out_suffix
+
+ def get_relative_uri(self, from_, to, typ=None):
+ # ignore source
+ return self.get_target_uri(to, typ)
+
+ def fix_refuris(self, tree):
+ # fix refuris with double anchor
+ fname = self.config.master_doc + self.out_suffix
+ for refnode in tree.traverse(nodes.reference):
+ if 'refuri' not in refnode:
+ continue
+ refuri = refnode['refuri']
+ hashindex = refuri.find('#')
+ if hashindex < 0:
+ continue
+ hashindex = refuri.find('#', hashindex+1)
+ if hashindex >= 0:
+ refnode['refuri'] = fname + refuri[hashindex:]
+
+ def assemble_doctree(self):
+ master = self.config.master_doc
+ tree = self.env.get_doctree(master)
+ tree = inline_all_toctrees(self, set(), master, tree, darkgreen)
+ tree['docname'] = master
+ self.env.resolve_references(tree, master, self)
+ self.fix_refuris(tree)
+ return tree
+
+ def get_doc_context(self, docname, body, metatags):
+ # no relation links...
+ toc = self.env.get_toctree_for(self.config.master_doc, self, False)
+ # if there is no toctree, toc is None
+ if toc:
+ self.fix_refuris(toc)
+ toc = self.render_partial(toc)['fragment']
+ display_toc = True
+ else:
+ toc = ''
+ display_toc = False
+ return dict(
+ parents = [],
+ prev = None,
+ next = None,
+ docstitle = None,
+ title = self.config.html_title,
+ meta = None,
+ body = body,
+ metatags = metatags,
+ rellinks = [],
+ sourcename = '',
+ toc = toc,
+ display_toc = display_toc,
+ )
+
+ def write(self, *ignored):
+ docnames = self.env.all_docs
+
+ self.info(bold('preparing documents... '), nonl=True)
+ self.prepare_writing(docnames)
+ self.info('done')
+
+ self.info(bold('assembling single document... '), nonl=True)
+ doctree = self.assemble_doctree()
+ self.info()
+ self.info(bold('writing... '), nonl=True)
+ self.write_doc_serialized(self.config.master_doc, doctree)
+ self.write_doc(self.config.master_doc, doctree)
+ self.info('done')
+
+ def finish(self):
+ # no indices or search pages are supported
+ self.info(bold('writing additional files...'), nonl=1)
+
+ # additional pages from conf.py
+ for pagename, template in self.config.html_additional_pages.items():
+ self.info(' '+pagename, nonl=1)
+ self.handle_page(pagename, {}, template)
+
+ if self.config.html_use_opensearch:
+ self.info(' opensearch', nonl=1)
+ fn = path.join(self.outdir, '_static', 'opensearch.xml')
+ self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
+
+ self.info()
+
+ self.copy_image_files()
+ self.copy_download_files()
+ self.copy_static_files()
+ self.copy_extra_files()
+ self.write_buildinfo()
+ self.dump_inventory()
+
+
+class SerializingHTMLBuilder(StandaloneHTMLBuilder):
+ """
+ An abstract builder that serializes the generated HTML.
+ """
+ #: the serializing implementation to use. Set this to a module that
+ #: implements a `dump`, `load`, `dumps` and `loads` functions
+ #: (pickle, simplejson etc.)
+ implementation = None
+ implementation_dumps_unicode = False
+ #: additional arguments for dump()
+ additional_dump_args = ()
+
+ #: the filename for the global context file
+ globalcontext_filename = None
+
+ supported_image_types = ['image/svg+xml', 'image/png',
+ 'image/gif', 'image/jpeg']
+
+ def init(self):
+ self.config_hash = ''
+ self.tags_hash = ''
+ self.theme = None # no theme necessary
+ self.templates = None # no template bridge necessary
+ self.init_translator_class()
+ self.init_highlighter()
+
+ def get_target_uri(self, docname, typ=None):
+ if docname == 'index':
+ return ''
+ if docname.endswith(SEP + 'index'):
+ return docname[:-5] # up to sep
+ return docname + SEP
+
+ def dump_context(self, context, filename):
+ if self.implementation_dumps_unicode:
+ f = codecs.open(filename, 'w', encoding='utf-8')
+ else:
+ f = open(filename, 'wb')
+ try:
+ self.implementation.dump(context, f, *self.additional_dump_args)
+ finally:
+ f.close()
+
+ def handle_page(self, pagename, ctx, templatename='page.html',
+ outfilename=None, event_arg=None):
+ ctx['current_page_name'] = pagename
+ self.add_sidebars(pagename, ctx)
+
+ if not outfilename:
+ outfilename = path.join(self.outdir,
+ os_path(pagename) + self.out_suffix)
+
+ self.app.emit('html-page-context', pagename, templatename,
+ ctx, event_arg)
+
+ ensuredir(path.dirname(outfilename))
+ self.dump_context(ctx, outfilename)
+
+ # if there is a source file, copy the source file for the
+ # "show source" link
+ if ctx.get('sourcename'):
+ source_name = path.join(self.outdir, '_sources',
+ os_path(ctx['sourcename']))
+ ensuredir(path.dirname(source_name))
+ copyfile(self.env.doc2path(pagename), source_name)
+
+ def handle_finish(self):
+ # dump the global context
+ outfilename = path.join(self.outdir, self.globalcontext_filename)
+ self.dump_context(self.globalcontext, outfilename)
+
+ # super here to dump the search index
+ StandaloneHTMLBuilder.handle_finish(self)
+
+ # copy the environment file from the doctree dir to the output dir
+ # as needed by the web app
+ copyfile(path.join(self.doctreedir, ENV_PICKLE_FILENAME),
+ path.join(self.outdir, ENV_PICKLE_FILENAME))
+
+ # touch 'last build' file, used by the web application to determine
+ # when to reload its environment and clear the cache
+ open(path.join(self.outdir, LAST_BUILD_FILENAME), 'w').close()
+
+
+class PickleHTMLBuilder(SerializingHTMLBuilder):
+ """
+ A Builder that dumps the generated HTML into pickle files.
+ """
+ implementation = pickle
+ implementation_dumps_unicode = False
+ additional_dump_args = (pickle.HIGHEST_PROTOCOL,)
+ indexer_format = pickle
+ indexer_dumps_unicode = False
+ name = 'pickle'
+ out_suffix = '.fpickle'
+ globalcontext_filename = 'globalcontext.pickle'
+ searchindex_filename = 'searchindex.pickle'
+
+# compatibility alias
+WebHTMLBuilder = PickleHTMLBuilder
+
+
+class JSONHTMLBuilder(SerializingHTMLBuilder):
+ """
+ A builder that dumps the generated HTML into JSON files.
+ """
+ implementation = jsonimpl
+ implementation_dumps_unicode = True
+ indexer_format = jsonimpl
+ indexer_dumps_unicode = True
+ name = 'json'
+ out_suffix = '.fjson'
+ globalcontext_filename = 'globalcontext.json'
+ searchindex_filename = 'searchindex.json'
+
+ def init(self):
+ if jsonimpl.json is None:
+ raise SphinxError(
+ 'The module simplejson (or json in Python >= 2.6) '
+ 'is not available. The JSONHTMLBuilder builder will not work.')
+ SerializingHTMLBuilder.init(self)
diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py
new file mode 100644
index 0000000..77fcd43
--- /dev/null
+++ b/sphinx/builders/htmlhelp.py
@@ -0,0 +1,299 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.htmlhelp
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Build HTML help support files.
+ Parts adapted from Python's Doc/tools/prechm.py.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import codecs
+from os import path
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.util.pycompat import htmlescape
+
+
+# Project file (*.hhp) template. 'outname' is the file basename (like
+# the pythlp in pythlp.hhp); 'version' is the doc version number (like
+# the 2.2 in Python 2.2).
+# The magical numbers in the long line under [WINDOWS] set most of the
+# user-visible features (visible buttons, tabs, etc).
+# About 0x10384e: This defines the buttons in the help viewer. The
+# following defns are taken from htmlhelp.h. Not all possibilities
+# actually work, and not all those that work are available from the Help
+# Workshop GUI. In particular, the Zoom/Font button works and is not
+# available from the GUI. The ones we're using are marked with 'x':
+#
+# 0x000002 Hide/Show x
+# 0x000004 Back x
+# 0x000008 Forward x
+# 0x000010 Stop
+# 0x000020 Refresh
+# 0x000040 Home x
+# 0x000080 Forward
+# 0x000100 Back
+# 0x000200 Notes
+# 0x000400 Contents
+# 0x000800 Locate x
+# 0x001000 Options x
+# 0x002000 Print x
+# 0x004000 Index
+# 0x008000 Search
+# 0x010000 History
+# 0x020000 Favorites
+# 0x040000 Jump 1
+# 0x080000 Jump 2
+# 0x100000 Zoom/Font x
+# 0x200000 TOC Next
+# 0x400000 TOC Prev
+
+project_template = '''\
+[OPTIONS]
+Binary TOC=No
+Binary Index=No
+Compiled file=%(outname)s.chm
+Contents file=%(outname)s.hhc
+Default Window=%(outname)s
+Default topic=index.html
+Display compile progress=No
+Full text search stop list file=%(outname)s.stp
+Full-text search=Yes
+Index file=%(outname)s.hhk
+Language=%(lcid)#x
+Title=%(title)s
+
+[WINDOWS]
+%(outname)s="%(title)s","%(outname)s.hhc","%(outname)s.hhk",\
+"index.html","index.html",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
+
+[FILES]
+'''
+
+contents_header = '''\
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+<HEAD>
+<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+<OBJECT type="text/site properties">
+ <param name="Window Styles" value="0x801227">
+ <param name="ImageType" value="Folder">
+</OBJECT>
+<UL>
+'''
+
+contents_footer = '''\
+</UL></BODY></HTML>
+'''
+
+object_sitemap = '''\
+<OBJECT type="text/sitemap">
+ <param name="Name" value="%s">
+ <param name="Local" value="%s">
+</OBJECT>
+'''
+
+# List of words the full text search facility shouldn't index. This
+# becomes file outname.stp. Note that this list must be pretty small!
+# Different versions of the MS docs claim the file has a maximum size of
+# 256 or 512 bytes (including \r\n at the end of each line).
+# Note that "and", "or", "not" and "near" are operators in the search
+# language, so no point indexing them even if we wanted to.
+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
+""".split()
+
+# The following list includes only languages supported by Sphinx.
+# See http://msdn.microsoft.com/en-us/library/ms930130.aspx for more.
+chm_locales = {
+ # lang: LCID, encoding
+ 'ca': (0x403, 'cp1252'),
+ 'cs': (0x405, 'cp1250'),
+ 'da': (0x406, 'cp1252'),
+ 'de': (0x407, 'cp1252'),
+ 'en': (0x409, 'cp1252'),
+ 'es': (0x40a, 'cp1252'),
+ 'et': (0x425, 'cp1257'),
+ 'fa': (0x429, 'cp1256'),
+ 'fi': (0x40b, 'cp1252'),
+ 'fr': (0x40c, 'cp1252'),
+ 'hr': (0x41a, 'cp1250'),
+ 'hu': (0x40e, 'cp1250'),
+ 'it': (0x410, 'cp1252'),
+ 'ja': (0x411, 'cp932'),
+ 'ko': (0x412, 'cp949'),
+ 'lt': (0x427, 'cp1257'),
+ 'lv': (0x426, 'cp1257'),
+ 'nl': (0x413, 'cp1252'),
+ 'no_NB': (0x414, 'cp1252'),
+ 'pl': (0x415, 'cp1250'),
+ 'pt_BR': (0x416, 'cp1252'),
+ 'ru': (0x419, 'cp1251'),
+ 'sk': (0x41b, 'cp1250'),
+ 'sl': (0x424, 'cp1250'),
+ 'sv': (0x41d, 'cp1252'),
+ 'tr': (0x41f, 'cp1254'),
+ 'uk_UA': (0x422, 'cp1251'),
+ 'zh_CN': (0x804, 'cp936'),
+ 'zh_TW': (0x404, 'cp950'),
+}
+
+
+class HTMLHelpBuilder(StandaloneHTMLBuilder):
+ """
+ Builder that also outputs Windows HTML help project, contents and
+ index files. Adapted from the original Doc/tools/prechm.py.
+ """
+ name = 'htmlhelp'
+
+ # don't copy the reST source
+ copysource = False
+ supported_image_types = ['image/png', 'image/gif', 'image/jpeg']
+
+ # don't add links
+ add_permalinks = False
+ # don't add sidebar etc.
+ embedded = True
+
+ lcid = 0x409
+ encoding = 'cp1252'
+
+ def init(self):
+ StandaloneHTMLBuilder.init(self)
+ # the output files for HTML help must be .html only
+ self.out_suffix = '.html'
+ # determine the correct locale setting
+ locale = chm_locales.get(self.config.language)
+ if locale is not None:
+ self.lcid, self.encoding = locale
+
+ def open_file(self, outdir, basename, mode='w'):
+ # open a file with the correct encoding for the selected language
+ return codecs.open(path.join(outdir, basename), mode,
+ self.encoding, 'xmlcharrefreplace')
+
+ def handle_finish(self):
+ self.build_hhx(self.outdir, self.config.htmlhelp_basename)
+
+ def build_hhx(self, outdir, outname):
+ self.info('dumping stopword list...')
+ f = self.open_file(outdir, outname+'.stp')
+ try:
+ for word in sorted(stopwords):
+ print >>f, word
+ finally:
+ f.close()
+
+ self.info('writing project file...')
+ f = self.open_file(outdir, outname+'.hhp')
+ try:
+ f.write(project_template % {'outname': outname,
+ 'title': self.config.html_title,
+ 'version': self.config.version,
+ 'project': self.config.project,
+ 'lcid': self.lcid})
+ if not outdir.endswith(os.sep):
+ outdir += os.sep
+ olen = len(outdir)
+ for root, dirs, files in os.walk(outdir):
+ staticdir = root.startswith(path.join(outdir, '_static'))
+ for fn in files:
+ if (staticdir and not fn.endswith('.js')) or \
+ fn.endswith('.html'):
+ print >>f, path.join(root, fn)[olen:].replace(os.sep,
+ '\\')
+ finally:
+ f.close()
+
+ self.info('writing TOC file...')
+ f = self.open_file(outdir, outname+'.hhc')
+ try:
+ f.write(contents_header)
+ # special books
+ f.write('<LI> ' + object_sitemap % (self.config.html_short_title,
+ 'index.html'))
+ for indexname, indexcls, content, collapse in self.domain_indices:
+ f.write('<LI> ' + object_sitemap % (indexcls.localname,
+ '%s.html' % indexname))
+ # the TOC
+ tocdoc = self.env.get_and_resolve_doctree(
+ self.config.master_doc, self, prune_toctrees=False)
+ def write_toc(node, ullevel=0):
+ if isinstance(node, nodes.list_item):
+ f.write('<LI> ')
+ for subnode in node:
+ write_toc(subnode, ullevel)
+ elif isinstance(node, nodes.reference):
+ link = node['refuri']
+ title = htmlescape(node.astext()).replace('"','"')
+ f.write(object_sitemap % (title, link))
+ elif isinstance(node, nodes.bullet_list):
+ if ullevel != 0:
+ f.write('<UL>\n')
+ for subnode in node:
+ write_toc(subnode, ullevel+1)
+ if ullevel != 0:
+ f.write('</UL>\n')
+ elif isinstance(node, addnodes.compact_paragraph):
+ for subnode in node:
+ write_toc(subnode, ullevel)
+ def istoctree(node):
+ return isinstance(node, addnodes.compact_paragraph) and \
+ node.has_key('toctree')
+ for node in tocdoc.traverse(istoctree):
+ write_toc(node)
+ f.write(contents_footer)
+ finally:
+ f.close()
+
+ self.info('writing index file...')
+ index = self.env.create_index(self)
+ f = self.open_file(outdir, outname+'.hhk')
+ try:
+ f.write('<UL>\n')
+ def write_index(title, refs, subitems):
+ def write_param(name, value):
+ item = ' <param name="%s" value="%s">\n' % \
+ (name, value)
+ f.write(item)
+ title = htmlescape(title)
+ f.write('<LI> <OBJECT type="text/sitemap">\n')
+ write_param('Keyword', title)
+ if len(refs) == 0:
+ write_param('See Also', title)
+ elif len(refs) == 1:
+ write_param('Local', refs[0][1])
+ else:
+ for i, ref in enumerate(refs):
+ # XXX: better title?
+ write_param('Name', '[%d] %s' % (i, ref[1]))
+ write_param('Local', ref[1])
+ f.write('</OBJECT>\n')
+ if subitems:
+ f.write('<UL> ')
+ for subitem in subitems:
+ write_index(subitem[0], subitem[1], [])
+ f.write('</UL>')
+ for (key, group) in index:
+ for title, (refs, subitems) in group:
+ write_index(title, refs, subitems)
+ f.write('</UL>\n')
+ finally:
+ f.close()
diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py
new file mode 100644
index 0000000..f545330
--- /dev/null
+++ b/sphinx/builders/latex.py
@@ -0,0 +1,183 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.latex
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ LaTeX builder.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+from os import path
+
+from docutils import nodes
+from docutils.io import FileOutput
+from docutils.utils import new_document
+from docutils.frontend import OptionParser
+
+from sphinx import package_dir, addnodes
+from sphinx.util import texescape
+from sphinx.locale import _
+from sphinx.builders import Builder
+from sphinx.environment import NoUri
+from sphinx.util.nodes import inline_all_toctrees
+from sphinx.util.osutil import SEP, copyfile
+from sphinx.util.console import bold, darkgreen
+from sphinx.writers.latex import LaTeXWriter
+
+
+class LaTeXBuilder(Builder):
+ """
+ Builds LaTeX output to create PDF.
+ """
+ name = 'latex'
+ format = 'latex'
+ supported_image_types = ['application/pdf', 'image/png',
+ 'image/gif', 'image/jpeg']
+
+ def init(self):
+ self.docnames = []
+ self.document_data = []
+ texescape.init()
+
+ def get_outdated_docs(self):
+ return 'all documents' # for now
+
+ def get_target_uri(self, docname, typ=None):
+ if docname not in self.docnames:
+ raise NoUri
+ else:
+ return '%' + docname
+
+ def get_relative_uri(self, from_, to, typ=None):
+ # ignore source path
+ return self.get_target_uri(to, typ)
+
+ def init_document_data(self):
+ preliminary_document_data = map(list, self.config.latex_documents)
+ if not preliminary_document_data:
+ self.warn('no "latex_documents" config value found; no documents '
+ 'will be written')
+ return
+ # assign subdirs to titles
+ self.titles = []
+ for entry in preliminary_document_data:
+ docname = entry[0]
+ if docname not in self.env.all_docs:
+ self.warn('"latex_documents" config value references unknown '
+ 'document %s' % docname)
+ continue
+ self.document_data.append(entry)
+ if docname.endswith(SEP+'index'):
+ docname = docname[:-5]
+ self.titles.append((docname, entry[2]))
+
+ def write(self, *ignored):
+ docwriter = LaTeXWriter(self)
+ docsettings = OptionParser(
+ defaults=self.env.settings,
+ components=(docwriter,),
+ read_config_files=True).get_default_values()
+
+ self.init_document_data()
+
+ for entry in self.document_data:
+ docname, targetname, title, author, docclass = entry[:5]
+ toctree_only = False
+ if len(entry) > 5:
+ toctree_only = entry[5]
+ destination = FileOutput(
+ destination_path=path.join(self.outdir, targetname),
+ encoding='utf-8')
+ self.info("processing " + targetname + "... ", nonl=1)
+ doctree = self.assemble_doctree(docname, toctree_only,
+ appendices=((docclass != 'howto') and
+ self.config.latex_appendices or []))
+ self.post_process_images(doctree)
+ self.info("writing... ", nonl=1)
+ doctree.settings = docsettings
+ doctree.settings.author = author
+ doctree.settings.title = title
+ doctree.settings.docname = docname
+ doctree.settings.docclass = docclass
+ docwriter.write(doctree, destination)
+ self.info("done")
+
+ def assemble_doctree(self, indexfile, toctree_only, appendices):
+ self.docnames = set([indexfile] + appendices)
+ self.info(darkgreen(indexfile) + " ", nonl=1)
+ tree = self.env.get_doctree(indexfile)
+ tree['docname'] = indexfile
+ if toctree_only:
+ # extract toctree nodes from the tree and put them in a
+ # fresh document
+ new_tree = new_document('<latex output>')
+ new_sect = nodes.section()
+ new_sect += nodes.title(u'<Set title in conf.py>',
+ u'<Set title in conf.py>')
+ new_tree += new_sect
+ for node in tree.traverse(addnodes.toctree):
+ new_sect += node
+ tree = new_tree
+ largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
+ darkgreen)
+ largetree['docname'] = indexfile
+ for docname in appendices:
+ appendix = self.env.get_doctree(docname)
+ appendix['docname'] = docname
+ largetree.append(appendix)
+ self.info()
+ self.info("resolving references...")
+ self.env.resolve_references(largetree, indexfile, self)
+ # resolve :ref:s to distant tex files -- we can't add a cross-reference,
+ # but append the document name
+ for pendingnode in largetree.traverse(addnodes.pending_xref):
+ docname = pendingnode['refdocname']
+ sectname = pendingnode['refsectname']
+ newnodes = [nodes.emphasis(sectname, sectname)]
+ for subdir, title in self.titles:
+ if docname.startswith(subdir):
+ newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
+ newnodes.append(nodes.emphasis(title, title))
+ newnodes.append(nodes.Text(')', ')'))
+ break
+ else:
+ pass
+ pendingnode.replace_self(newnodes)
+ return largetree
+
+ def finish(self):
+ # copy image files
+ if self.images:
+ self.info(bold('copying images...'), nonl=1)
+ for src, dest in self.images.iteritems():
+ self.info(' '+src, nonl=1)
+ copyfile(path.join(self.srcdir, src),
+ path.join(self.outdir, dest))
+ self.info()
+
+ # copy TeX support files from texinputs
+ self.info(bold('copying TeX support files...'))
+ staticdirname = path.join(package_dir, 'texinputs')
+ for filename in os.listdir(staticdirname):
+ if not filename.startswith('.'):
+ copyfile(path.join(staticdirname, filename),
+ path.join(self.outdir, filename))
+
+ # copy additional files
+ if self.config.latex_additional_files:
+ self.info(bold('copying additional files...'), nonl=1)
+ for filename in self.config.latex_additional_files:
+ self.info(' '+filename, nonl=1)
+ copyfile(path.join(self.confdir, filename),
+ path.join(self.outdir, path.basename(filename)))
+ self.info()
+
+ # the logo is handled differently
+ if self.config.latex_logo:
+ logobase = path.basename(self.config.latex_logo)
+ copyfile(path.join(self.confdir, self.config.latex_logo),
+ path.join(self.outdir, logobase))
+ self.info('done')
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
new file mode 100644
index 0000000..f0cb3c9
--- /dev/null
+++ b/sphinx/builders/linkcheck.py
@@ -0,0 +1,264 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.linkcheck
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The CheckExternalLinksBuilder class.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import sys
+import Queue
+import socket
+import threading
+from os import path
+from urllib2 import build_opener, unquote, Request, \
+ HTTPError, HTTPRedirectHandler
+from HTMLParser import HTMLParser, HTMLParseError
+
+from docutils import nodes
+
+from sphinx.builders import Builder
+from sphinx.util.console import purple, red, darkgreen, darkgray, \
+ darkred, turquoise
+from sphinx.util.pycompat import TextIOWrapper
+
+
+class RedirectHandler(HTTPRedirectHandler):
+ """A RedirectHandler that records the redirect code we got."""
+
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
+ new_req = HTTPRedirectHandler.redirect_request(self, req, fp, code,
+ msg, headers, newurl)
+ req.redirect_code = code
+ return new_req
+
+# create an opener that will simulate a browser user-agent
+opener = build_opener(RedirectHandler)
+opener.addheaders = [('User-agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:25.0) '
+ 'Gecko/20100101 Firefox/25.0')]
+
+
+class HeadRequest(Request):
+ """Subclass of urllib2.Request that sends a HEAD request."""
+ def get_method(self):
+ return 'HEAD'
+
+
+class AnchorCheckParser(HTMLParser):
+ """Specialized HTML parser that looks for a specific anchor."""
+
+ def __init__(self, search_anchor):
+ HTMLParser.__init__(self)
+
+ self.search_anchor = search_anchor
+ self.found = False
+
+ def handle_starttag(self, tag, attrs):
+ for key, value in attrs:
+ if key in ('id', 'name') and value == self.search_anchor:
+ self.found = True
+
+
+def check_anchor(f, hash):
+ """Reads HTML data from a filelike object 'f' searching for anchor 'hash'.
+ Returns True if anchor was found, False otherwise.
+ """
+ parser = AnchorCheckParser(hash)
+ try:
+ # Read file in chunks of 8192 bytes. If we find a matching anchor, we
+ # break the loop early in hopes not to have to download the whole thing.
+ chunk = f.read(8192)
+ while chunk and not parser.found:
+ parser.feed(chunk)
+ chunk = f.read(8192)
+ parser.close()
+ except HTMLParseError:
+ # HTMLParser is usually pretty good with sloppy HTML, but it tends to
+ # choke on EOF. But we're done then anyway.
+ pass
+ return parser.found
+
+
+class CheckExternalLinksBuilder(Builder):
+ """
+ Checks for broken external links.
+ """
+ name = 'linkcheck'
+
+ def init(self):
+ self.to_ignore = map(re.compile, self.app.config.linkcheck_ignore)
+ self.good = set()
+ self.broken = {}
+ self.redirected = {}
+ # set a timeout for non-responding servers
+ socket.setdefaulttimeout(5.0)
+ # create output file
+ open(path.join(self.outdir, 'output.txt'), 'w').close()
+
+ # create queues and worker threads
+ self.wqueue = Queue.Queue()
+ self.rqueue = Queue.Queue()
+ self.workers = []
+ for i in range(self.app.config.linkcheck_workers):
+ thread = threading.Thread(target=self.check_thread)
+ thread.setDaemon(True)
+ thread.start()
+ self.workers.append(thread)
+
+ def check_thread(self):
+ kwargs = {}
+ if sys.version_info > (2, 5) and self.app.config.linkcheck_timeout:
+ kwargs['timeout'] = self.app.config.linkcheck_timeout
+
+ def check():
+ # check for various conditions without bothering the network
+ if len(uri) == 0 or uri[0] == '#' or \
+ uri[0:7] == 'mailto:' or uri[0:4] == 'ftp:':
+ return 'unchecked', '', 0
+ elif not (uri[0:5] == 'http:' or uri[0:6] == 'https:'):
+ return 'local', '', 0
+ elif uri in self.good:
+ return 'working', '', 0
+ elif uri in self.broken:
+ return 'broken', self.broken[uri], 0
+ elif uri in self.redirected:
+ return 'redirected', self.redirected[uri][0], self.redirected[uri][1]
+ for rex in self.to_ignore:
+ if rex.match(uri):
+ return 'ignored', '', 0
+
+ if '#' in uri:
+ req_url, hash = uri.split('#', 1)
+ else:
+ req_url = uri
+ hash = None
+
+ # need to actually check the URI
+ try:
+ if hash and self.app.config.linkcheck_anchors:
+ # Read the whole document and see if #hash exists
+ req = Request(req_url)
+ f = opener.open(req, **kwargs)
+ encoding = 'utf-8'
+ if hasattr(f.headers, 'get_content_charset'):
+ encoding = f.headers.get_content_charset() or encoding
+ found = check_anchor(TextIOWrapper(f, encoding), unquote(hash))
+ f.close()
+
+ if not found:
+ raise Exception("Anchor '%s' not found" % hash)
+ else:
+ try:
+ # try a HEAD request, which should be easier on
+ # the server and the network
+ req = HeadRequest(req_url)
+ f = opener.open(req, **kwargs)
+ f.close()
+ except HTTPError, err:
+ if err.code != 405:
+ raise
+ # retry with GET if that fails, some servers
+ # don't like HEAD requests and reply with 405
+ req = Request(req_url)
+ f = opener.open(req, **kwargs)
+ f.close()
+
+ except Exception, err:
+ self.broken[uri] = str(err)
+ return 'broken', str(err), 0
+ if f.url.rstrip('/') == req_url.rstrip('/'):
+ self.good.add(uri)
+ return 'working', 'new', 0
+ else:
+ new_url = f.url
+ if hash:
+ new_url += '#' + hash
+ code = getattr(req, 'redirect_code', 0)
+ self.redirected[uri] = (new_url, code)
+ return 'redirected', new_url, code
+
+ while True:
+ uri, docname, lineno = self.wqueue.get()
+ if uri is None:
+ break
+ status, info, code = check()
+ self.rqueue.put((uri, docname, lineno, status, info, code))
+
+ def process_result(self, result):
+ uri, docname, lineno, status, info, code = result
+ if status == 'unchecked':
+ return
+ if status == 'working' and info != 'new':
+ return
+ if lineno:
+ self.info('(line %4d) ' % lineno, nonl=1)
+ if status == 'ignored':
+ self.info(darkgray('-ignored- ') + uri)
+ elif status == 'local':
+ self.info(darkgray('-local- ') + uri)
+ self.write_entry('local', docname, lineno, uri)
+ elif status == 'working':
+ self.info(darkgreen('ok ') + uri)
+ elif status == 'broken':
+ self.info(red('broken ') + uri + red(' - ' + info))
+ self.write_entry('broken', docname, lineno, uri + ': ' + info)
+ if self.app.quiet:
+ self.warn('broken link: %s' % uri,
+ '%s:%s' % (self.env.doc2path(docname), lineno))
+ elif status == 'redirected':
+ text, color = {
+ 301: ('permanently', darkred),
+ 302: ('with Found', purple),
+ 303: ('with See Other', purple),
+ 307: ('temporarily', turquoise),
+ 0: ('with unknown code', purple),
+ }[code]
+ self.write_entry('redirected ' + text, docname, lineno,
+ uri + ' to ' + info)
+ self.info(color('redirect ') + uri + color(' - ' + text + ' to ' + info))
+
+ def get_target_uri(self, docname, typ=None):
+ return ''
+
+ def get_outdated_docs(self):
+ return self.env.found_docs
+
+ def prepare_writing(self, docnames):
+ return
+
+ def write_doc(self, docname, doctree):
+ self.info()
+ n = 0
+ for node in doctree.traverse(nodes.reference):
+ if 'refuri' not in node:
+ continue
+ uri = node['refuri']
+ lineno = None
+ while lineno is None:
+ node = node.parent
+ if node is None:
+ break
+ lineno = node.line
+ self.wqueue.put((uri, docname, lineno), False)
+ n += 1
+ done = 0
+ while done < n:
+ self.process_result(self.rqueue.get())
+ done += 1
+
+ if self.broken:
+ self.app.statuscode = 1
+
+ def write_entry(self, what, docname, line, uri):
+ output = open(path.join(self.outdir, 'output.txt'), 'a')
+ output.write("%s:%s: [%s] %s\n" % (self.env.doc2path(docname, None),
+ line, what, uri))
+ output.close()
+
+ def finish(self):
+ for worker in self.workers:
+ self.wqueue.put((None, None, None), False)
diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py
new file mode 100644
index 0000000..4de82a7
--- /dev/null
+++ b/sphinx/builders/manpage.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.manpage
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Manual pages builder.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from os import path
+
+from docutils.io import FileOutput
+from docutils.frontend import OptionParser
+
+from sphinx import addnodes
+from sphinx.errors import SphinxError
+from sphinx.builders import Builder
+from sphinx.environment import NoUri
+from sphinx.util.nodes import inline_all_toctrees
+from sphinx.util.console import bold, darkgreen
+from sphinx.writers.manpage import ManualPageWriter, has_manpage_writer
+
+
+class ManualPageBuilder(Builder):
+ """
+ Builds groff output in manual page format.
+ """
+ name = 'man'
+ format = 'man'
+ supported_image_types = []
+
+ def init(self):
+ if not has_manpage_writer:
+ raise SphinxError('The docutils manual page writer can\'t be '
+ 'found; it is only available as of docutils 0.6.')
+ if not self.config.man_pages:
+ self.warn('no "man_pages" config value found; no manual pages '
+ 'will be written')
+
+ def get_outdated_docs(self):
+ return 'all manpages' # for now
+
+ def get_target_uri(self, docname, typ=None):
+ if typ == 'token':
+ return ''
+ raise NoUri
+
+ def write(self, *ignored):
+ docwriter = ManualPageWriter(self)
+ docsettings = OptionParser(
+ defaults=self.env.settings,
+ components=(docwriter,),
+ read_config_files=True).get_default_values()
+
+ self.info(bold('writing... '), nonl=True)
+
+ for info in self.config.man_pages:
+ docname, name, description, authors, section = info
+ if isinstance(authors, basestring):
+ if authors:
+ authors = [authors]
+ else:
+ authors = []
+
+ targetname = '%s.%s' % (name, section)
+ self.info(darkgreen(targetname) + ' { ', nonl=True)
+ destination = FileOutput(
+ destination_path=path.join(self.outdir, targetname),
+ encoding='utf-8')
+
+ tree = self.env.get_doctree(docname)
+ docnames = set()
+ largetree = inline_all_toctrees(self, docnames, docname, tree,
+ darkgreen)
+ self.info('} ', nonl=True)
+ self.env.resolve_references(largetree, docname, self)
+ # remove pending_xref nodes
+ for pendingnode in largetree.traverse(addnodes.pending_xref):
+ pendingnode.replace_self(pendingnode.children)
+
+ largetree.settings = docsettings
+ largetree.settings.title = name
+ largetree.settings.subtitle = description
+ largetree.settings.authors = authors
+ largetree.settings.section = section
+
+ docwriter.write(largetree, destination)
+ self.info()
+
+ def finish(self):
+ pass
diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py
new file mode 100644
index 0000000..1d46284
--- /dev/null
+++ b/sphinx/builders/qthelp.py
@@ -0,0 +1,296 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.qthelp
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Build input files for the Qt collection generator.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import codecs
+import posixpath
+from os import path
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.util import force_decode
+from sphinx.util.pycompat import htmlescape
+
+
+_idpattern = re.compile(
+ r'(?P<title>.+) (\((class in )?(?P<id>[\w\.]+)( (?P<descr>\w+))?\))$')
+
+
+# Qt Help Collection Project (.qhcp).
+# Is the input file for the help collection generator.
+# It contains references to compressed help files which should be
+# included in the collection.
+# It may contain various other information for customizing Qt Assistant.
+collection_template = u'''\
+<?xml version="1.0" encoding="utf-8" ?>
+<QHelpCollectionProject version="1.0">
+ <assistant>
+ <title>%(title)s</title>
+ <homePage>%(homepage)s</homePage>
+ <startPage>%(startpage)s</startPage>
+ </assistant>
+ <docFiles>
+ <generate>
+ <file>
+ <input>%(outname)s.qhp</input>
+ <output>%(outname)s.qch</output>
+ </file>
+ </generate>
+ <register>
+ <file>%(outname)s.qch</file>
+ </register>
+ </docFiles>
+</QHelpCollectionProject>
+'''
+
+# Qt Help Project (.qhp)
+# This is the input file for the help generator.
+# It contains the table of contents, indices and references to the
+# actual documentation files (*.html).
+# In addition it defines a unique namespace for the documentation.
+project_template = u'''\
+<?xml version="1.0" encoding="utf-8" ?>
+<QtHelpProject version="1.0">
+ <namespace>%(namespace)s</namespace>
+ <virtualFolder>doc</virtualFolder>
+ <customFilter name="%(project)s %(version)s">
+ <filterAttribute>%(outname)s</filterAttribute>
+ <filterAttribute>%(version)s</filterAttribute>
+ </customFilter>
+ <filterSection>
+ <filterAttribute>%(outname)s</filterAttribute>
+ <filterAttribute>%(version)s</filterAttribute>
+ <toc>
+ <section title="%(title)s" ref="%(masterdoc)s.html">
+%(sections)s
+ </section>
+ </toc>
+ <keywords>
+%(keywords)s
+ </keywords>
+ <files>
+%(files)s
+ </files>
+ </filterSection>
+</QtHelpProject>
+'''
+
+section_template = '<section title="%(title)s" ref="%(ref)s"/>'
+file_template = ' '*12 + '<file>%(filename)s</file>'
+
+
+class QtHelpBuilder(StandaloneHTMLBuilder):
+ """
+ Builder that also outputs Qt help project, contents and index files.
+ """
+ name = 'qthelp'
+
+ # don't copy the reST source
+ copysource = False
+ supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
+ 'image/jpeg']
+
+ # don't add links
+ add_permalinks = False
+ # don't add sidebar etc.
+ embedded = True
+
+ def init(self):
+ StandaloneHTMLBuilder.init(self)
+ # the output files for HTML help must be .html only
+ self.out_suffix = '.html'
+ #self.config.html_style = 'traditional.css'
+
+ def handle_finish(self):
+ self.build_qhp(self.outdir, self.config.qthelp_basename)
+
+ def build_qhp(self, outdir, outname):
+ self.info('writing project file...')
+
+ # sections
+ tocdoc = self.env.get_and_resolve_doctree(self.config.master_doc, self,
+ prune_toctrees=False)
+ istoctree = lambda node: (
+ isinstance(node, addnodes.compact_paragraph)
+ and node.has_key('toctree'))
+ sections = []
+ for node in tocdoc.traverse(istoctree):
+ sections.extend(self.write_toc(node))
+
+ for indexname, indexcls, content, collapse in self.domain_indices:
+ item = section_template % {'title': indexcls.localname,
+ 'ref': '%s.html' % indexname}
+ sections.append(' ' * 4 * 4 + item)
+ # sections may be unicode strings or byte strings, we have to make sure
+ # they are all unicode strings before joining them
+ new_sections = []
+ for section in sections:
+ if not isinstance(section, unicode):
+ new_sections.append(force_decode(section, None))
+ else:
+ new_sections.append(section)
+ sections = u'\n'.join(new_sections)
+
+ # keywords
+ keywords = []
+ index = self.env.create_index(self, group_entries=False)
+ for (key, group) in index:
+ for title, (refs, subitems) in group:
+ keywords.extend(self.build_keywords(title, refs, subitems))
+ keywords = u'\n'.join(keywords)
+
+ # files
+ if not outdir.endswith(os.sep):
+ outdir += os.sep
+ olen = len(outdir)
+ projectfiles = []
+ staticdir = path.join(outdir, '_static')
+ imagesdir = path.join(outdir, '_images')
+ for root, dirs, files in os.walk(outdir):
+ resourcedir = root.startswith(staticdir) or \
+ root.startswith(imagesdir)
+ for fn in files:
+ if (resourcedir and not fn.endswith('.js')) or \
+ fn.endswith('.html'):
+ filename = path.join(root, fn)[olen:]
+ projectfiles.append(file_template %
+ {'filename': htmlescape(filename)})
+ projectfiles = '\n'.join(projectfiles)
+
+ # it seems that the "namespace" may not contain non-alphanumeric
+ # characters, and more than one successive dot, or leading/trailing
+ # dots, are also forbidden
+ nspace = 'org.sphinx.%s.%s' % (outname, self.config.version)
+ nspace = re.sub('[^a-zA-Z0-9.]', '', nspace)
+ nspace = re.sub(r'\.+', '.', nspace).strip('.')
+ nspace = nspace.lower()
+
+ # write the project file
+ f = codecs.open(path.join(outdir, outname+'.qhp'), 'w', 'utf-8')
+ try:
+ f.write(project_template % {
+ 'outname': htmlescape(outname),
+ 'title': htmlescape(self.config.html_title),
+ 'version': htmlescape(self.config.version),
+ 'project': htmlescape(self.config.project),
+ 'namespace': htmlescape(nspace),
+ 'masterdoc': htmlescape(self.config.master_doc),
+ 'sections': sections,
+ 'keywords': keywords,
+ 'files': projectfiles})
+ finally:
+ f.close()
+
+ homepage = 'qthelp://' + posixpath.join(
+ nspace, 'doc', self.get_target_uri(self.config.master_doc))
+ startpage = 'qthelp://' + posixpath.join(nspace, 'doc', 'index.html')
+
+ self.info('writing collection project file...')
+ f = codecs.open(path.join(outdir, outname+'.qhcp'), 'w', 'utf-8')
+ try:
+ f.write(collection_template % {
+ 'outname': htmlescape(outname),
+ 'title': htmlescape(self.config.html_short_title),
+ 'homepage': htmlescape(homepage),
+ 'startpage': htmlescape(startpage)})
+ finally:
+ f.close()
+
+ def isdocnode(self, node):
+ if not isinstance(node, nodes.list_item):
+ return False
+ if len(node.children) != 2:
+ return False
+ if not isinstance(node.children[0], addnodes.compact_paragraph):
+ return False
+ if not isinstance(node.children[0][0], nodes.reference):
+ return False
+ if not isinstance(node.children[1], nodes.bullet_list):
+ return False
+ return True
+
+ def write_toc(self, node, indentlevel=4):
+ # XXX this should return a Unicode string, not a bytestring
+ parts = []
+ if self.isdocnode(node):
+ refnode = node.children[0][0]
+ link = refnode['refuri']
+ title = htmlescape(refnode.astext()).replace('"', '"')
+ item = '<section title="%(title)s" ref="%(ref)s">' % \
+ {'title': title, 'ref': link}
+ parts.append(' '*4*indentlevel + item)
+ for subnode in node.children[1]:
+ parts.extend(self.write_toc(subnode, indentlevel+1))
+ parts.append(' '*4*indentlevel + '</section>')
+ elif isinstance(node, nodes.list_item):
+ for subnode in node:
+ parts.extend(self.write_toc(subnode, indentlevel))
+ elif isinstance(node, nodes.reference):
+ link = node['refuri']
+ title = htmlescape(node.astext()).replace('"','"')
+ item = section_template % {'title': title, 'ref': link}
+ item = u' ' * 4 * indentlevel + item
+ parts.append(item.encode('ascii', 'xmlcharrefreplace'))
+ elif isinstance(node, nodes.bullet_list):
+ for subnode in node:
+ parts.extend(self.write_toc(subnode, indentlevel))
+ elif isinstance(node, addnodes.compact_paragraph):
+ for subnode in node:
+ parts.extend(self.write_toc(subnode, indentlevel))
+
+ return parts
+
+ def keyword_item(self, name, ref):
+ matchobj = _idpattern.match(name)
+ if matchobj:
+ groupdict = matchobj.groupdict()
+ shortname = groupdict['title']
+ id = groupdict.get('id')
+ #descr = groupdict.get('descr')
+ if shortname.endswith('()'):
+ shortname = shortname[:-2]
+ id = '%s.%s' % (id, shortname)
+ else:
+ id = None
+
+ if id:
+ item = ' '*12 + '<keyword name="%s" id="%s" ref="%s"/>' % (
+ name, id, ref[1])
+ else:
+ item = ' '*12 + '<keyword name="%s" ref="%s"/>' % (name, ref[1])
+ item.encode('ascii', 'xmlcharrefreplace')
+ return item
+
+ def build_keywords(self, title, refs, subitems):
+ keywords = []
+
+ title = htmlescape(title)
+# if len(refs) == 0: # XXX
+# write_param('See Also', title)
+ if len(refs) == 1:
+ keywords.append(self.keyword_item(title, refs[0]))
+ elif len(refs) > 1:
+ for i, ref in enumerate(refs): # XXX
+# item = (' '*12 +
+# '<keyword name="%s [%d]" ref="%s"/>' % (
+# title, i, ref))
+# item.encode('ascii', 'xmlcharrefreplace')
+# keywords.append(item)
+ keywords.append(self.keyword_item(title, ref))
+
+ if subitems:
+ for subitem in subitems:
+ keywords.extend(self.build_keywords(subitem[0], subitem[1], []))
+
+ return keywords
diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py
new file mode 100644
index 0000000..39499e6
--- /dev/null
+++ b/sphinx/builders/texinfo.py
@@ -0,0 +1,228 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.texinfo
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Texinfo builder.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from os import path
+
+from docutils import nodes
+from docutils.io import FileOutput
+from docutils.utils import new_document
+from docutils.frontend import OptionParser
+
+from sphinx import addnodes
+from sphinx.locale import _
+from sphinx.builders import Builder
+from sphinx.environment import NoUri
+from sphinx.util.nodes import inline_all_toctrees
+from sphinx.util.osutil import SEP, copyfile
+from sphinx.util.console import bold, darkgreen
+from sphinx.writers.texinfo import TexinfoWriter
+
+
+TEXINFO_MAKEFILE = '''\
+# Makefile for Sphinx Texinfo output
+
+infodir ?= /usr/share/info
+
+MAKEINFO = makeinfo --no-split
+MAKEINFO_html = makeinfo --no-split --html
+MAKEINFO_plaintext = makeinfo --no-split --plaintext
+TEXI2PDF = texi2pdf --batch --expand
+INSTALL_INFO = install-info
+
+ALLDOCS = $(basename $(wildcard *.texi))
+
+all: info
+info: $(addsuffix .info,$(ALLDOCS))
+plaintext: $(addsuffix .txt,$(ALLDOCS))
+html: $(addsuffix .html,$(ALLDOCS))
+pdf: $(addsuffix .pdf,$(ALLDOCS))
+
+install-info: info
+\tfor f in *.info; do \\
+\t cp -t $(infodir) "$$f" && \\
+\t $(INSTALL_INFO) --info-dir=$(infodir) "$$f" ; \\
+\tdone
+
+uninstall-info: info
+\tfor f in *.info; do \\
+\t rm -f "$(infodir)/$$f" ; \\
+\t $(INSTALL_INFO) --delete --info-dir=$(infodir) "$$f" ; \\
+\tdone
+
+%.info: %.texi
+\t$(MAKEINFO) -o '$@' '$<'
+
+%.txt: %.texi
+\t$(MAKEINFO_plaintext) -o '$@' '$<'
+
+%.html: %.texi
+\t$(MAKEINFO_html) -o '$@' '$<'
+
+%.pdf: %.texi
+\t-$(TEXI2PDF) '$<'
+\t-$(TEXI2PDF) '$<'
+\t-$(TEXI2PDF) '$<'
+
+clean:
+\trm -f *.info *.pdf *.txt *.html
+\trm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ky *.pg
+\trm -f *.vr *.tp *.fn *.fns *.def *.defs *.cp *.cps *.ge *.ges *.mo
+
+.PHONY: all info plaintext html pdf install-info uninstall-info clean
+'''
+
+
+class TexinfoBuilder(Builder):
+ """
+ Builds Texinfo output to create Info documentation.
+ """
+ name = 'texinfo'
+ format = 'texinfo'
+ supported_image_types = ['image/png', 'image/jpeg',
+ 'image/gif',]
+
+ def init(self):
+ self.docnames = []
+ self.document_data = []
+
+ def get_outdated_docs(self):
+ return 'all documents' # for now
+
+ def get_target_uri(self, docname, typ=None):
+ if docname not in self.docnames:
+ raise NoUri
+ else:
+ return '%' + docname
+
+ def get_relative_uri(self, from_, to, typ=None):
+ # ignore source path
+ return self.get_target_uri(to, typ)
+
+ def init_document_data(self):
+ preliminary_document_data = map(list, self.config.texinfo_documents)
+ if not preliminary_document_data:
+ self.warn('no "texinfo_documents" config value found; no documents '
+ 'will be written')
+ return
+ # assign subdirs to titles
+ self.titles = []
+ for entry in preliminary_document_data:
+ docname = entry[0]
+ if docname not in self.env.all_docs:
+ self.warn('"texinfo_documents" config value references unknown '
+ 'document %s' % docname)
+ continue
+ self.document_data.append(entry)
+ if docname.endswith(SEP+'index'):
+ docname = docname[:-5]
+ self.titles.append((docname, entry[2]))
+
+ def write(self, *ignored):
+ self.init_document_data()
+ for entry in self.document_data:
+ docname, targetname, title, author = entry[:4]
+ targetname += '.texi'
+ direntry = description = category = ''
+ if len(entry) > 6:
+ direntry, description, category = entry[4:7]
+ toctree_only = False
+ if len(entry) > 7:
+ toctree_only = entry[7]
+ destination = FileOutput(
+ destination_path=path.join(self.outdir, targetname),
+ encoding='utf-8')
+ self.info("processing " + targetname + "... ", nonl=1)
+ doctree = self.assemble_doctree(docname, toctree_only,
+ appendices=(self.config.texinfo_appendices or []))
+ self.info("writing... ", nonl=1)
+ self.post_process_images(doctree)
+ docwriter = TexinfoWriter(self)
+ settings = OptionParser(
+ defaults=self.env.settings,
+ components=(docwriter,),
+ read_config_files=True).get_default_values()
+ settings.author = author
+ settings.title = title
+ settings.texinfo_filename = targetname[:-5] + '.info'
+ settings.texinfo_elements = self.config.texinfo_elements
+ settings.texinfo_dir_entry = direntry or ''
+ settings.texinfo_dir_category = category or ''
+ settings.texinfo_dir_description = description or ''
+ settings.docname = docname
+ doctree.settings = settings
+ docwriter.write(doctree, destination)
+ self.info("done")
+
+ def assemble_doctree(self, indexfile, toctree_only, appendices):
+ self.docnames = set([indexfile] + appendices)
+ self.info(darkgreen(indexfile) + " ", nonl=1)
+ tree = self.env.get_doctree(indexfile)
+ tree['docname'] = indexfile
+ if toctree_only:
+ # extract toctree nodes from the tree and put them in a
+ # fresh document
+ new_tree = new_document('<texinfo output>')
+ new_sect = nodes.section()
+ new_sect += nodes.title(u'<Set title in conf.py>',
+ u'<Set title in conf.py>')
+ new_tree += new_sect
+ for node in tree.traverse(addnodes.toctree):
+ new_sect += node
+ tree = new_tree
+ largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
+ darkgreen)
+ largetree['docname'] = indexfile
+ for docname in appendices:
+ appendix = self.env.get_doctree(docname)
+ appendix['docname'] = docname
+ largetree.append(appendix)
+ self.info()
+ self.info("resolving references...")
+ self.env.resolve_references(largetree, indexfile, self)
+ # TODO: add support for external :ref:s
+ for pendingnode in largetree.traverse(addnodes.pending_xref):
+ docname = pendingnode['refdocname']
+ sectname = pendingnode['refsectname']
+ newnodes = [nodes.emphasis(sectname, sectname)]
+ for subdir, title in self.titles:
+ if docname.startswith(subdir):
+ newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
+ newnodes.append(nodes.emphasis(title, title))
+ newnodes.append(nodes.Text(')', ')'))
+ break
+ else:
+ pass
+ pendingnode.replace_self(newnodes)
+ return largetree
+
+ def finish(self):
+ # copy image files
+ if self.images:
+ self.info(bold('copying images...'), nonl=1)
+ for src, dest in self.images.iteritems():
+ self.info(' '+src, nonl=1)
+ copyfile(path.join(self.srcdir, src),
+ path.join(self.outdir, dest))
+ self.info()
+
+ self.info(bold('copying Texinfo support files... '), nonl=True)
+ # copy Makefile
+ fn = path.join(self.outdir, 'Makefile')
+ self.info(fn, nonl=1)
+ try:
+ mkfile = open(fn, 'w')
+ try:
+ mkfile.write(TEXINFO_MAKEFILE)
+ finally:
+ mkfile.close()
+ except (IOError, OSError), err:
+ self.warn("error writing file %s: %s" % (fn, err))
+ self.info(' done')
diff --git a/sphinx/builders/text.py b/sphinx/builders/text.py
new file mode 100644
index 0000000..0aeeb5f
--- /dev/null
+++ b/sphinx/builders/text.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.text
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Plain-text Sphinx builder.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import codecs
+from os import path
+
+from docutils.io import StringOutput
+
+from sphinx.builders import Builder
+from sphinx.util.osutil import ensuredir, os_path
+from sphinx.writers.text import TextWriter
+
+
+class TextBuilder(Builder):
+ name = 'text'
+ format = 'text'
+ out_suffix = '.txt'
+ allow_parallel = True
+
+ def init(self):
+ pass
+
+ def get_outdated_docs(self):
+ for docname in self.env.found_docs:
+ if docname not in self.env.all_docs:
+ yield docname
+ continue
+ targetname = self.env.doc2path(docname, self.outdir,
+ self.out_suffix)
+ try:
+ targetmtime = path.getmtime(targetname)
+ except Exception:
+ targetmtime = 0
+ try:
+ srcmtime = path.getmtime(self.env.doc2path(docname))
+ if srcmtime > targetmtime:
+ yield docname
+ except EnvironmentError:
+ # source doesn't exist anymore
+ pass
+
+ def get_target_uri(self, docname, typ=None):
+ return ''
+
+ def prepare_writing(self, docnames):
+ self.writer = TextWriter(self)
+
+ def write_doc(self, docname, doctree):
+ self.current_docname = docname
+ destination = StringOutput(encoding='utf-8')
+ self.writer.write(doctree, destination)
+ outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
+ ensuredir(path.dirname(outfilename))
+ try:
+ f = codecs.open(outfilename, 'w', 'utf-8')
+ try:
+ f.write(self.writer.output)
+ finally:
+ f.close()
+ except (IOError, OSError), err:
+ self.warn("error writing file %s: %s" % (outfilename, err))
+
+ def finish(self):
+ pass
diff --git a/sphinx/builders/websupport.py b/sphinx/builders/websupport.py
new file mode 100644
index 0000000..6cf9810
--- /dev/null
+++ b/sphinx/builders/websupport.py
@@ -0,0 +1,160 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.websupport
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Builder for the web support package.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from os import path
+import posixpath
+import shutil
+
+from docutils.io import StringOutput
+
+from sphinx.jinja2glue import BuiltinTemplateLoader
+from sphinx.util.osutil import os_path, relative_uri, ensuredir, copyfile
+from sphinx.builders.html import PickleHTMLBuilder
+from sphinx.writers.websupport import WebSupportTranslator
+
+
+class WebSupportBuilder(PickleHTMLBuilder):
+ """
+ Builds documents for the web support package.
+ """
+ name = 'websupport'
+ versioning_method = 'commentable'
+
+ def init(self):
+ PickleHTMLBuilder.init(self)
+ # templates are needed for this builder, but the serializing
+ # builder does not initialize them
+ self.init_templates()
+ if not isinstance(self.templates, BuiltinTemplateLoader):
+ raise RuntimeError('websupport builder must be used with '
+ 'the builtin templates')
+ # add our custom JS
+ self.script_files.append('_static/websupport.js')
+
+ def set_webinfo(self, staticdir, virtual_staticdir, search, storage):
+ self.staticdir = staticdir
+ self.virtual_staticdir = virtual_staticdir
+ self.search = search
+ self.storage = storage
+
+ def init_translator_class(self):
+ self.translator_class = WebSupportTranslator
+
+ def prepare_writing(self, docnames):
+ PickleHTMLBuilder.prepare_writing(self, docnames)
+ self.globalcontext['no_search_suffix'] = True
+
+ def write_doc(self, docname, doctree):
+ destination = StringOutput(encoding='utf-8')
+ doctree.settings = self.docsettings
+
+ self.secnumbers = self.env.toc_secnumbers.get(docname, {})
+ self.imgpath = '/' + posixpath.join(self.virtual_staticdir, '_images')
+ self.dlpath = '/' + posixpath.join(self.virtual_staticdir, '_downloads')
+ self.current_docname = docname
+ self.docwriter.write(doctree, destination)
+ self.docwriter.assemble_parts()
+ body = self.docwriter.parts['fragment']
+ metatags = self.docwriter.clean_meta
+
+ ctx = self.get_doc_context(docname, body, metatags)
+ self.handle_page(docname, ctx, event_arg=doctree)
+
+ def write_doc_serialized(self, docname, doctree):
+ self.imgpath = '/' + posixpath.join(self.virtual_staticdir, '_images')
+ self.post_process_images(doctree)
+ title = self.env.longtitles.get(docname)
+ title = title and self.render_partial(title)['title'] or ''
+ self.index_page(docname, doctree, title)
+
+ def load_indexer(self, docnames):
+ self.indexer = self.search
+ self.indexer.init_indexing(changed=docnames)
+
+ def _render_page(self, pagename, addctx, templatename, event_arg=None):
+ # This is mostly copied from StandaloneHTMLBuilder. However, instead
+ # of rendering the template and saving the html, create a context
+ # dict and pickle it.
+ ctx = self.globalcontext.copy()
+ ctx['pagename'] = pagename
+
+ def pathto(otheruri, resource=False,
+ baseuri=self.get_target_uri(pagename)):
+ if resource and '://' in otheruri:
+ return otheruri
+ elif not resource:
+ otheruri = self.get_target_uri(otheruri)
+ return relative_uri(baseuri, otheruri) or '#'
+ else:
+ return '/' + posixpath.join(self.virtual_staticdir, otheruri)
+ ctx['pathto'] = pathto
+ ctx['hasdoc'] = lambda name: name in self.env.all_docs
+ ctx['encoding'] = self.config.html_output_encoding
+ ctx['toctree'] = lambda **kw: self._get_local_toctree(pagename, **kw)
+ self.add_sidebars(pagename, ctx)
+ ctx.update(addctx)
+
+ self.app.emit('html-page-context', pagename, templatename,
+ ctx, event_arg)
+
+ # create a dict that will be pickled and used by webapps
+ doc_ctx = {
+ 'body': ctx.get('body', ''),
+ 'title': ctx.get('title', ''),
+ }
+ # partially render the html template to get at interesting macros
+ template = self.templates.environment.get_template(templatename)
+ template_module = template.make_module(ctx)
+ for item in ['sidebar', 'relbar', 'script', 'css']:
+ if hasattr(template_module, item):
+ doc_ctx[item] = getattr(template_module, item)()
+
+ return ctx, doc_ctx
+
+ def handle_page(self, pagename, addctx, templatename='page.html',
+ outfilename=None, event_arg=None):
+ ctx, doc_ctx = self._render_page(pagename, addctx,
+ templatename, event_arg)
+
+ if not outfilename:
+ outfilename = path.join(self.outdir, 'pickles',
+ os_path(pagename) + self.out_suffix)
+ ensuredir(path.dirname(outfilename))
+ self.dump_context(doc_ctx, outfilename)
+
+ # if there is a source file, copy the source file for the
+ # "show source" link
+ if ctx.get('sourcename'):
+ source_name = path.join(self.staticdir,
+ '_sources', os_path(ctx['sourcename']))
+ ensuredir(path.dirname(source_name))
+ copyfile(self.env.doc2path(pagename), source_name)
+
+ def handle_finish(self):
+ # get global values for css and script files
+ _, doc_ctx = self._render_page('tmp', {}, 'page.html')
+ self.globalcontext['css'] = doc_ctx['css']
+ self.globalcontext['script'] = doc_ctx['script']
+
+ PickleHTMLBuilder.handle_finish(self)
+
+ # move static stuff over to separate directory
+ directories = ['_images', '_static']
+ for directory in directories:
+ src = path.join(self.outdir, directory)
+ dst = path.join(self.staticdir, directory)
+ if path.isdir(src):
+ if path.isdir(dst):
+ shutil.rmtree(dst)
+ shutil.move(src, dst)
+
+ def dump_search_index(self):
+ self.indexer.finish_indexing()
diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py
new file mode 100644
index 0000000..9a9aec9
--- /dev/null
+++ b/sphinx/builders/xml.py
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.builders.xml
+ ~~~~~~~~~~~~~~~~~~~
+
+ Docutils-native XML and pseudo-XML builders.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import codecs
+from os import path
+
+from docutils import nodes
+from docutils.io import StringOutput
+
+from sphinx.builders import Builder
+from sphinx.util.osutil import ensuredir, os_path
+from sphinx.writers.xml import XMLWriter, PseudoXMLWriter
+
+class XMLBuilder(Builder):
+ """
+ Builds Docutils-native XML.
+ """
+ name = 'xml'
+ format = 'xml'
+ out_suffix = '.xml'
+ allow_parallel = True
+
+ _writer_class = XMLWriter
+
+ def init(self):
+ pass
+
+ def get_outdated_docs(self):
+ for docname in self.env.found_docs:
+ if docname not in self.env.all_docs:
+ yield docname
+ continue
+ targetname = self.env.doc2path(docname, self.outdir,
+ self.out_suffix)
+ try:
+ targetmtime = path.getmtime(targetname)
+ except Exception:
+ targetmtime = 0
+ try:
+ srcmtime = path.getmtime(self.env.doc2path(docname))
+ if srcmtime > targetmtime:
+ yield docname
+ except EnvironmentError:
+ # source doesn't exist anymore
+ pass
+
+ def get_target_uri(self, docname, typ=None):
+ return docname
+
+ def prepare_writing(self, docnames):
+ self.writer = self._writer_class(self)
+
+ def write_doc(self, docname, doctree):
+ # work around multiple string % tuple issues in docutils;
+ # replace tuples in attribute values with lists
+ doctree = doctree.deepcopy()
+ for node in doctree.traverse(nodes.Element):
+ for att, value in node.attributes.items():
+ if isinstance(value, tuple):
+ node.attributes[att] = list(value)
+ value = node.attributes[att]
+ if isinstance(value, list):
+ for i, val in enumerate(value):
+ if isinstance(val, tuple):
+ value[i] = list(val)
+ destination = StringOutput(encoding='utf-8')
+ self.writer.write(doctree, destination)
+ outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
+ ensuredir(path.dirname(outfilename))
+ try:
+ f = codecs.open(outfilename, 'w', 'utf-8')
+ try:
+ f.write(self.writer.output)
+ finally:
+ f.close()
+ except (IOError, OSError), err:
+ self.warn("error writing file %s: %s" % (outfilename, err))
+
+ def finish(self):
+ pass
+
+
+class PseudoXMLBuilder(XMLBuilder):
+ """
+ Builds pseudo-XML for display purposes.
+ """
+ name = 'pseudoxml'
+ format = 'pseudoxml'
+ out_suffix = '.pseudoxml'
+
+ _writer_class = PseudoXMLWriter
diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py
new file mode 100644
index 0000000..ec24d90
--- /dev/null
+++ b/sphinx/cmdline.py
@@ -0,0 +1,296 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.cmdline
+ ~~~~~~~~~~~~~~
+
+ sphinx-build command-line handling.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import sys
+import getopt
+import traceback
+from os import path
+
+from docutils.utils import SystemMessage
+
+from sphinx import __version__
+from sphinx.errors import SphinxError
+from sphinx.application import Sphinx
+from sphinx.util import Tee, format_exception_cut_frames, save_traceback
+from sphinx.util.console import red, nocolor, color_terminal
+from sphinx.util.osutil import abspath, fs_encoding
+from sphinx.util.pycompat import terminal_safe, bytes
+
+
+def usage(argv, msg=None):
+ if msg:
+ print >>sys.stderr, msg
+ print >>sys.stderr
+ print >>sys.stderr, """\
+Sphinx v%s
+Usage: %s [options] sourcedir outdir [filenames...]
+
+General options
+^^^^^^^^^^^^^^^
+-b <builder> builder to use; default is html
+-a write all files; default is to only write new and changed files
+-E don't use a saved environment, always read all files
+-d <path> path for the cached environment and doctree files
+ (default: outdir/.doctrees)
+-j <N> build in parallel with N processes where possible
+-M <builder> "make" mode -- used by Makefile, like "sphinx-build -M html"
+
+Build configuration options
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+-c <path> path where configuration file (conf.py) is located
+ (default: same as sourcedir)
+-C use no config file at all, only -D options
+-D <setting=value> override a setting in configuration file
+-t <tag> define tag: include "only" blocks with <tag>
+-A <name=value> pass a value into the templates, for HTML builder
+-n nit-picky mode, warn about all missing references
+
+Console output options
+^^^^^^^^^^^^^^^^^^^^^^
+-v increase verbosity (can be repeated)
+-q no output on stdout, just warnings on stderr
+-Q no output at all, not even warnings
+-w <file> write warnings (and errors) to given file
+-W turn warnings into errors
+-T show full traceback on exception
+-N do not emit colored output
+-P run Pdb on exception
+
+Filename arguments
+^^^^^^^^^^^^^^^^^^
+* without -a and without filenames, write new and changed files.
+* with -a, write all files.
+* with filenames, write these.
+
+Standard options
+^^^^^^^^^^^^^^^^
+-h, --help show this help and exit
+--version show version information and exit
+""" % (__version__, argv[0])
+
+
+def main(argv):
+ if not color_terminal():
+ # Windows' poor cmd box doesn't understand ANSI sequences
+ nocolor()
+
+ # parse options
+ try:
+ opts, args = getopt.getopt(argv[1:], 'ab:t:d:c:CD:A:nNEqQWw:PThvj:',
+ ['help', 'version'])
+ except getopt.error, err:
+ usage(argv, 'Error: %s' % err)
+ return 1
+
+ # handle basic options
+ allopts = set(opt[0] for opt in opts)
+ # help and version options
+ if '-h' in allopts or '--help' in allopts:
+ usage(argv)
+ print >>sys.stderr
+ print >>sys.stderr, 'For more information, see <http://sphinx-doc.org/>.'
+ return 0
+ if '--version' in allopts:
+ print 'Sphinx (sphinx-build) %s' % __version__
+ return 0
+
+ # get paths (first and second positional argument)
+ try:
+ srcdir = confdir = abspath(args[0])
+ if not path.isdir(srcdir):
+ print >>sys.stderr, 'Error: Cannot find source directory `%s\'.' % (
+ srcdir,)
+ return 1
+ if not path.isfile(path.join(srcdir, 'conf.py')) and \
+ '-c' not in allopts and '-C' not in allopts:
+ print >>sys.stderr, ('Error: Source directory doesn\'t '
+ 'contain a conf.py file.')
+ return 1
+ outdir = abspath(args[1])
+ except IndexError:
+ usage(argv, 'Error: Insufficient arguments.')
+ return 1
+ except UnicodeError:
+ print >>sys.stderr, (
+ 'Error: Multibyte filename not supported on this filesystem '
+ 'encoding (%r).' % fs_encoding)
+ return 1
+
+ # handle remaining filename arguments
+ filenames = args[2:]
+ err = 0
+ for filename in filenames:
+ if not path.isfile(filename):
+ print >>sys.stderr, 'Error: Cannot find file %r.' % filename
+ err = 1
+ if err:
+ return 1
+
+ # likely encoding used for command-line arguments
+ try:
+ locale = __import__('locale') # due to submodule of the same name
+ likely_encoding = locale.getpreferredencoding()
+ except Exception:
+ likely_encoding = None
+
+ buildername = None
+ force_all = freshenv = warningiserror = use_pdb = False
+ show_traceback = False
+ verbosity = 0
+ parallel = 0
+ status = sys.stdout
+ warning = sys.stderr
+ error = sys.stderr
+ warnfile = None
+ confoverrides = {}
+ tags = []
+ doctreedir = path.join(outdir, '.doctrees')
+ for opt, val in opts:
+ if opt == '-b':
+ buildername = val
+ elif opt == '-a':
+ if filenames:
+ usage(argv, 'Error: Cannot combine -a option and filenames.')
+ return 1
+ force_all = True
+ elif opt == '-t':
+ tags.append(val)
+ elif opt == '-d':
+ doctreedir = abspath(val)
+ elif opt == '-c':
+ confdir = abspath(val)
+ if not path.isfile(path.join(confdir, 'conf.py')):
+ print >>sys.stderr, ('Error: Configuration directory '
+ 'doesn\'t contain conf.py file.')
+ return 1
+ elif opt == '-C':
+ confdir = None
+ elif opt == '-D':
+ try:
+ key, val = val.split('=')
+ except ValueError:
+ print >>sys.stderr, ('Error: -D option argument must be '
+ 'in the form name=value.')
+ return 1
+ try:
+ val = int(val)
+ except ValueError:
+ if likely_encoding and isinstance(val, bytes):
+ try:
+ val = val.decode(likely_encoding)
+ except UnicodeError:
+ pass
+ confoverrides[key] = val
+ elif opt == '-A':
+ try:
+ key, val = val.split('=')
+ except ValueError:
+ print >>sys.stderr, ('Error: -A option argument must be '
+ 'in the form name=value.')
+ return 1
+ try:
+ val = int(val)
+ except ValueError:
+ if likely_encoding and isinstance(val, bytes):
+ try:
+ val = val.decode(likely_encoding)
+ except UnicodeError:
+ pass
+ confoverrides['html_context.%s' % key] = val
+ elif opt == '-n':
+ confoverrides['nitpicky'] = True
+ elif opt == '-N':
+ nocolor()
+ elif opt == '-E':
+ freshenv = True
+ elif opt == '-q':
+ status = None
+ elif opt == '-Q':
+ status = None
+ warning = None
+ elif opt == '-W':
+ warningiserror = True
+ elif opt == '-w':
+ warnfile = val
+ elif opt == '-P':
+ use_pdb = True
+ elif opt == '-T':
+ show_traceback = True
+ elif opt == '-v':
+ verbosity += 1
+ show_traceback = True
+ elif opt == '-j':
+ try:
+ parallel = int(val)
+ except ValueError:
+ print >>sys.stderr, ('Error: -j option argument must be an '
+ 'integer.')
+ return 1
+
+ if warning and warnfile:
+ warnfp = open(warnfile, 'w')
+ warning = Tee(warning, warnfp)
+ error = warning
+
+ if not path.isdir(outdir):
+ if status:
+ print >>status, 'Making output directory...'
+ os.makedirs(outdir)
+
+ app = None
+ try:
+ app = Sphinx(srcdir, confdir, outdir, doctreedir, buildername,
+ confoverrides, status, warning, freshenv,
+ warningiserror, tags, verbosity, parallel)
+ app.build(force_all, filenames)
+ return app.statuscode
+ except (Exception, KeyboardInterrupt), err:
+ if use_pdb:
+ import pdb
+ print >>error, red('Exception occurred while building, '
+ 'starting debugger:')
+ traceback.print_exc()
+ pdb.post_mortem(sys.exc_info()[2])
+ else:
+ print >>error
+ if show_traceback:
+ traceback.print_exc(None, error)
+ print >>error
+ if isinstance(err, KeyboardInterrupt):
+ print >>error, 'interrupted!'
+ elif isinstance(err, SystemMessage):
+ print >>error, red('reST markup error:')
+ print >>error, terminal_safe(err.args[0])
+ elif isinstance(err, SphinxError):
+ print >>error, red('%s:' % err.category)
+ print >>error, terminal_safe(unicode(err))
+ elif isinstance(err, UnicodeError):
+ print >>error, red('Encoding error:')
+ print >>error, terminal_safe(unicode(err))
+ tbpath = save_traceback(app)
+ print >>error, red('The full traceback has been saved '
+ 'in %s, if you want to report the '
+ 'issue to the developers.' % tbpath)
+ else:
+ print >>error, red('Exception occurred:')
+ print >>error, format_exception_cut_frames().rstrip()
+ tbpath = save_traceback(app)
+ print >>error, red('The full traceback has been saved '
+ 'in %s, if you want to report the '
+ 'issue to the developers.' % tbpath)
+ print >>error, ('Please also report this if it was a user '
+ 'error, so that a better error message '
+ 'can be provided next time.')
+ print >>error, (
+ 'A bug report can be filed in the tracker at '
+ '<https://bitbucket.org/birkenfeld/sphinx/issues/>. Thanks!')
+ return 1
diff --git a/sphinx/config.py b/sphinx/config.py
new file mode 100644
index 0000000..a4fc234
--- /dev/null
+++ b/sphinx/config.py
@@ -0,0 +1,284 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.config
+ ~~~~~~~~~~~~~
+
+ Build configuration file handling.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import sys
+from os import path
+
+from sphinx.errors import ConfigError
+from sphinx.locale import l_
+from sphinx.util.osutil import make_filename
+from sphinx.util.pycompat import bytes, b, execfile_
+
+nonascii_re = re.compile(b(r'[\x80-\xff]'))
+
+CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s"
+if sys.version_info >= (3, 0):
+ CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
+
+class Config(object):
+ """
+ Configuration file abstraction.
+ """
+
+ # the values are: (default, what needs to be rebuilt if changed)
+
+ # If you add a value here, don't forget to include it in the
+ # quickstart.py file template as well as in the docs!
+
+ config_values = dict(
+ # general options
+ project = ('Python', 'env'),
+ copyright = ('', 'html'),
+ version = ('', 'env'),
+ release = ('', 'env'),
+ today = ('', 'env'),
+ today_fmt = (None, 'env'), # the real default is locale-dependent
+
+ language = (None, 'env'),
+ locale_dirs = ([], 'env'),
+
+ master_doc = ('contents', 'env'),
+ source_suffix = ('.rst', 'env'),
+ source_encoding = ('utf-8-sig', 'env'),
+ exclude_patterns = ([], 'env'),
+ # the next three are all deprecated now
+ unused_docs = ([], 'env'),
+ exclude_trees = ([], 'env'),
+ exclude_dirnames = ([], 'env'),
+ default_role = (None, 'env'),
+ add_function_parentheses = (True, 'env'),
+ add_module_names = (True, 'env'),
+ trim_footnote_reference_space = (False, 'env'),
+ show_authors = (False, 'env'),
+ pygments_style = (None, 'html'),
+ highlight_language = ('python', 'env'),
+ templates_path = ([], 'html'),
+ template_bridge = (None, 'html'),
+ keep_warnings = (False, 'env'),
+ modindex_common_prefix = ([], 'html'),
+ rst_epilog = (None, 'env'),
+ rst_prolog = (None, 'env'),
+ trim_doctest_flags = (True, 'env'),
+ primary_domain = ('py', 'env'),
+ needs_sphinx = (None, None),
+ nitpicky = (False, 'env'),
+ nitpick_ignore = ([], 'html'),
+
+ # HTML options
+ html_theme = ('default', 'html'),
+ html_theme_path = ([], 'html'),
+ html_theme_options = ({}, 'html'),
+ html_title = (lambda self: l_('%s %s documentation') %
+ (self.project, self.release),
+ 'html'),
+ html_short_title = (lambda self: self.html_title, 'html'),
+ html_style = (None, 'html'),
+ html_logo = (None, 'html'),
+ html_favicon = (None, 'html'),
+ html_static_path = ([], 'html'),
+ html_extra_path = ([], 'html'),
+ # the real default is locale-dependent
+ html_last_updated_fmt = (None, 'html'),
+ html_use_smartypants = (True, 'html'),
+ html_translator_class = (None, 'html'),
+ html_sidebars = ({}, 'html'),
+ html_additional_pages = ({}, 'html'),
+ html_use_modindex = (True, 'html'), # deprecated
+ html_domain_indices = (True, 'html'),
+ html_add_permalinks = (u'\u00B6', 'html'),
+ html_use_index = (True, 'html'),
+ html_split_index = (False, 'html'),
+ html_copy_source = (True, 'html'),
+ html_show_sourcelink = (True, 'html'),
+ html_use_opensearch = ('', 'html'),
+ html_file_suffix = (None, 'html'),
+ html_link_suffix = (None, 'html'),
+ html_show_copyright = (True, 'html'),
+ html_show_sphinx = (True, 'html'),
+ html_context = ({}, 'html'),
+ html_output_encoding = ('utf-8', 'html'),
+ html_compact_lists = (True, 'html'),
+ html_secnumber_suffix = ('. ', 'html'),
+ html_search_language = (None, 'html'),
+ html_search_options = ({}, 'html'),
+ html_search_scorer = ('', None),
+
+ # HTML help only options
+ htmlhelp_basename = (lambda self: make_filename(self.project), None),
+
+ # Qt help only options
+ qthelp_basename = (lambda self: make_filename(self.project), None),
+
+ # Devhelp only options
+ devhelp_basename = (lambda self: make_filename(self.project), None),
+
+ # Epub options
+ epub_basename = (lambda self: make_filename(self.project), None),
+ epub_theme = ('epub', 'html'),
+ epub_theme_options = ({}, 'html'),
+ epub_title = (lambda self: self.html_title, 'html'),
+ epub_author = ('unknown', 'html'),
+ epub_language = (lambda self: self.language or 'en', 'html'),
+ epub_publisher = ('unknown', 'html'),
+ epub_copyright = (lambda self: self.copyright, 'html'),
+ epub_identifier = ('unknown', 'html'),
+ epub_scheme = ('unknown', 'html'),
+ epub_uid = ('unknown', 'env'),
+ epub_cover = ((), 'env'),
+ epub_guide = ((), 'env'),
+ epub_pre_files = ([], 'env'),
+ epub_post_files = ([], 'env'),
+ epub_exclude_files = ([], 'env'),
+ epub_tocdepth = (3, 'env'),
+ epub_tocdup = (True, 'env'),
+ epub_tocscope = ('default', 'env'),
+ epub_fix_images = (False, 'env'),
+ epub_max_image_width = (0, 'env'),
+ epub_show_urls = ('inline', 'html'),
+ epub_use_index = (lambda self: self.html_use_index, 'html'),
+
+ # LaTeX options
+ latex_documents = (lambda self: [(self.master_doc,
+ make_filename(self.project) + '.tex',
+ self.project,
+ '', 'manual')],
+ None),
+ latex_logo = (None, None),
+ latex_appendices = ([], None),
+ latex_use_parts = (False, None),
+ latex_use_modindex = (True, None), # deprecated
+ latex_domain_indices = (True, None),
+ latex_show_urls = ('no', None),
+ latex_show_pagerefs = (False, None),
+ # paper_size and font_size are still separate values
+ # so that you can give them easily on the command line
+ latex_paper_size = ('letter', None),
+ latex_font_size = ('10pt', None),
+ latex_elements = ({}, None),
+ latex_additional_files = ([], None),
+ latex_docclass = ({}, None),
+ # now deprecated - use latex_elements
+ latex_preamble = ('', None),
+
+ # text options
+ text_sectionchars = ('*=-~"+`', 'env'),
+ text_newlines = ('unix', 'env'),
+
+ # manpage options
+ man_pages = (lambda self: [(self.master_doc,
+ make_filename(self.project).lower(),
+ '%s %s' % (self.project, self.release),
+ [], 1)],
+ None),
+ man_show_urls = (False, None),
+
+ # Texinfo options
+ texinfo_documents = (lambda self: [(self.master_doc,
+ make_filename(self.project).lower(),
+ self.project, '',
+ make_filename(self.project),
+ 'The %s reference manual.' %
+ make_filename(self.project),
+ 'Python')],
+ None),
+ texinfo_appendices = ([], None),
+ texinfo_elements = ({}, None),
+ texinfo_domain_indices = (True, None),
+ texinfo_show_urls = ('footnote', None),
+ texinfo_no_detailmenu = (False, None),
+
+ # linkcheck options
+ linkcheck_ignore = ([], None),
+ linkcheck_timeout = (None, None),
+ linkcheck_workers = (5, None),
+ linkcheck_anchors = (True, None),
+
+ # gettext options
+ gettext_compact = (True, 'gettext'),
+
+ # XML options
+ xml_pretty = (True, 'env'),
+ )
+
+ def __init__(self, dirname, filename, overrides, tags):
+ self.overrides = overrides
+ self.values = Config.config_values.copy()
+ config = {}
+ if "extensions" in overrides:
+ config["extensions"] = overrides["extensions"]
+ if dirname is not None:
+ config_file = path.join(dirname, filename)
+ config['__file__'] = config_file
+ config['tags'] = tags
+ olddir = os.getcwd()
+ try:
+ # we promise to have the config dir as current dir while the
+ # config file is executed
+ os.chdir(dirname)
+ try:
+ execfile_(filename, config)
+ except SyntaxError, err:
+ raise ConfigError(CONFIG_SYNTAX_ERROR % err)
+ finally:
+ os.chdir(olddir)
+
+ self._raw_config = config
+ # these two must be preinitialized because extensions can add their
+ # own config values
+ self.setup = config.get('setup', None)
+ self.extensions = config.get('extensions', [])
+
+ def check_unicode(self, warn):
+ # check all string values for non-ASCII characters in bytestrings,
+ # since that can result in UnicodeErrors all over the place
+ for name, value in self._raw_config.iteritems():
+ if isinstance(value, bytes) and nonascii_re.search(value):
+ warn('the config value %r is set to a string with non-ASCII '
+ 'characters; this can lead to Unicode errors occurring. '
+ 'Please use Unicode strings, e.g. %r.' % (name, u'Content')
+ )
+
+ def init_values(self):
+ config = self._raw_config
+ for valname, value in self.overrides.iteritems():
+ if '.' in valname:
+ realvalname, key = valname.split('.', 1)
+ config.setdefault(realvalname, {})[key] = value
+ else:
+ config[valname] = value
+ for name in config:
+ if name in self.values:
+ self.__dict__[name] = config[name]
+ del self._raw_config
+
+ def __getattr__(self, name):
+ if name.startswith('_'):
+ raise AttributeError(name)
+ if name not in self.values:
+ raise AttributeError('No such config value: %s' % name)
+ default = self.values[name][0]
+ if hasattr(default, '__call__'):
+ return default(self)
+ return default
+
+ def __getitem__(self, name):
+ return getattr(self, name)
+
+ def __setitem__(self, name, value):
+ setattr(self, name, value)
+
+ def __delitem__(self, name):
+ delattr(self, name)
+
+ def __contains__(self, name):
+ return name in self.values
diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py
new file mode 100644
index 0000000..250a013
--- /dev/null
+++ b/sphinx/directives/__init__.py
@@ -0,0 +1,192 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.directives
+ ~~~~~~~~~~~~~~~~~
+
+ Handlers for additional ReST directives.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from docutils.parsers.rst import Directive, directives
+
+from sphinx import addnodes
+from sphinx.util.docfields import DocFieldTransformer
+
+# import and register directives
+from sphinx.directives.code import *
+from sphinx.directives.other import *
+
+
+# RE to strip backslash escapes
+nl_escape_re = re.compile(r'\\\n')
+strip_backslash_re = re.compile(r'\\(.)')
+
+
+class ObjectDescription(Directive):
+ """
+ Directive to describe a class, function or similar object. Not used
+ directly, but subclassed (in domain-specific directives) to add custom
+ behavior.
+ """
+
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {
+ 'noindex': directives.flag,
+ }
+
+ # types of doc fields that this directive handles, see sphinx.util.docfields
+ doc_field_types = []
+
+ def get_signatures(self):
+ """
+ Retrieve the signatures to document from the directive arguments. By
+ default, signatures are given as arguments, one per line.
+
+ Backslash-escaping of newlines is supported.
+ """
+ lines = nl_escape_re.sub('', self.arguments[0]).split('\n')
+ # remove backslashes to support (dummy) escapes; helps Vim highlighting
+ return [strip_backslash_re.sub(r'\1', line.strip()) for line in lines]
+
+ def handle_signature(self, sig, signode):
+ """
+ Parse the signature *sig* into individual nodes and append them to
+ *signode*. If ValueError is raised, parsing is aborted and the whole
+ *sig* is put into a single desc_name node.
+
+ The return value should be a value that identifies the object. It is
+ passed to :meth:`add_target_and_index()` unchanged, and otherwise only
+ used to skip duplicates.
+ """
+ raise ValueError
+
+ def add_target_and_index(self, name, sig, signode):
+ """
+ Add cross-reference IDs and entries to self.indexnode, if applicable.
+
+ *name* is whatever :meth:`handle_signature()` returned.
+ """
+ return # do nothing by default
+
+ def before_content(self):
+ """
+ Called before parsing content. Used to set information about the current
+ directive context on the build environment.
+ """
+ pass
+
+ def after_content(self):
+ """
+ Called after parsing content. Used to reset information about the
+ current directive context on the build environment.
+ """
+ pass
+
+ def run(self):
+ """
+ Main directive entry function, called by docutils upon encountering the
+ directive.
+
+ This directive is meant to be quite easily subclassable, so it delegates
+ to several additional methods. What it does:
+
+ * find out if called as a domain-specific directive, set self.domain
+ * create a `desc` node to fit all description inside
+ * parse standard options, currently `noindex`
+ * create an index node if needed as self.indexnode
+ * parse all given signatures (as returned by self.get_signatures())
+ using self.handle_signature(), which should either return a name
+ or raise ValueError
+ * add index entries using self.add_target_and_index()
+ * parse the content and handle doc fields in it
+ """
+ if ':' in self.name:
+ self.domain, self.objtype = self.name.split(':', 1)
+ else:
+ self.domain, self.objtype = '', self.name
+ self.env = self.state.document.settings.env
+ self.indexnode = addnodes.index(entries=[])
+
+ node = addnodes.desc()
+ node.document = self.state.document
+ node['domain'] = self.domain
+ # 'desctype' is a backwards compatible attribute
+ node['objtype'] = node['desctype'] = self.objtype
+ node['noindex'] = noindex = ('noindex' in self.options)
+
+ self.names = []
+ signatures = self.get_signatures()
+ for i, sig in enumerate(signatures):
+ # add a signature node for each signature in the current unit
+ # and add a reference target for it
+ signode = addnodes.desc_signature(sig, '')
+ signode['first'] = False
+ node.append(signode)
+ try:
+ # name can also be a tuple, e.g. (classname, objname);
+ # this is strictly domain-specific (i.e. no assumptions may
+ # be made in this base class)
+ name = self.handle_signature(sig, signode)
+ except ValueError:
+ # signature parsing failed
+ signode.clear()
+ signode += addnodes.desc_name(sig, sig)
+ continue # we don't want an index entry here
+ if name not in self.names:
+ self.names.append(name)
+ if not noindex:
+ # only add target and index entry if this is the first
+ # description of the object with this name in this desc block
+ self.add_target_and_index(name, sig, signode)
+
+ contentnode = addnodes.desc_content()
+ node.append(contentnode)
+ if self.names:
+ # needed for association of version{added,changed} directives
+ self.env.temp_data['object'] = self.names[0]
+ self.before_content()
+ self.state.nested_parse(self.content, self.content_offset, contentnode)
+ DocFieldTransformer(self).transform_all(contentnode)
+ self.env.temp_data['object'] = None
+ self.after_content()
+ return [self.indexnode, node]
+
+# backwards compatible old name
+DescDirective = ObjectDescription
+
+
+class DefaultDomain(Directive):
+ """
+ Directive to (re-)set the default domain for this source file.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ domain_name = self.arguments[0].lower()
+ # if domain_name not in env.domains:
+ # # try searching by label
+ # for domain in env.domains.itervalues():
+ # if domain.label.lower() == domain_name:
+ # domain_name = domain.name
+ # break
+ env.temp_data['default_domain'] = env.domains.get(domain_name)
+ return []
+
+
+directives.register_directive('default-domain', DefaultDomain)
+directives.register_directive('describe', ObjectDescription)
+# new, more consistent, name
+directives.register_directive('object', ObjectDescription)
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
new file mode 100644
index 0000000..9bfac5a
--- /dev/null
+++ b/sphinx/directives/code.py
@@ -0,0 +1,219 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.directives.code
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import codecs
+
+from docutils import nodes
+from docutils.parsers.rst import Directive, directives
+
+from sphinx import addnodes
+from sphinx.util import parselinenos
+from sphinx.util.nodes import set_source_info
+
+
+class Highlight(Directive):
+ """
+ Directive to set the highlighting language for code blocks, as well
+ as the threshold for line numbers.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {
+ 'linenothreshold': directives.unchanged,
+ }
+
+ def run(self):
+ if 'linenothreshold' in self.options:
+ try:
+ linenothreshold = int(self.options['linenothreshold'])
+ except Exception:
+ linenothreshold = 10
+ else:
+ linenothreshold = sys.maxint
+ return [addnodes.highlightlang(lang=self.arguments[0].strip(),
+ linenothreshold=linenothreshold)]
+
+
+class CodeBlock(Directive):
+ """
+ Directive for a code block with special highlighting or line numbering
+ settings.
+ """
+
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {
+ 'linenos': directives.flag,
+ 'emphasize-lines': directives.unchanged_required,
+ }
+
+ def run(self):
+ code = u'\n'.join(self.content)
+
+ linespec = self.options.get('emphasize-lines')
+ if linespec:
+ try:
+ nlines = len(self.content)
+ hl_lines = [x+1 for x in parselinenos(linespec, nlines)]
+ except ValueError, err:
+ document = self.state.document
+ return [document.reporter.warning(str(err), line=self.lineno)]
+ else:
+ hl_lines = None
+
+ literal = nodes.literal_block(code, code)
+ literal['language'] = self.arguments[0]
+ literal['linenos'] = 'linenos' in self.options
+ if hl_lines is not None:
+ literal['highlight_args'] = {'hl_lines': hl_lines}
+ set_source_info(self, literal)
+ return [literal]
+
+
+class LiteralInclude(Directive):
+ """
+ Like ``.. include:: :literal:``, but only warns if the include file is
+ not found, and does not raise errors. Also has several options for
+ selecting what to include.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {
+ 'linenos': directives.flag,
+ 'tab-width': int,
+ 'language': directives.unchanged_required,
+ 'encoding': directives.encoding,
+ 'pyobject': directives.unchanged_required,
+ 'lines': directives.unchanged_required,
+ 'start-after': directives.unchanged_required,
+ 'end-before': directives.unchanged_required,
+ 'prepend': directives.unchanged_required,
+ 'append': directives.unchanged_required,
+ 'emphasize-lines': directives.unchanged_required,
+ }
+
+ def run(self):
+ document = self.state.document
+ if not document.settings.file_insertion_enabled:
+ return [document.reporter.warning('File insertion disabled',
+ line=self.lineno)]
+ env = document.settings.env
+ rel_filename, filename = env.relfn2path(self.arguments[0])
+
+ if 'pyobject' in self.options and 'lines' in self.options:
+ return [document.reporter.warning(
+ 'Cannot use both "pyobject" and "lines" options',
+ line=self.lineno)]
+
+ encoding = self.options.get('encoding', env.config.source_encoding)
+ codec_info = codecs.lookup(encoding)
+ f = None
+ try:
+ f = codecs.StreamReaderWriter(open(filename, 'rb'),
+ codec_info[2], codec_info[3], 'strict')
+ lines = f.readlines()
+ except (IOError, OSError):
+ return [document.reporter.warning(
+ 'Include file %r not found or reading it failed' % filename,
+ line=self.lineno)]
+ except UnicodeError:
+ return [document.reporter.warning(
+ 'Encoding %r used for reading included file %r seems to '
+ 'be wrong, try giving an :encoding: option' %
+ (encoding, filename))]
+ finally:
+ if f is not None:
+ f.close()
+
+ objectname = self.options.get('pyobject')
+ if objectname is not None:
+ from sphinx.pycode import ModuleAnalyzer
+ analyzer = ModuleAnalyzer.for_file(filename, '')
+ tags = analyzer.find_tags()
+ if objectname not in tags:
+ return [document.reporter.warning(
+ 'Object named %r not found in include file %r' %
+ (objectname, filename), line=self.lineno)]
+ else:
+ lines = lines[tags[objectname][1]-1 : tags[objectname][2]-1]
+
+ linespec = self.options.get('lines')
+ if linespec is not None:
+ try:
+ linelist = parselinenos(linespec, len(lines))
+ except ValueError, err:
+ return [document.reporter.warning(str(err), line=self.lineno)]
+ # just ignore nonexisting lines
+ nlines = len(lines)
+ lines = [lines[i] for i in linelist if i < nlines]
+ if not lines:
+ return [document.reporter.warning(
+ 'Line spec %r: no lines pulled from include file %r' %
+ (linespec, filename), line=self.lineno)]
+
+ linespec = self.options.get('emphasize-lines')
+ if linespec:
+ try:
+ hl_lines = [x+1 for x in parselinenos(linespec, len(lines))]
+ except ValueError, err:
+ return [document.reporter.warning(str(err), line=self.lineno)]
+ else:
+ hl_lines = None
+
+ startafter = self.options.get('start-after')
+ endbefore = self.options.get('end-before')
+ prepend = self.options.get('prepend')
+ append = self.options.get('append')
+ if startafter is not None or endbefore is not None:
+ use = not startafter
+ res = []
+ for line in lines:
+ if not use and startafter and startafter in line:
+ use = True
+ elif use and endbefore and endbefore in line:
+ use = False
+ break
+ elif use:
+ res.append(line)
+ lines = res
+
+ if prepend:
+ lines.insert(0, prepend + '\n')
+ if append:
+ lines.append(append + '\n')
+
+ text = ''.join(lines)
+ if self.options.get('tab-width'):
+ text = text.expandtabs(self.options['tab-width'])
+ retnode = nodes.literal_block(text, text, source=filename)
+ set_source_info(self, retnode)
+ if self.options.get('language', ''):
+ retnode['language'] = self.options['language']
+ if 'linenos' in self.options:
+ retnode['linenos'] = True
+ if hl_lines is not None:
+ retnode['highlight_args'] = {'hl_lines': hl_lines}
+ env.note_dependency(rel_filename)
+ return [retnode]
+
+
+directives.register_directive('highlight', Highlight)
+directives.register_directive('highlightlang', Highlight) # old
+directives.register_directive('code-block', CodeBlock)
+directives.register_directive('sourcecode', CodeBlock)
+directives.register_directive('literalinclude', LiteralInclude)
diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py
new file mode 100644
index 0000000..d28c00f
--- /dev/null
+++ b/sphinx/directives/other.py
@@ -0,0 +1,418 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.directives.other
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+from docutils.parsers.rst import Directive, directives
+from docutils.parsers.rst.directives.admonitions import BaseAdmonition
+from docutils.parsers.rst.directives.misc import Class
+from docutils.parsers.rst.directives.misc import Include as BaseInclude
+
+from sphinx import addnodes
+from sphinx.locale import versionlabels, _
+from sphinx.util import url_re, docname_join
+from sphinx.util.nodes import explicit_title_re, set_source_info, \
+ process_index_entry
+from sphinx.util.matching import patfilter
+
+
+def int_or_nothing(argument):
+ if not argument:
+ return 999
+ return int(argument)
+
+
+class TocTree(Directive):
+ """
+ Directive to notify Sphinx about the hierarchical structure of the docs,
+ and to include a table-of-contents like tree in the current document.
+ """
+ has_content = True
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {
+ 'maxdepth': int,
+ 'glob': directives.flag,
+ 'hidden': directives.flag,
+ 'includehidden': directives.flag,
+ 'numbered': int_or_nothing,
+ 'titlesonly': directives.flag,
+ }
+
+ def run(self):
+ env = self.state.document.settings.env
+ suffix = env.config.source_suffix
+ glob = 'glob' in self.options
+
+ ret = []
+ # (title, ref) pairs, where ref may be a document, or an external link,
+ # and title may be None if the document's title is to be used
+ entries = []
+ includefiles = []
+ all_docnames = env.found_docs.copy()
+ # don't add the currently visited file in catch-all patterns
+ all_docnames.remove(env.docname)
+ for entry in self.content:
+ if not entry:
+ continue
+ if not glob:
+ # look for explicit titles ("Some Title <document>")
+ m = explicit_title_re.match(entry)
+ if m:
+ ref = m.group(2)
+ title = m.group(1)
+ docname = ref
+ else:
+ ref = docname = entry
+ title = None
+ # remove suffixes (backwards compatibility)
+ if docname.endswith(suffix):
+ docname = docname[:-len(suffix)]
+ # absolutize filenames
+ docname = docname_join(env.docname, docname)
+ if url_re.match(ref) or ref == 'self':
+ entries.append((title, ref))
+ elif docname not in env.found_docs:
+ ret.append(self.state.document.reporter.warning(
+ 'toctree contains reference to nonexisting '
+ 'document %r' % docname, line=self.lineno))
+ env.note_reread()
+ else:
+ entries.append((title, docname))
+ includefiles.append(docname)
+ else:
+ patname = docname_join(env.docname, entry)
+ docnames = sorted(patfilter(all_docnames, patname))
+ for docname in docnames:
+ all_docnames.remove(docname) # don't include it again
+ entries.append((None, docname))
+ includefiles.append(docname)
+ if not docnames:
+ ret.append(self.state.document.reporter.warning(
+ 'toctree glob pattern %r didn\'t match any documents'
+ % entry, line=self.lineno))
+ subnode = addnodes.toctree()
+ subnode['parent'] = env.docname
+ # entries contains all entries (self references, external links etc.)
+ subnode['entries'] = entries
+ # includefiles only entries that are documents
+ subnode['includefiles'] = includefiles
+ subnode['maxdepth'] = self.options.get('maxdepth', -1)
+ subnode['glob'] = glob
+ subnode['hidden'] = 'hidden' in self.options
+ subnode['includehidden'] = 'includehidden' in self.options
+ subnode['numbered'] = self.options.get('numbered', 0)
+ subnode['titlesonly'] = 'titlesonly' in self.options
+ set_source_info(self, subnode)
+ wrappernode = nodes.compound(classes=['toctree-wrapper'])
+ wrappernode.append(subnode)
+ ret.append(wrappernode)
+ return ret
+
+
+class Author(Directive):
+ """
+ Directive to give the name of the author of the current document
+ or section. Shown in the output only if the show_authors option is on.
+ """
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ if not env.config.show_authors:
+ return []
+ para = nodes.paragraph()
+ emph = nodes.emphasis()
+ para += emph
+ if self.name == 'sectionauthor':
+ text = _('Section author: ')
+ elif self.name == 'moduleauthor':
+ text = _('Module author: ')
+ elif self.name == 'codeauthor':
+ text = _('Code author: ')
+ else:
+ text = _('Author: ')
+ emph += nodes.Text(text, text)
+ inodes, messages = self.state.inline_text(self.arguments[0],
+ self.lineno)
+ emph.extend(inodes)
+ return [para] + messages
+
+
+class Index(Directive):
+ """
+ Directive to add entries to the index.
+ """
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ arguments = self.arguments[0].split('\n')
+ env = self.state.document.settings.env
+ targetid = 'index-%s' % env.new_serialno('index')
+ targetnode = nodes.target('', '', ids=[targetid])
+ self.state.document.note_explicit_target(targetnode)
+ indexnode = addnodes.index()
+ indexnode['entries'] = ne = []
+ indexnode['inline'] = False
+ set_source_info(self, indexnode)
+ for entry in arguments:
+ ne.extend(process_index_entry(entry, targetid))
+ return [indexnode, targetnode]
+
+
+class VersionChange(Directive):
+ """
+ Directive to describe a change/addition/deprecation in a specific version.
+ """
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 1
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ node = addnodes.versionmodified()
+ node.document = self.state.document
+ set_source_info(self, node)
+ node['type'] = self.name
+ node['version'] = self.arguments[0]
+ text = versionlabels[self.name] % self.arguments[0]
+ if len(self.arguments) == 2:
+ inodes, messages = self.state.inline_text(self.arguments[1],
+ self.lineno+1)
+ para = nodes.paragraph(self.arguments[1], '', *inodes)
+ set_source_info(self, para)
+ node.append(para)
+ else:
+ messages = []
+ if self.content:
+ self.state.nested_parse(self.content, self.content_offset, node)
+ if len(node):
+ if isinstance(node[0], nodes.paragraph) and node[0].rawsource:
+ content = nodes.inline(node[0].rawsource, translatable=True)
+ content.source = node[0].source
+ content.line = node[0].line
+ content += node[0].children
+ node[0].replace_self(nodes.paragraph('', '', content))
+ node[0].insert(0, nodes.inline('', '%s: ' % text,
+ classes=['versionmodified']))
+ else:
+ para = nodes.paragraph('', '',
+ nodes.inline('', '%s.' % text, classes=['versionmodified']))
+ node.append(para)
+ env = self.state.document.settings.env
+ # XXX should record node.source as well
+ env.note_versionchange(node['type'], node['version'], node, node.line)
+ return [node] + messages
+
+
+class SeeAlso(BaseAdmonition):
+ """
+ An admonition mentioning things to look at as reference.
+ """
+ node_class = addnodes.seealso
+
+
+class TabularColumns(Directive):
+ """
+ Directive to give an explicit tabulary column definition to LaTeX.
+ """
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ node = addnodes.tabular_col_spec()
+ node['spec'] = self.arguments[0]
+ set_source_info(self, node)
+ return [node]
+
+
+class Centered(Directive):
+ """
+ Directive to create a centered line of bold text.
+ """
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ if not self.arguments:
+ return []
+ subnode = addnodes.centered()
+ inodes, messages = self.state.inline_text(self.arguments[0],
+ self.lineno)
+ subnode.extend(inodes)
+ return [subnode] + messages
+
+
+class Acks(Directive):
+ """
+ Directive for a list of names.
+ """
+ has_content = True
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {}
+
+ def run(self):
+ node = addnodes.acks()
+ node.document = self.state.document
+ self.state.nested_parse(self.content, self.content_offset, node)
+ if len(node.children) != 1 or not isinstance(node.children[0],
+ nodes.bullet_list):
+ return [self.state.document.reporter.warning(
+ '.. acks content is not a list', line=self.lineno)]
+ return [node]
+
+
+class HList(Directive):
+ """
+ Directive for a list that gets compacted horizontally.
+ """
+ has_content = True
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {
+ 'columns': int,
+ }
+
+ def run(self):
+ ncolumns = self.options.get('columns', 2)
+ node = nodes.paragraph()
+ node.document = self.state.document
+ self.state.nested_parse(self.content, self.content_offset, node)
+ if len(node.children) != 1 or not isinstance(node.children[0],
+ nodes.bullet_list):
+ return [self.state.document.reporter.warning(
+ '.. hlist content is not a list', line=self.lineno)]
+ fulllist = node.children[0]
+ # create a hlist node where the items are distributed
+ npercol, nmore = divmod(len(fulllist), ncolumns)
+ index = 0
+ newnode = addnodes.hlist()
+ for column in range(ncolumns):
+ endindex = index + (column < nmore and (npercol+1) or npercol)
+ col = addnodes.hlistcol()
+ col += nodes.bullet_list()
+ col[0] += fulllist.children[index:endindex]
+ index = endindex
+ newnode += col
+ return [newnode]
+
+
+class Only(Directive):
+ """
+ Directive to only include text if the given tag(s) are enabled.
+ """
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ node = addnodes.only()
+ node.document = self.state.document
+ set_source_info(self, node)
+ node['expr'] = self.arguments[0]
+
+ # Same as util.nested_parse_with_titles but try to handle nested
+ # sections which should be raised higher up the doctree.
+ surrounding_title_styles = self.state.memo.title_styles
+ surrounding_section_level = self.state.memo.section_level
+ self.state.memo.title_styles = []
+ self.state.memo.section_level = 0
+ try:
+ self.state.nested_parse(self.content, self.content_offset,
+ node, match_titles=1)
+ title_styles = self.state.memo.title_styles
+ if (not surrounding_title_styles
+ or not title_styles
+ or title_styles[0] not in surrounding_title_styles
+ or not self.state.parent):
+ # No nested sections so no special handling needed.
+ return [node]
+ # Calculate the depths of the current and nested sections.
+ current_depth = 0
+ parent = self.state.parent
+ while parent:
+ current_depth += 1
+ parent = parent.parent
+ current_depth -= 2
+ title_style = title_styles[0]
+ nested_depth = len(surrounding_title_styles)
+ if title_style in surrounding_title_styles:
+ nested_depth = surrounding_title_styles.index(title_style)
+ # Use these depths to determine where the nested sections should
+ # be placed in the doctree.
+ n_sects_to_raise = current_depth - nested_depth + 1
+ parent = self.state.parent
+ for i in xrange(n_sects_to_raise):
+ if parent.parent:
+ parent = parent.parent
+ parent.append(node)
+ return []
+ finally:
+ self.state.memo.title_styles = surrounding_title_styles
+ self.state.memo.section_level = surrounding_section_level
+
+
+class Include(BaseInclude):
+ """
+ Like the standard "Include" directive, but interprets absolute paths
+ "correctly", i.e. relative to source directory.
+ """
+
+ def run(self):
+ env = self.state.document.settings.env
+ if self.arguments[0].startswith('<') and \
+ self.arguments[0].endswith('>'):
+ # docutils "standard" includes, do not do path processing
+ return BaseInclude.run(self)
+ rel_filename, filename = env.relfn2path(self.arguments[0])
+ self.arguments[0] = filename
+ return BaseInclude.run(self)
+
+
+directives.register_directive('toctree', TocTree)
+directives.register_directive('sectionauthor', Author)
+directives.register_directive('moduleauthor', Author)
+directives.register_directive('codeauthor', Author)
+directives.register_directive('index', Index)
+directives.register_directive('deprecated', VersionChange)
+directives.register_directive('versionadded', VersionChange)
+directives.register_directive('versionchanged', VersionChange)
+directives.register_directive('seealso', SeeAlso)
+directives.register_directive('tabularcolumns', TabularColumns)
+directives.register_directive('centered', Centered)
+directives.register_directive('acks', Acks)
+directives.register_directive('hlist', HList)
+directives.register_directive('only', Only)
+directives.register_directive('include', Include)
+
+# register the standard rst class directive under a different name
+# only for backwards compatibility now
+directives.register_directive('cssclass', Class)
+# new standard name when default-domain with "class" is in effect
+directives.register_directive('rst-class', Class)
diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py
new file mode 100644
index 0000000..200fd51
--- /dev/null
+++ b/sphinx/domains/__init__.py
@@ -0,0 +1,261 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.domains
+ ~~~~~~~~~~~~~~
+
+ Support for domains, which are groupings of description directives
+ and roles describing e.g. constructs of one programming language.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.errors import SphinxError
+from sphinx.locale import _
+
+
+class ObjType(object):
+ """
+ An ObjType is the description for a type of object that a domain can
+ document. In the object_types attribute of Domain subclasses, object type
+ names are mapped to instances of this class.
+
+ Constructor arguments:
+
+ - *lname*: localized name of the type (do not include domain name)
+ - *roles*: all the roles that can refer to an object of this type
+ - *attrs*: object attributes -- currently only "searchprio" is known,
+ which defines the object's priority in the full-text search index,
+ see :meth:`Domain.get_objects()`.
+ """
+
+ known_attrs = {
+ 'searchprio': 1,
+ }
+
+ def __init__(self, lname, *roles, **attrs):
+ self.lname = lname
+ self.roles = roles
+ self.attrs = self.known_attrs.copy()
+ self.attrs.update(attrs)
+
+
+class Index(object):
+ """
+ An Index is the description for a domain-specific index. To add an index to
+ a domain, subclass Index, overriding the three name attributes:
+
+ * `name` is an identifier used for generating file names.
+ * `localname` is the section title for the index.
+ * `shortname` is a short name for the index, for use in the relation bar in
+ HTML output. Can be empty to disable entries in the relation bar.
+
+ and providing a :meth:`generate()` method. Then, add the index class to
+ your domain's `indices` list. Extensions can add indices to existing
+ domains using :meth:`~sphinx.application.Sphinx.add_index_to_domain()`.
+ """
+
+ name = None
+ localname = None
+ shortname = None
+
+ def __init__(self, domain):
+ if self.name is None or self.localname is None:
+ raise SphinxError('Index subclass %s has no valid name or localname'
+ % self.__class__.__name__)
+ self.domain = domain
+
+ def generate(self, docnames=None):
+ """Return entries for the index given by *name*. If *docnames* is
+ given, restrict to entries referring to these docnames.
+
+ The return value is a tuple of ``(content, collapse)``, where *collapse*
+ is a boolean that determines if sub-entries should start collapsed (for
+ output formats that support collapsing sub-entries).
+
+ *content* is a sequence of ``(letter, entries)`` tuples, where *letter*
+ is the "heading" for the given *entries*, usually the starting letter.
+
+ *entries* is a sequence of single entries, where a single entry is a
+ sequence ``[name, subtype, docname, anchor, extra, qualifier, descr]``.
+ The items in this sequence have the following meaning:
+
+ - `name` -- the name of the index entry to be displayed
+ - `subtype` -- sub-entry related type:
+ 0 -- normal entry
+ 1 -- entry with sub-entries
+ 2 -- sub-entry
+ - `docname` -- docname where the entry is located
+ - `anchor` -- anchor for the entry within `docname`
+ - `extra` -- extra info for the entry
+ - `qualifier` -- qualifier for the description
+ - `descr` -- description for the entry
+
+ Qualifier and description are not rendered e.g. in LaTeX output.
+ """
+ return []
+
+
+class Domain(object):
+ """
+ A Domain is meant to be a group of "object" description directives for
+ objects of a similar nature, and corresponding roles to create references to
+ them. Examples would be Python modules, classes, functions etc., elements
+ of a templating language, Sphinx roles and directives, etc.
+
+ Each domain has a separate storage for information about existing objects
+ and how to reference them in `self.data`, which must be a dictionary. It
+ also must implement several functions that expose the object information in
+ a uniform way to parts of Sphinx that allow the user to reference or search
+ for objects in a domain-agnostic way.
+
+ About `self.data`: since all object and cross-referencing information is
+ stored on a BuildEnvironment instance, the `domain.data` object is also
+ stored in the `env.domaindata` dict under the key `domain.name`. Before the
+ build process starts, every active domain is instantiated and given the
+ environment object; the `domaindata` dict must then either be nonexistent or
+ a dictionary whose 'version' key is equal to the domain class'
+ :attr:`data_version` attribute. Otherwise, `IOError` is raised and the
+ pickled environment is discarded.
+ """
+
+ #: domain name: should be short, but unique
+ name = ''
+ #: domain label: longer, more descriptive (used in messages)
+ label = ''
+ #: type (usually directive) name -> ObjType instance
+ object_types = {}
+ #: directive name -> directive class
+ directives = {}
+ #: role name -> role callable
+ roles = {}
+ #: a list of Index subclasses
+ indices = []
+ #: role name -> a warning message if reference is missing
+ dangling_warnings = {}
+
+ #: data value for a fresh environment
+ initial_data = {}
+ #: data version, bump this when the format of `self.data` changes
+ data_version = 0
+
+ def __init__(self, env):
+ self.env = env
+ if self.name not in env.domaindata:
+ assert isinstance(self.initial_data, dict)
+ new_data = self.initial_data.copy()
+ new_data['version'] = self.data_version
+ self.data = env.domaindata[self.name] = new_data
+ else:
+ self.data = env.domaindata[self.name]
+ if self.data['version'] != self.data_version:
+ raise IOError('data of %r domain out of date' % self.label)
+ self._role_cache = {}
+ self._directive_cache = {}
+ self._role2type = {}
+ for name, obj in self.object_types.iteritems():
+ for rolename in obj.roles:
+ self._role2type.setdefault(rolename, []).append(name)
+ self.objtypes_for_role = self._role2type.get
+
+ def role(self, name):
+ """Return a role adapter function that always gives the registered
+ role its full name ('domain:name') as the first argument.
+ """
+ if name in self._role_cache:
+ return self._role_cache[name]
+ if name not in self.roles:
+ return None
+ fullname = '%s:%s' % (self.name, name)
+ def role_adapter(typ, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ return self.roles[name](fullname, rawtext, text, lineno,
+ inliner, options, content)
+ self._role_cache[name] = role_adapter
+ return role_adapter
+
+ def directive(self, name):
+ """Return a directive adapter class that always gives the registered
+ directive its full name ('domain:name') as ``self.name``.
+ """
+ if name in self._directive_cache:
+ return self._directive_cache[name]
+ if name not in self.directives:
+ return None
+ fullname = '%s:%s' % (self.name, name)
+ BaseDirective = self.directives[name]
+ class DirectiveAdapter(BaseDirective):
+ def run(self):
+ self.name = fullname
+ return BaseDirective.run(self)
+ self._directive_cache[name] = DirectiveAdapter
+ return DirectiveAdapter
+
+ # methods that should be overwritten
+
+ def clear_doc(self, docname):
+ """Remove traces of a document in the domain-specific inventories."""
+ pass
+
+ def process_doc(self, env, docname, document):
+ """Process a document after it is read by the environment."""
+ pass
+
+ def resolve_xref(self, env, fromdocname, builder,
+ typ, target, node, contnode):
+ """Resolve the pending_xref *node* with the given *typ* and *target*.
+
+ This method should return a new node, to replace the xref node,
+ containing the *contnode* which is the markup content of the
+ cross-reference.
+
+ If no resolution can be found, None can be returned; the xref node will
+ then given to the 'missing-reference' event, and if that yields no
+ resolution, replaced by *contnode*.
+
+ The method can also raise :exc:`sphinx.environment.NoUri` to suppress
+ the 'missing-reference' event being emitted.
+ """
+ pass
+
+ def get_objects(self):
+ """Return an iterable of "object descriptions", which are tuples with
+ five items:
+
+ * `name` -- fully qualified name
+ * `dispname` -- name to display when searching/linking
+ * `type` -- object type, a key in ``self.object_types``
+ * `docname` -- the document where it is to be found
+ * `anchor` -- the anchor name for the object
+ * `priority` -- how "important" the object is (determines placement
+ in search results)
+
+ - 1: default priority (placed before full-text matches)
+ - 0: object is important (placed before default-priority objects)
+ - 2: object is unimportant (placed after full-text matches)
+ - -1: object should not show up in search at all
+ """
+ return []
+
+ def get_type_name(self, type, primary=False):
+ """Return full name for given ObjType."""
+ if primary:
+ return type.lname
+ return _('%s %s') % (self.label, type.lname)
+
+
+from sphinx.domains.c import CDomain
+from sphinx.domains.cpp import CPPDomain
+from sphinx.domains.std import StandardDomain
+from sphinx.domains.python import PythonDomain
+from sphinx.domains.javascript import JavaScriptDomain
+from sphinx.domains.rst import ReSTDomain
+
+BUILTIN_DOMAINS = {
+ 'std': StandardDomain,
+ 'py': PythonDomain,
+ 'c': CDomain,
+ 'cpp': CPPDomain,
+ 'js': JavaScriptDomain,
+ 'rst': ReSTDomain,
+}
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
new file mode 100644
index 0000000..fb38cfe
--- /dev/null
+++ b/sphinx/domains/c.py
@@ -0,0 +1,253 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.domains.c
+ ~~~~~~~~~~~~~~~~
+
+ The C language domain.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import string
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.roles import XRefRole
+from sphinx.locale import l_, _
+from sphinx.domains import Domain, ObjType
+from sphinx.directives import ObjectDescription
+from sphinx.util.nodes import make_refnode
+from sphinx.util.docfields import Field, TypedField
+
+
+# RE to split at word boundaries
+wsplit_re = re.compile(r'(\W+)')
+
+# REs for C signatures
+c_sig_re = re.compile(
+ r'''^([^(]*?) # return type
+ ([\w:.]+) \s* # thing name (colon allowed for C++)
+ (?: \((.*)\) )? # optionally arguments
+ (\s+const)? $ # const specifier
+ ''', re.VERBOSE)
+c_funcptr_sig_re = re.compile(
+ r'''^([^(]+?) # return type
+ (\( [^()]+ \)) \s* # name in parentheses
+ \( (.*) \) # arguments
+ (\s+const)? $ # const specifier
+ ''', re.VERBOSE)
+c_funcptr_name_re = re.compile(r'^\(\s*\*\s*(.*?)\s*\)$')
+
+
+class CObject(ObjectDescription):
+ """
+ Description of a C language object.
+ """
+
+ doc_field_types = [
+ TypedField('parameter', label=l_('Parameters'),
+ names=('param', 'parameter', 'arg', 'argument'),
+ typerolename='type', typenames=('type',)),
+ Field('returnvalue', label=l_('Returns'), has_arg=False,
+ names=('returns', 'return')),
+ Field('returntype', label=l_('Return type'), has_arg=False,
+ names=('rtype',)),
+ ]
+
+ # These C types aren't described anywhere, so don't try to create
+ # a cross-reference to them
+ stopwords = set((
+ 'const', 'void', 'char', 'wchar_t', 'int', 'short',
+ 'long', 'float', 'double', 'unsigned', 'signed', 'FILE',
+ 'clock_t', 'time_t', 'ptrdiff_t', 'size_t', 'ssize_t',
+ 'struct', '_Bool',
+ ))
+
+ def _parse_type(self, node, ctype):
+ # add cross-ref nodes for all words
+ for part in filter(None, wsplit_re.split(ctype)):
+ tnode = nodes.Text(part, part)
+ if part[0] in string.ascii_letters+'_' and \
+ part not in self.stopwords:
+ pnode = addnodes.pending_xref(
+ '', refdomain='c', reftype='type', reftarget=part,
+ modname=None, classname=None)
+ pnode += tnode
+ node += pnode
+ else:
+ node += tnode
+
+ def handle_signature(self, sig, signode):
+ """Transform a C signature into RST nodes."""
+ # first try the function pointer signature regex, it's more specific
+ m = c_funcptr_sig_re.match(sig)
+ if m is None:
+ m = c_sig_re.match(sig)
+ if m is None:
+ raise ValueError('no match')
+ rettype, name, arglist, const = m.groups()
+
+ signode += addnodes.desc_type('', '')
+ self._parse_type(signode[-1], rettype)
+ try:
+ classname, funcname = name.split('::', 1)
+ classname += '::'
+ signode += addnodes.desc_addname(classname, classname)
+ signode += addnodes.desc_name(funcname, funcname)
+ # name (the full name) is still both parts
+ except ValueError:
+ signode += addnodes.desc_name(name, name)
+ # clean up parentheses from canonical name
+ m = c_funcptr_name_re.match(name)
+ if m:
+ name = m.group(1)
+
+ typename = self.env.temp_data.get('c:type')
+ if self.name == 'c:member' and typename:
+ fullname = typename + '.' + name
+ else:
+ fullname = name
+
+ if not arglist:
+ if self.objtype == 'function':
+ # for functions, add an empty parameter list
+ signode += addnodes.desc_parameterlist()
+ if const:
+ signode += addnodes.desc_addname(const, const)
+ return fullname
+
+ paramlist = addnodes.desc_parameterlist()
+ arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
+ # this messes up function pointer types, but not too badly ;)
+ args = arglist.split(',')
+ for arg in args:
+ arg = arg.strip()
+ param = addnodes.desc_parameter('', '', noemph=True)
+ try:
+ ctype, argname = arg.rsplit(' ', 1)
+ except ValueError:
+ # no argument name given, only the type
+ self._parse_type(param, arg)
+ else:
+ self._parse_type(param, ctype)
+ # separate by non-breaking space in the output
+ param += nodes.emphasis(' '+argname, u'\xa0'+argname)
+ paramlist += param
+ signode += paramlist
+ if const:
+ signode += addnodes.desc_addname(const, const)
+ return fullname
+
+ def get_index_text(self, name):
+ if self.objtype == 'function':
+ return _('%s (C function)') % name
+ elif self.objtype == 'member':
+ return _('%s (C member)') % name
+ elif self.objtype == 'macro':
+ return _('%s (C macro)') % name
+ elif self.objtype == 'type':
+ return _('%s (C type)') % name
+ elif self.objtype == 'var':
+ return _('%s (C variable)') % name
+ else:
+ return ''
+
+ def add_target_and_index(self, name, sig, signode):
+ # for C API items we add a prefix since names are usually not qualified
+ # by a module name and so easily clash with e.g. section titles
+ targetname = 'c.' + name
+ if targetname not in self.state.document.ids:
+ signode['names'].append(targetname)
+ signode['ids'].append(targetname)
+ signode['first'] = (not self.names)
+ self.state.document.note_explicit_target(signode)
+ inv = self.env.domaindata['c']['objects']
+ if name in inv:
+ self.state_machine.reporter.warning(
+ 'duplicate C object description of %s, ' % name +
+ 'other instance in ' + self.env.doc2path(inv[name][0]),
+ line=self.lineno)
+ inv[name] = (self.env.docname, self.objtype)
+
+ indextext = self.get_index_text(name)
+ if indextext:
+ self.indexnode['entries'].append(('single', indextext,
+ targetname, ''))
+
+ def before_content(self):
+ self.typename_set = False
+ if self.name == 'c:type':
+ if self.names:
+ self.env.temp_data['c:type'] = self.names[0]
+ self.typename_set = True
+
+ def after_content(self):
+ if self.typename_set:
+ self.env.temp_data['c:type'] = None
+
+
+class CXRefRole(XRefRole):
+ def process_link(self, env, refnode, has_explicit_title, title, target):
+ if not has_explicit_title:
+ target = target.lstrip('~') # only has a meaning for the title
+ # if the first character is a tilde, don't display the module/class
+ # parts of the contents
+ if title[0:1] == '~':
+ title = title[1:]
+ dot = title.rfind('.')
+ if dot != -1:
+ title = title[dot+1:]
+ return title, target
+
+
+class CDomain(Domain):
+ """C language domain."""
+ name = 'c'
+ label = 'C'
+ object_types = {
+ 'function': ObjType(l_('function'), 'func'),
+ 'member': ObjType(l_('member'), 'member'),
+ 'macro': ObjType(l_('macro'), 'macro'),
+ 'type': ObjType(l_('type'), 'type'),
+ 'var': ObjType(l_('variable'), 'data'),
+ }
+
+ directives = {
+ 'function': CObject,
+ 'member': CObject,
+ 'macro': CObject,
+ 'type': CObject,
+ 'var': CObject,
+ }
+ roles = {
+ 'func' : CXRefRole(fix_parens=True),
+ 'member': CXRefRole(),
+ 'macro': CXRefRole(),
+ 'data': CXRefRole(),
+ 'type': CXRefRole(),
+ }
+ initial_data = {
+ 'objects': {}, # fullname -> docname, objtype
+ }
+
+ def clear_doc(self, docname):
+ for fullname, (fn, _) in self.data['objects'].items():
+ if fn == docname:
+ del self.data['objects'][fullname]
+
+ def resolve_xref(self, env, fromdocname, builder,
+ typ, target, node, contnode):
+ # strip pointer asterisk
+ target = target.rstrip(' *')
+ if target not in self.data['objects']:
+ return None
+ obj = self.data['objects'][target]
+ return make_refnode(builder, fromdocname, obj[0], 'c.' + target,
+ contnode, target)
+
+ def get_objects(self):
+ for refname, (docname, type) in self.data['objects'].iteritems():
+ yield (refname, refname, type, docname, 'c.' + refname, 1)
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
new file mode 100644
index 0000000..cb64a60
--- /dev/null
+++ b/sphinx/domains/cpp.py
@@ -0,0 +1,1317 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.domains.cpp
+ ~~~~~~~~~~~~~~~~~~
+
+ The C++ language domain.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+from copy import deepcopy
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.roles import XRefRole
+from sphinx.locale import l_, _
+from sphinx.domains import Domain, ObjType
+from sphinx.directives import ObjectDescription
+from sphinx.util.nodes import make_refnode
+from sphinx.util.compat import Directive
+from sphinx.util.docfields import Field, GroupedField
+
+
+_identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*)\b')
+_whitespace_re = re.compile(r'\s+(?u)')
+_string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
+ r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
+_visibility_re = re.compile(r'\b(public|private|protected)\b')
+_array_def_re = re.compile(r'\[\s*([^\]]+?)?\s*\]')
+_template_arg_re = re.compile(r'(%s)|([^,>]+)' % _string_re.pattern, re.S)
+_operator_re = re.compile(r'''(?x)
+ \[\s*\]
+ | \(\s*\)
+ | \+\+ | --
+ | ->\*? | \,
+ | (<<|>>)=? | && | \|\|
+ | [!<>=/*%+|&^~-]=?
+''')
+
+_id_shortwords = {
+ 'char': 'c',
+ 'signed char': 'c',
+ 'unsigned char': 'C',
+ 'int': 'i',
+ 'signed int': 'i',
+ 'unsigned int': 'U',
+ 'long': 'l',
+ 'signed long': 'l',
+ 'unsigned long': 'L',
+ 'bool': 'b',
+ 'size_t': 's',
+ 'std::string': 'ss',
+ 'std::ostream': 'os',
+ 'std::istream': 'is',
+ 'std::iostream': 'ios',
+ 'std::vector': 'v',
+ 'std::map': 'm',
+ 'operator[]': 'subscript-operator',
+ 'operator()': 'call-operator',
+ 'operator!': 'not-operator',
+ 'operator<': 'lt-operator',
+ 'operator<=': 'lte-operator',
+ 'operator>': 'gt-operator',
+ 'operator>=': 'gte-operator',
+ 'operator=': 'assign-operator',
+ 'operator/': 'div-operator',
+ 'operator*': 'mul-operator',
+ 'operator%': 'mod-operator',
+ 'operator+': 'add-operator',
+ 'operator-': 'sub-operator',
+ 'operator|': 'or-operator',
+ 'operator&': 'and-operator',
+ 'operator^': 'xor-operator',
+ 'operator&&': 'sand-operator',
+ 'operator||': 'sor-operator',
+ 'operator==': 'eq-operator',
+ 'operator!=': 'neq-operator',
+ 'operator<<': 'lshift-operator',
+ 'operator>>': 'rshift-operator',
+ 'operator-=': 'sub-assign-operator',
+ 'operator+=': 'add-assign-operator',
+ 'operator*-': 'mul-assign-operator',
+ 'operator/=': 'div-assign-operator',
+ 'operator%=': 'mod-assign-operator',
+ 'operator&=': 'and-assign-operator',
+ 'operator|=': 'or-assign-operator',
+ 'operator<<=': 'lshift-assign-operator',
+ 'operator>>=': 'rshift-assign-operator',
+ 'operator^=': 'xor-assign-operator',
+ 'operator,': 'comma-operator',
+ 'operator->': 'pointer-operator',
+ 'operator->*': 'pointer-by-pointer-operator',
+ 'operator~': 'inv-operator',
+ 'operator++': 'inc-operator',
+ 'operator--': 'dec-operator',
+ 'operator new': 'new-operator',
+ 'operator new[]': 'new-array-operator',
+ 'operator delete': 'delete-operator',
+ 'operator delete[]': 'delete-array-operator'
+}
+
+
+class DefinitionError(Exception):
+
+ def __init__(self, description):
+ self.description = description
+
+ def __str__(self):
+ return unicode(self).encode('utf-8')
+
+ def __unicode__(self):
+ return self.description
+
+
+class DefExpr(object):
+
+ def __eq__(self, other):
+ if type(self) is not type(other):
+ return False
+ try:
+ for key, value in self.__dict__.iteritems():
+ if value != getattr(other, key):
+ return False
+ except AttributeError:
+ return False
+ return True
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ __hash__ = None
+
+ def clone(self):
+ """Clone a definition expression node."""
+ return deepcopy(self)
+
+ def get_id(self):
+ """Return the id for the node."""
+ return u''
+
+ def get_name(self):
+ """Return the name.
+
+ Returns either `None` or a node with a name you might call
+ :meth:`split_owner` on.
+ """
+ return None
+
+ def split_owner(self):
+ """Nodes returned by :meth:`get_name` can split off their
+ owning parent. This function returns the owner and the
+ name as a tuple of two items. If a node does not support
+ it, it returns None as owner and self as name.
+ """
+ return None, self
+
+ def prefix(self, prefix):
+ """Prefix a name node (a node returned by :meth:`get_name`)."""
+ raise NotImplementedError()
+
+ def __str__(self):
+ return unicode(self).encode('utf-8')
+
+ def __unicode__(self):
+ raise NotImplementedError()
+
+ def __repr__(self):
+ return '<%s %s>' % (self.__class__.__name__, self)
+
+
+class PrimaryDefExpr(DefExpr):
+
+ def get_name(self):
+ return self
+
+ def prefix(self, prefix):
+ if isinstance(prefix, PathDefExpr):
+ prefix = prefix.clone()
+ prefix.path.append(self)
+ return prefix
+ return PathDefExpr([prefix, self])
+
+
+class NameDefExpr(PrimaryDefExpr):
+
+ def __init__(self, name):
+ self.name = name
+
+ def get_id(self):
+ name = _id_shortwords.get(self.name)
+ if name is not None:
+ return name
+ return self.name.replace(u' ', u'-')
+
+ def __unicode__(self):
+ return unicode(self.name)
+
+
+class PathDefExpr(PrimaryDefExpr):
+
+ def __init__(self, parts):
+ self.path = parts
+
+ def get_id(self):
+ rv = u'::'.join(x.get_id() for x in self.path)
+ return _id_shortwords.get(rv, rv)
+
+ def split_owner(self):
+ if len(self.path) > 1:
+ return PathDefExpr(self.path[:-1]), self.path[-1]
+ return None, self
+
+ def prefix(self, prefix):
+ if isinstance(prefix, PathDefExpr):
+ prefix = prefix.clone()
+ prefix.path.extend(self.path)
+ return prefix
+ return PathDefExpr([prefix] + self.path)
+
+ def __unicode__(self):
+ return u'::'.join(map(unicode, self.path))
+
+
+class ArrayTypeSuffixDefExpr(object):
+
+ def __init__(self, size_hint=None):
+ self.size_hint = size_hint
+
+ def get_id_suffix(self):
+ return 'A'
+
+ def __unicode__(self):
+ return u'[%s]' % (
+ self.size_hint is not None and unicode(self.size_hint) or u'',
+ )
+
+
+class TemplateDefExpr(PrimaryDefExpr):
+
+ def __init__(self, typename, args):
+ self.typename = typename
+ self.args = args
+
+ def split_owner(self):
+ owner, typename = self.typename.split_owner()
+ return owner, TemplateDefExpr(typename, self.args)
+
+ def get_id(self):
+ return u'%s:%s:' % (self.typename.get_id(),
+ u'.'.join(x.get_id() for x in self.args))
+
+ def __unicode__(self):
+ return u'%s<%s>' % (self.typename, u', '.join(map(unicode, self.args)))
+
+
+class ConstantTemplateArgExpr(PrimaryDefExpr):
+
+ def __init__(self, arg):
+ self.arg = arg
+
+ def get_id(self):
+ return self.arg.replace(u' ', u'-')
+
+ def __unicode__(self):
+ return unicode(self.arg)
+
+
+class WrappingDefExpr(DefExpr):
+
+ def __init__(self, typename):
+ self.typename = typename
+
+ def get_name(self):
+ return self.typename.get_name()
+
+
+class ModifierDefExpr(WrappingDefExpr):
+
+ def __init__(self, typename, modifiers):
+ WrappingDefExpr.__init__(self, typename)
+ self.modifiers = modifiers
+
+ def get_id(self):
+ pieces = [_id_shortwords.get(unicode(x), unicode(x))
+ for x in self.modifiers]
+ pieces.append(self.typename.get_id())
+ return u'-'.join(pieces)
+
+ def __unicode__(self):
+ return u' '.join(map(unicode, list(self.modifiers) + [self.typename]))
+
+
+class PtrDefExpr(WrappingDefExpr):
+
+ def get_id(self):
+ return self.typename.get_id() + u'P'
+
+ def __unicode__(self):
+ return u'%s*' % self.typename
+
+
+class LValRefDefExpr(WrappingDefExpr):
+
+ def get_id(self):
+ return self.typename.get_id() + u'R'
+
+ def __unicode__(self):
+ return u'%s&' % self.typename
+
+
+class RValRefDefExpr(WrappingDefExpr):
+
+ def get_id(self):
+ return self.typename.get_id() + u'RR'
+
+ def __unicode__(self):
+ return u'%s&&' % self.typename
+
+
+class ConstDefExpr(WrappingDefExpr):
+
+ def __init__(self, typename, prefix=False):
+ WrappingDefExpr.__init__(self, typename)
+ self.prefix = prefix
+
+ def get_id(self):
+ return self.typename.get_id() + u'C'
+
+ def __unicode__(self):
+ return (self.prefix and u'const %s' or u'%s const') % self.typename
+
+
+class CastOpDefExpr(PrimaryDefExpr):
+
+ def __init__(self, typename):
+ self.typename = typename
+
+ def get_id(self):
+ return u'castto-%s-operator' % self.typename.get_id()
+
+ def __unicode__(self):
+ return u'operator %s' % self.typename
+
+
+class ArgumentDefExpr(DefExpr):
+
+ def __init__(self, type, name, type_suffixes, default=None):
+ self.name = name
+ self.type = type
+ self.type_suffixes = type_suffixes
+ self.default = default
+
+ def get_name(self):
+ return self.name.get_name()
+
+ def get_id(self):
+ buf = []
+ buf.append(self.type and self.type.get_id() or 'X')
+ for suffix in self.type_suffixes:
+ buf.append(suffix.get_id_suffix())
+ return u''.join(buf)
+
+ def __unicode__(self):
+ buf = [(u'%s %s' % (self.type or u'', self.name or u'')).strip()]
+ if self.default is not None:
+ buf.append('=%s' % self.default)
+ for suffix in self.type_suffixes:
+ buf.append(unicode(suffix))
+ return u''.join(buf)
+
+
+class NamedDefExpr(DefExpr):
+
+ def __init__(self, name, visibility, static):
+ self.name = name
+ self.visibility = visibility
+ self.static = static
+
+ def get_name(self):
+ return self.name.get_name()
+
+ def get_modifiers(self, visibility='public'):
+ rv = []
+ if self.visibility != visibility:
+ rv.append(self.visibility)
+ if self.static:
+ rv.append(u'static')
+ return rv
+
+
+class TypeObjDefExpr(NamedDefExpr):
+
+ def __init__(self, name, visibility, static, typename, type_suffixes):
+ NamedDefExpr.__init__(self, name, visibility, static)
+ self.typename = typename
+ self.type_suffixes = type_suffixes
+
+ def get_id(self):
+ if self.typename is None:
+ buf = [self.name.get_id()]
+ else:
+ buf = [u'%s__%s' % (self.name.get_id(), self.typename.get_id())]
+ for suffix in self.type_suffixes:
+ buf.append(suffix.get_id_suffix())
+ return u''.join(buf)
+
+ def __unicode__(self):
+ buf = self.get_modifiers()
+ if self.typename is None:
+ buf.append(unicode(self.name))
+ else:
+ buf.extend(map(unicode, (self.typename, self.name)))
+ buf = [u' '.join(buf)]
+ for suffix in self.type_suffixes:
+ buf.append(unicode(suffix))
+ return u''.join(buf)
+
+
+class MemberObjDefExpr(NamedDefExpr):
+
+ def __init__(self, name, visibility, static, typename, type_suffixes,
+ value):
+ NamedDefExpr.__init__(self, name, visibility, static)
+ self.typename = typename
+ self.type_suffixes = type_suffixes
+ self.value = value
+
+ def get_id(self):
+ buf = [u'%s__%s' % (self.name.get_id(), self.typename.get_id())]
+ for suffix in self.type_suffixes:
+ buf.append(suffix.get_id_suffix())
+ return u''.join(buf)
+
+ def __unicode__(self):
+ buf = self.get_modifiers()
+ buf.extend((unicode(self.typename), unicode(self.name)))
+ buf = [u' '.join(buf)]
+ for suffix in self.type_suffixes:
+ buf.append(unicode(suffix))
+ if self.value is not None:
+ buf.append(u' = %s' % self.value)
+ return u''.join(buf)
+
+
+class FuncDefExpr(NamedDefExpr):
+
+ def __init__(self, name, visibility, static, explicit, constexpr, rv,
+ signature, **kwargs):
+ NamedDefExpr.__init__(self, name, visibility, static)
+ self.rv = rv
+ self.signature = signature
+ self.explicit = explicit
+ self.constexpr = constexpr
+ self.const = kwargs.get('const', False)
+ self.volatile = kwargs.get('volatile', False)
+ self.noexcept = kwargs.get('noexcept', False)
+ self.override = kwargs.get('override', False)
+ self.rvalue_this = kwargs.get('rvalue_this', False)
+ self.lvalue_this = kwargs.get('lvalue_this', False)
+ self.pure_virtual = kwargs.get('pure_virtual', False)
+ self.delete = kwargs.get('delete', False)
+ self.default = kwargs.get('default', False)
+
+ def get_id(self):
+ return u'%s%s%s%s' % (
+ self.name.get_id(),
+ self.signature and u'__' +
+ u'.'.join(x.get_id() for x in self.signature) or u'',
+ self.const and u'C' or u'',
+ self.constexpr and 'CE' or ''
+ )
+
+ def __unicode__(self):
+ buf = self.get_modifiers()
+ if self.explicit:
+ buf.append(u'explicit')
+ if self.constexpr:
+ buf.append(u'constexpr')
+ if self.rv is not None:
+ buf.append(unicode(self.rv))
+ buf.append(u'%s(%s)' % (self.name, u', '.join(
+ map(unicode, self.signature))))
+ if self.const:
+ buf.append(u'const')
+ if self.volatile:
+ buf.append(u'volatile')
+ if self.rvalue_this:
+ buf.append(u'&&')
+ if self.lvalue_this:
+ buf.append(u'&')
+ if self.noexcept:
+ buf.append(u'noexcept')
+ if self.override:
+ buf.append(u'override')
+ if self.pure_virtual:
+ buf.append(u'= 0')
+ if self.default:
+ buf.append(u'= default')
+ if self.delete:
+ buf.append(u'= delete')
+ return u' '.join(buf)
+
+
+class ClassDefExpr(NamedDefExpr):
+
+ def __init__(self, name, visibility, static, bases):
+ NamedDefExpr.__init__(self, name, visibility, static)
+ self.bases = bases
+
+ def get_id(self):
+ return self.name.get_id()
+
+ def _tostring(self, visibility='public'):
+ buf = self.get_modifiers(visibility)
+ buf.append(unicode(self.name))
+ if self.bases:
+ buf.append(u':')
+ buf.append(u', '.join(base._tostring('private')
+ for base in self.bases))
+ return u' '.join(buf)
+
+ def __unicode__(self):
+ return self._tostring('public')
+
+class DefinitionParser(object):
+
+ # mapping of valid type modifiers. if the set is None it means
+ # the modifier can prefix all types, otherwise only the types
+ # (actually more keywords) in the set. Also check
+ # _guess_typename when changing this.
+ _modifiers = {
+ 'volatile': None,
+ 'register': None,
+ 'mutable': None,
+ 'const': None,
+ 'typename': None,
+ 'struct': None,
+ 'unsigned': set(('char', 'short', 'int', 'long')),
+ 'signed': set(('char', 'short', 'int', 'long')),
+ 'short': set(('int',)),
+ 'long': set(('int', 'long', 'double'))
+ }
+
+ def __init__(self, definition):
+ self.definition = definition.strip()
+ self.pos = 0
+ self.end = len(self.definition)
+ self.last_match = None
+ self._previous_state = (0, None)
+
+ def fail(self, msg):
+ raise DefinitionError('Invalid definition: %s [error at %d]\n %s' %
+ (msg, self.pos, self.definition))
+
+ def match(self, regex):
+ match = regex.match(self.definition, self.pos)
+ if match is not None:
+ self._previous_state = (self.pos, self.last_match)
+ self.pos = match.end()
+ self.last_match = match
+ return True
+ return False
+
+ def backout(self):
+ self.pos, self.last_match = self._previous_state
+
+ def skip_string(self, string):
+ strlen = len(string)
+ if self.definition[self.pos:self.pos + strlen] == string:
+ self.pos += strlen
+ return True
+ return False
+
+ def skip_word(self, word):
+ return self.match(re.compile(r'\b%s\b' % re.escape(word)))
+
+ def skip_ws(self):
+ return self.match(_whitespace_re)
+
+ def skip_word_and_ws(self, word):
+ if self.skip_word(word):
+ self.skip_ws()
+ return True
+ return False
+
+ @property
+ def eof(self):
+ return self.pos >= self.end
+
+ @property
+ def current_char(self):
+ try:
+ return self.definition[self.pos]
+ except IndexError:
+ return 'EOF'
+
+ @property
+ def matched_text(self):
+ if self.last_match is not None:
+ return self.last_match.group()
+
+ def _parse_operator(self):
+ self.skip_ws()
+ # thank god, a regular operator definition
+ if self.match(_operator_re):
+ return NameDefExpr('operator' +
+ _whitespace_re.sub('', self.matched_text))
+
+ # new/delete operator?
+ for allocop in 'new', 'delete':
+ if not self.skip_word(allocop):
+ continue
+ self.skip_ws()
+ if self.skip_string('['):
+ self.skip_ws()
+ if not self.skip_string(']'):
+ self.fail('expected "]" for ' + allocop)
+ allocop += '[]'
+ return NameDefExpr('operator ' + allocop)
+
+ # oh well, looks like a cast operator definition.
+ # In that case, eat another type.
+ type = self._parse_type()
+ return CastOpDefExpr(type)
+
+ def _parse_name(self):
+ return self._parse_name_or_template_arg(False)
+
+ def _parse_name_or_template_arg(self, in_template):
+ if not self.match(_identifier_re):
+ if not in_template:
+ self.fail('expected name')
+ if not self.match(_template_arg_re):
+ self.fail('expected name or constant template argument')
+ return ConstantTemplateArgExpr(self.matched_text.strip())
+ identifier = self.matched_text
+
+ # strictly speaking, operators are not regular identifiers
+ # but because operator is a keyword, it might not be used
+ # for variable names anyways, so we can safely parse the
+ # operator here as identifier
+ if identifier == 'operator':
+ return self._parse_operator()
+
+ return NameDefExpr(identifier)
+
+ def _guess_typename(self, path):
+ if not path:
+ return [], 'int'
+ # for the long type, we don't want the int in there
+ if 'long' in path:
+ path = [x for x in path if x != 'int']
+ # remove one long
+ path.remove('long')
+ return path, 'long'
+ if path[-1] in ('int', 'char'):
+ return path[:-1], path[-1]
+ return path, 'int'
+
+ def _attach_crefptr(self, expr, is_const=False):
+ if is_const:
+ expr = ConstDefExpr(expr, prefix=True)
+ while 1:
+ self.skip_ws()
+ if self.skip_word('const'):
+ expr = ConstDefExpr(expr)
+ elif self.skip_string('*'):
+ expr = PtrDefExpr(expr)
+ elif self.skip_string('&'):
+ if self.skip_string('&'):
+ expr = RValRefDefExpr(expr)
+ else:
+ expr = LValRefDefExpr(expr)
+ else:
+ return expr
+
+ def _try_parse_type_suffixes(self):
+ rv = []
+ while self.match(_array_def_re):
+ rv.append(ArrayTypeSuffixDefExpr(self.last_match.group(1)))
+ self.skip_ws()
+ return rv
+
+ def _peek_const(self, path):
+ try:
+ path.remove('const')
+ return True
+ except ValueError:
+ return False
+
+ def _parse_builtin(self, modifiers):
+ modifier = modifiers[-1]
+ path = modifiers
+ following = self._modifiers[modifier]
+ while 1:
+ self.skip_ws()
+ if not self.match(_identifier_re):
+ break
+ identifier = self.matched_text
+ if identifier in following:
+ path.append(identifier)
+ following = self._modifiers[modifier]
+ assert following
+ else:
+ self.backout()
+ break
+
+ is_const = self._peek_const(path)
+ modifiers, typename = self._guess_typename(path)
+ rv = ModifierDefExpr(NameDefExpr(typename), modifiers)
+ return self._attach_crefptr(rv, is_const)
+
+ def _parse_type_expr(self, in_template=False):
+ typename = self._parse_name_or_template_arg(in_template)
+ self.skip_ws()
+ if not self.skip_string('<'):
+ return typename
+
+ args = []
+ while 1:
+ self.skip_ws()
+ if self.skip_string('>'):
+ break
+ if args:
+ if not self.skip_string(','):
+ self.fail('"," or ">" in template expected')
+ self.skip_ws()
+ args.append(self._parse_type(True))
+ return TemplateDefExpr(typename, args)
+
+ def _parse_type(self, in_template=False):
+ self.skip_ws()
+ result = []
+ modifiers = []
+
+ # if there is a leading :: or not, we don't care because we
+ # treat them exactly the same. Buf *if* there is one, we
+ # don't have to check for type modifiers
+ if not self.skip_string('::'):
+ self.skip_ws()
+ while self.match(_identifier_re):
+ modifier = self.matched_text
+ if modifier in self._modifiers:
+ following = self._modifiers[modifier]
+ # if the set is not none, there is a limited set
+ # of types that might follow. It is technically
+ # impossible for a template to follow, so what
+ # we do is go to a different function that just
+ # eats types
+ modifiers.append(modifier)
+ if following is not None:
+ return self._parse_builtin(modifiers)
+ self.skip_ws()
+ else:
+ self.backout()
+ break
+
+ while 1:
+ self.skip_ws()
+ if (in_template and self.current_char in ',>') or \
+ (result and not self.skip_string('::')) or \
+ self.eof:
+ break
+ result.append(self._parse_type_expr(in_template))
+
+ if not result:
+ self.fail('expected type')
+ if len(result) == 1:
+ rv = result[0]
+ else:
+ rv = PathDefExpr(result)
+ is_const = self._peek_const(modifiers)
+ if modifiers:
+ rv = ModifierDefExpr(rv, modifiers)
+ return self._attach_crefptr(rv, is_const)
+
+ def _parse_default_expr(self):
+ self.skip_ws()
+ if self.match(_string_re):
+ return self.matched_text
+ paren_stack_depth = 0
+ max_pos = len(self.definition)
+ rv_start = self.pos
+ while 1:
+ idx0 = self.definition.find('(', self.pos)
+ idx1 = self.definition.find(',', self.pos)
+ idx2 = self.definition.find(')', self.pos)
+ if idx0 < 0:
+ idx0 = max_pos
+ if idx1 < 0:
+ idx1 = max_pos
+ if idx2 < 0:
+ idx2 = max_pos
+ idx = min(idx0, idx1, idx2)
+ if idx >= max_pos:
+ self.fail('unexpected end in default expression')
+ if idx == idx0:
+ paren_stack_depth += 1
+ elif idx == idx2:
+ paren_stack_depth -= 1
+ if paren_stack_depth < 0:
+ break
+ elif paren_stack_depth == 0:
+ break
+ self.pos = idx+1
+
+ rv = self.definition[rv_start:idx]
+ self.pos = idx
+ return rv
+
+ def _parse_signature(self):
+ self.skip_ws()
+ if not self.skip_string('('):
+ self.fail('expected parentheses for function')
+
+ args = []
+ while 1:
+ self.skip_ws()
+ if self.eof:
+ self.fail('missing closing parentheses')
+ if self.skip_string(')'):
+ break
+ if args:
+ if not self.skip_string(','):
+ self.fail('expected comma between arguments')
+ self.skip_ws()
+
+ if self.skip_string('...'):
+ args.append(ArgumentDefExpr(None, '...', [], None))
+ if self.skip_string(')'):
+ break
+ else:
+ self.fail('expected closing parenthesis after ellipses')
+
+ argname = default = None
+ argtype = self._parse_type()
+ self.skip_ws()
+ type_suffixes = self._try_parse_type_suffixes()
+ if self.skip_string('='):
+ default = self._parse_default_expr()
+ elif self.current_char not in ',)':
+ argname = self._parse_name()
+ self.skip_ws()
+ type_suffixes.extend(self._try_parse_type_suffixes())
+ if self.skip_string('='):
+ default = self._parse_default_expr()
+ if argname is None:
+ argname = argtype
+ argtype = None
+
+ args.append(ArgumentDefExpr(argtype, argname,
+ type_suffixes, default))
+ self.skip_ws()
+ attributes = dict(
+ signature=args,
+ const=self.skip_word_and_ws('const'),
+ volatile=self.skip_word_and_ws('volatile'),
+ noexcept=self.skip_word_and_ws('noexcept'),
+ override=self.skip_word_and_ws('override'),
+ pure_virtual=False,
+ lvalue_this=False,
+ rvalue_this=False,
+ delete=False,
+ default=False)
+
+ if self.skip_string('&&'):
+ attributes['rvalue_this'] = True
+ if self.skip_string('&'):
+ attributes['lvalue_this'] = True
+
+ if attributes['lvalue_this'] and attributes['rvalue_this']:
+ self.fail('rvalue reference for *this specifier must be one of'
+ '"&&" or "&"')
+
+ if self.skip_string('='):
+ self.skip_ws()
+ if self.skip_string('0'):
+ attributes['pure_virtual'] = True
+ return attributes
+ if self.skip_word('NULL') or self.skip_word('nullptr'):
+ attributes['pure_virtual'] = True
+ return attributes
+ if self.skip_word('delete'):
+ attributes['delete'] = True
+ return attributes
+ if self.skip_word('default'):
+ attributes['default'] = True
+ return attributes
+
+ self.fail('functions must be defined with '
+ 'either 0, NULL, nullptr, default or delete, other'
+ 'macros are not allowed')
+ return attributes
+
+ def _parse_visibility_static(self):
+ visibility = 'public'
+ if self.match(_visibility_re):
+ visibility = self.matched_text
+ static = self.skip_word_and_ws('static')
+ return visibility, static
+
+ def parse_type(self):
+ return self._parse_type()
+
+ def parse_type_object(self):
+ visibility, static = self._parse_visibility_static()
+ typename = self._parse_type()
+ self.skip_ws()
+ if not self.eof:
+ name = self._parse_type()
+ type_suffixes = self._try_parse_type_suffixes()
+ else:
+ name = typename
+ typename = None
+ type_suffixes = []
+ return TypeObjDefExpr(name, visibility, static, typename, type_suffixes)
+
+ def parse_member_object(self):
+ visibility, static = self._parse_visibility_static()
+ typename = self._parse_type()
+ name = self._parse_type()
+ type_suffixes = self._try_parse_type_suffixes()
+ self.skip_ws()
+ if self.skip_string('='):
+ value = self.read_rest().strip()
+ else:
+ value = None
+ return MemberObjDefExpr(name, visibility, static, typename,
+ type_suffixes, value)
+
+ def parse_function(self):
+ visibility, static = self._parse_visibility_static()
+ explicit = self.skip_word_and_ws('explicit')
+ constexpr = self.skip_word_and_ws('constexpr')
+
+ rv = self._parse_type()
+ self.skip_ws()
+ # some things just don't have return values
+ if self.current_char == '(':
+ name = rv
+ rv = None
+ else:
+ name = self._parse_type()
+ return FuncDefExpr(name, visibility, static, explicit, constexpr, rv,
+ **self._parse_signature())
+
+ def parse_class(self):
+ visibility, static = self._parse_visibility_static()
+ name = self._parse_type()
+ bases = []
+ if self.skip_string(':'):
+ self.skip_ws()
+ while 1:
+ access = 'private'
+ if self.match(_visibility_re):
+ access = self.matched_text
+ base = self._parse_type()
+ bases.append(ClassDefExpr(base, access, False, []))
+ if self.skip_string(','):
+ self.skip_ws()
+ else:
+ break
+ return ClassDefExpr(name, visibility, static, bases)
+
+ def read_rest(self):
+ rv = self.definition[self.pos:]
+ self.pos = self.end
+ return rv
+
+ def assert_end(self):
+ self.skip_ws()
+ if not self.eof:
+ self.fail('expected end of definition, got %r' %
+ self.definition[self.pos:])
+
+
+class CPPObject(ObjectDescription):
+ """Description of a C++ language object."""
+
+ doc_field_types = [
+ GroupedField('parameter', label=l_('Parameters'),
+ names=('param', 'parameter', 'arg', 'argument'),
+ can_collapse=True),
+ GroupedField('exceptions', label=l_('Throws'), rolename='cpp:class',
+ names=('throws', 'throw', 'exception'),
+ can_collapse=True),
+ Field('returnvalue', label=l_('Returns'), has_arg=False,
+ names=('returns', 'return')),
+ ]
+
+ def attach_name(self, node, name):
+ owner, name = name.split_owner()
+ varname = unicode(name)
+ if owner is not None:
+ owner = unicode(owner) + '::'
+ node += addnodes.desc_addname(owner, owner)
+ node += addnodes.desc_name(varname, varname)
+
+ def attach_type_suffixes(self, node, suffixes):
+ for suffix in suffixes:
+ node += nodes.Text(unicode(suffix))
+
+ def attach_type(self, node, type):
+ # XXX: link to c?
+ text = unicode(type)
+ pnode = addnodes.pending_xref(
+ '', refdomain='cpp', reftype='type',
+ reftarget=text, modname=None, classname=None)
+ pnode['cpp:parent'] = self.env.temp_data.get('cpp:parent')
+ pnode += nodes.Text(text)
+ node += pnode
+
+ def attach_modifiers(self, node, obj, visibility='public'):
+ if obj.visibility != visibility:
+ node += addnodes.desc_annotation(obj.visibility,
+ obj.visibility)
+ node += nodes.Text(' ')
+ if obj.static:
+ node += addnodes.desc_annotation('static', 'static')
+ node += nodes.Text(' ')
+ if getattr(obj, 'constexpr', False):
+ node += addnodes.desc_annotation('constexpr', 'constexpr')
+ node += nodes.Text(' ')
+
+ def add_target_and_index(self, sigobj, sig, signode):
+ theid = sigobj.get_id()
+ name = unicode(sigobj.name)
+ if theid not in self.state.document.ids:
+ signode['names'].append(theid)
+ signode['ids'].append(theid)
+ signode['first'] = (not self.names)
+ self.state.document.note_explicit_target(signode)
+
+ self.env.domaindata['cpp']['objects'].setdefault(name,
+ (self.env.docname, self.objtype, theid))
+
+ indextext = self.get_index_text(name)
+ if indextext:
+ self.indexnode['entries'].append(('single', indextext, theid, ''))
+
+ def before_content(self):
+ lastname = self.names and self.names[-1]
+ if lastname and not self.env.temp_data.get('cpp:parent'):
+ assert isinstance(lastname, NamedDefExpr)
+ self.env.temp_data['cpp:parent'] = lastname.name
+ self.parentname_set = True
+ else:
+ self.parentname_set = False
+
+ def after_content(self):
+ if self.parentname_set:
+ self.env.temp_data['cpp:parent'] = None
+
+ def parse_definition(self, parser):
+ raise NotImplementedError()
+
+ def describe_signature(self, signode, arg):
+ raise NotImplementedError()
+
+ def handle_signature(self, sig, signode):
+ parser = DefinitionParser(sig)
+ try:
+ rv = self.parse_definition(parser)
+ parser.assert_end()
+ except DefinitionError, e:
+ self.state_machine.reporter.warning(e.description, line=self.lineno)
+ raise ValueError
+ self.describe_signature(signode, rv)
+
+ parent = self.env.temp_data.get('cpp:parent')
+ if parent is not None:
+ rv = rv.clone()
+ rv.name = rv.name.prefix(parent)
+ return rv
+
+
+class CPPClassObject(CPPObject):
+
+ def get_index_text(self, name):
+ return _('%s (C++ class)') % name
+
+ def parse_definition(self, parser):
+ return parser.parse_class()
+
+ def describe_signature(self, signode, cls):
+ self.attach_modifiers(signode, cls)
+ signode += addnodes.desc_annotation('class ', 'class ')
+ self.attach_name(signode, cls.name)
+ if cls.bases:
+ signode += nodes.Text(' : ')
+ for base in cls.bases:
+ self.attach_modifiers(signode, base, 'private')
+ signode += nodes.emphasis(unicode(base.name),
+ unicode(base.name))
+ signode += nodes.Text(', ')
+ signode.pop() # remove the trailing comma
+
+
+class CPPTypeObject(CPPObject):
+
+ def get_index_text(self, name):
+ if self.objtype == 'type':
+ return _('%s (C++ type)') % name
+ return ''
+
+ def parse_definition(self, parser):
+ return parser.parse_type_object()
+
+ def describe_signature(self, signode, obj):
+ self.attach_modifiers(signode, obj)
+ signode += addnodes.desc_annotation('type ', 'type ')
+ if obj.typename is not None:
+ self.attach_type(signode, obj.typename)
+ signode += nodes.Text(' ')
+ self.attach_name(signode, obj.name)
+ self.attach_type_suffixes(signode, obj.type_suffixes)
+
+
+class CPPMemberObject(CPPObject):
+
+ def get_index_text(self, name):
+ if self.objtype == 'member':
+ return _('%s (C++ member)') % name
+ return ''
+
+ def parse_definition(self, parser):
+ return parser.parse_member_object()
+
+ def describe_signature(self, signode, obj):
+ self.attach_modifiers(signode, obj)
+ self.attach_type(signode, obj.typename)
+ signode += nodes.Text(' ')
+ self.attach_name(signode, obj.name)
+ self.attach_type_suffixes(signode, obj.type_suffixes)
+ if obj.value is not None:
+ signode += nodes.Text(u' = ' + obj.value)
+
+
+class CPPFunctionObject(CPPObject):
+
+ def attach_function(self, node, func):
+ owner, name = func.name.split_owner()
+ if owner is not None:
+ owner = unicode(owner) + '::'
+ node += addnodes.desc_addname(owner, owner)
+
+ # cast operator is special. in this case the return value
+ # is reversed.
+ if isinstance(name, CastOpDefExpr):
+ node += addnodes.desc_name('operator', 'operator')
+ node += nodes.Text(u' ')
+ self.attach_type(node, name.typename)
+ else:
+ funcname = unicode(name)
+ node += addnodes.desc_name(funcname, funcname)
+
+ paramlist = addnodes.desc_parameterlist()
+ for arg in func.signature:
+ param = addnodes.desc_parameter('', '', noemph=True)
+ if arg.type is not None:
+ self.attach_type(param, arg.type)
+ param += nodes.Text(u' ')
+ param += nodes.emphasis(unicode(arg.name), unicode(arg.name))
+ self.attach_type_suffixes(param, arg.type_suffixes)
+ if arg.default is not None:
+ def_ = u'=' + unicode(arg.default)
+ param += nodes.emphasis(def_, def_)
+ paramlist += param
+
+ node += paramlist
+ if func.const:
+ node += addnodes.desc_addname(' const', ' const')
+ if func.noexcept:
+ node += addnodes.desc_addname(' noexcept', ' noexcept')
+ if func.pure_virtual:
+ node += addnodes.desc_addname(' = 0', ' = 0')
+
+ def get_index_text(self, name):
+ return _('%s (C++ function)') % name
+
+ def parse_definition(self, parser):
+ return parser.parse_function()
+
+ def describe_signature(self, signode, func):
+ self.attach_modifiers(signode, func)
+ if func.explicit:
+ signode += addnodes.desc_annotation('explicit', 'explicit')
+ signode += nodes.Text(' ')
+ # return value is None for things with a reverse return value
+ # such as casting operator definitions or constructors
+ # and destructors.
+ if func.rv is not None:
+ self.attach_type(signode, func.rv)
+ signode += nodes.Text(u' ')
+ self.attach_function(signode, func)
+
+
+class CPPCurrentNamespace(Directive):
+ """
+ This directive is just to tell Sphinx that we're documenting stuff in
+ namespace foo.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
+ env.temp_data['cpp:prefix'] = None
+ else:
+ parser = DefinitionParser(self.arguments[0])
+ try:
+ prefix = parser.parse_type()
+ parser.assert_end()
+ except DefinitionError, e:
+ self.state_machine.reporter.warning(e.description,
+ line=self.lineno)
+ else:
+ env.temp_data['cpp:prefix'] = prefix
+ return []
+
+
+class CPPXRefRole(XRefRole):
+
+ def process_link(self, env, refnode, has_explicit_title, title, target):
+ refnode['cpp:parent'] = env.temp_data.get('cpp:parent')
+ if not has_explicit_title:
+ target = target.lstrip('~') # only has a meaning for the title
+ # if the first character is a tilde, don't display the module/class
+ # parts of the contents
+ if title[:1] == '~':
+ title = title[1:]
+ dcolon = title.rfind('::')
+ if dcolon != -1:
+ title = title[dcolon + 2:]
+ return title, target
+
+
+class CPPDomain(Domain):
+ """C++ language domain."""
+ name = 'cpp'
+ label = 'C++'
+ object_types = {
+ 'class': ObjType(l_('class'), 'class'),
+ 'function': ObjType(l_('function'), 'func'),
+ 'member': ObjType(l_('member'), 'member'),
+ 'type': ObjType(l_('type'), 'type')
+ }
+
+ directives = {
+ 'class': CPPClassObject,
+ 'function': CPPFunctionObject,
+ 'member': CPPMemberObject,
+ 'type': CPPTypeObject,
+ 'namespace': CPPCurrentNamespace
+ }
+ roles = {
+ 'class': CPPXRefRole(),
+ 'func' : CPPXRefRole(fix_parens=True),
+ 'member': CPPXRefRole(),
+ 'type': CPPXRefRole()
+ }
+ initial_data = {
+ 'objects': {}, # fullname -> docname, objtype
+ }
+
+ def clear_doc(self, docname):
+ for fullname, (fn, _, _) in self.data['objects'].items():
+ if fn == docname:
+ del self.data['objects'][fullname]
+
+ def resolve_xref(self, env, fromdocname, builder,
+ typ, target, node, contnode):
+ def _create_refnode(expr):
+ name = unicode(expr)
+ if name not in self.data['objects']:
+ return None
+ obj = self.data['objects'][name]
+ if obj[1] not in self.objtypes_for_role(typ):
+ return None
+ return make_refnode(builder, fromdocname, obj[0], obj[2],
+ contnode, name)
+
+ parser = DefinitionParser(target)
+ try:
+ expr = parser.parse_type().get_name()
+ parser.skip_ws()
+ if not parser.eof or expr is None:
+ raise DefinitionError('')
+ except DefinitionError:
+ env.warn_node('unparseable C++ definition: %r' % target, node)
+ return None
+
+ parent = node.get('cpp:parent', None)
+
+ rv = _create_refnode(expr)
+ if rv is not None or parent is None:
+ return rv
+ parent = parent.get_name()
+
+ rv = _create_refnode(expr.prefix(parent))
+ if rv is not None:
+ return rv
+
+ parent, name = parent.split_owner()
+ return _create_refnode(expr.prefix(parent))
+
+ def get_objects(self):
+ for refname, (docname, type, theid) in self.data['objects'].iteritems():
+ yield (refname, refname, type, docname, refname, 1)
diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py
new file mode 100644
index 0000000..9b7777f
--- /dev/null
+++ b/sphinx/domains/javascript.py
@@ -0,0 +1,220 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.domains.javascript
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The JavaScript domain.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx import addnodes
+from sphinx.domains import Domain, ObjType
+from sphinx.locale import l_, _
+from sphinx.directives import ObjectDescription
+from sphinx.roles import XRefRole
+from sphinx.domains.python import _pseudo_parse_arglist
+from sphinx.util.nodes import make_refnode
+from sphinx.util.docfields import Field, GroupedField, TypedField
+
+
+class JSObject(ObjectDescription):
+ """
+ Description of a JavaScript object.
+ """
+ #: If set to ``True`` this object is callable and a `desc_parameterlist` is
+ #: added
+ has_arguments = False
+
+ #: what is displayed right before the documentation entry
+ display_prefix = None
+
+ def handle_signature(self, sig, signode):
+ sig = sig.strip()
+ if '(' in sig and sig[-1:] == ')':
+ prefix, arglist = sig.split('(', 1)
+ prefix = prefix.strip()
+ arglist = arglist[:-1].strip()
+ else:
+ prefix = sig
+ arglist = None
+ if '.' in prefix:
+ nameprefix, name = prefix.rsplit('.', 1)
+ else:
+ nameprefix = None
+ name = prefix
+
+ objectname = self.env.temp_data.get('js:object')
+ if nameprefix:
+ if objectname:
+ # someone documenting the method of an attribute of the current
+ # object? shouldn't happen but who knows...
+ nameprefix = objectname + '.' + nameprefix
+ fullname = nameprefix + '.' + name
+ elif objectname:
+ fullname = objectname + '.' + name
+ else:
+ # just a function or constructor
+ objectname = ''
+ fullname = name
+
+ signode['object'] = objectname
+ signode['fullname'] = fullname
+
+ if self.display_prefix:
+ signode += addnodes.desc_annotation(self.display_prefix,
+ self.display_prefix)
+ if nameprefix:
+ signode += addnodes.desc_addname(nameprefix + '.', nameprefix + '.')
+ signode += addnodes.desc_name(name, name)
+ if self.has_arguments:
+ if not arglist:
+ signode += addnodes.desc_parameterlist()
+ else:
+ _pseudo_parse_arglist(signode, arglist)
+ return fullname, nameprefix
+
+ def add_target_and_index(self, name_obj, sig, signode):
+ objectname = self.options.get(
+ 'object', self.env.temp_data.get('js:object'))
+ fullname = name_obj[0]
+ if fullname not in self.state.document.ids:
+ signode['names'].append(fullname)
+ signode['ids'].append(fullname.replace('$', '_S_'))
+ signode['first'] = not self.names
+ self.state.document.note_explicit_target(signode)
+ objects = self.env.domaindata['js']['objects']
+ if fullname in objects:
+ self.state_machine.reporter.warning(
+ 'duplicate object description of %s, ' % fullname +
+ 'other instance in ' +
+ self.env.doc2path(objects[fullname][0]),
+ line=self.lineno)
+ objects[fullname] = self.env.docname, self.objtype
+
+ indextext = self.get_index_text(objectname, name_obj)
+ if indextext:
+ self.indexnode['entries'].append(('single', indextext,
+ fullname.replace('$', '_S_'),
+ ''))
+
+ def get_index_text(self, objectname, name_obj):
+ name, obj = name_obj
+ if self.objtype == 'function':
+ if not obj:
+ return _('%s() (built-in function)') % name
+ return _('%s() (%s method)') % (name, obj)
+ elif self.objtype == 'class':
+ return _('%s() (class)') % name
+ elif self.objtype == 'data':
+ return _('%s (global variable or constant)') % name
+ elif self.objtype == 'attribute':
+ return _('%s (%s attribute)') % (name, obj)
+ return ''
+
+
+class JSCallable(JSObject):
+ """Description of a JavaScript function, method or constructor."""
+ has_arguments = True
+
+ doc_field_types = [
+ TypedField('arguments', label=l_('Arguments'),
+ names=('argument', 'arg', 'parameter', 'param'),
+ typerolename='func', typenames=('paramtype', 'type')),
+ GroupedField('errors', label=l_('Throws'), rolename='err',
+ names=('throws', ),
+ can_collapse=True),
+ Field('returnvalue', label=l_('Returns'), has_arg=False,
+ names=('returns', 'return')),
+ Field('returntype', label=l_('Return type'), has_arg=False,
+ names=('rtype',)),
+ ]
+
+
+class JSConstructor(JSCallable):
+ """Like a callable but with a different prefix."""
+ display_prefix = 'class '
+
+
+class JSXRefRole(XRefRole):
+ def process_link(self, env, refnode, has_explicit_title, title, target):
+ # basically what sphinx.domains.python.PyXRefRole does
+ refnode['js:object'] = env.temp_data.get('js:object')
+ if not has_explicit_title:
+ title = title.lstrip('.')
+ target = target.lstrip('~')
+ if title[0:1] == '~':
+ title = title[1:]
+ dot = title.rfind('.')
+ if dot != -1:
+ title = title[dot+1:]
+ if target[0:1] == '.':
+ target = target[1:]
+ refnode['refspecific'] = True
+ return title, target
+
+
+class JavaScriptDomain(Domain):
+ """JavaScript language domain."""
+ name = 'js'
+ label = 'JavaScript'
+ # if you add a new object type make sure to edit JSObject.get_index_string
+ object_types = {
+ 'function': ObjType(l_('function'), 'func'),
+ 'class': ObjType(l_('class'), 'class'),
+ 'data': ObjType(l_('data'), 'data'),
+ 'attribute': ObjType(l_('attribute'), 'attr'),
+ }
+ directives = {
+ 'function': JSCallable,
+ 'class': JSConstructor,
+ 'data': JSObject,
+ 'attribute': JSObject,
+ }
+ roles = {
+ 'func': JSXRefRole(fix_parens=True),
+ 'class': JSXRefRole(fix_parens=True),
+ 'data': JSXRefRole(),
+ 'attr': JSXRefRole(),
+ }
+ initial_data = {
+ 'objects': {}, # fullname -> docname, objtype
+ }
+
+ def clear_doc(self, docname):
+ for fullname, (fn, _) in self.data['objects'].items():
+ if fn == docname:
+ del self.data['objects'][fullname]
+
+ def find_obj(self, env, obj, name, typ, searchorder=0):
+ if name[-2:] == '()':
+ name = name[:-2]
+ objects = self.data['objects']
+ newname = None
+ if searchorder == 1:
+ if obj and obj + '.' + name in objects:
+ newname = obj + '.' + name
+ else:
+ newname = name
+ else:
+ if name in objects:
+ newname = name
+ elif obj and obj + '.' + name in objects:
+ newname = obj + '.' + name
+ return newname, objects.get(newname)
+
+ def resolve_xref(self, env, fromdocname, builder, typ, target, node,
+ contnode):
+ objectname = node.get('js:object')
+ searchorder = node.hasattr('refspecific') and 1 or 0
+ name, obj = self.find_obj(env, objectname, target, typ, searchorder)
+ if not obj:
+ return None
+ return make_refnode(builder, fromdocname, obj[0],
+ name.replace('$', '_S_'), contnode, name)
+
+ def get_objects(self):
+ for refname, (docname, type) in self.data['objects'].iteritems():
+ yield refname, refname, type, docname, \
+ refname.replace('$', '_S_'), 1
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
new file mode 100644
index 0000000..792cffd
--- /dev/null
+++ b/sphinx/domains/python.py
@@ -0,0 +1,710 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.domains.python
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ The Python domain.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+
+from sphinx import addnodes
+from sphinx.roles import XRefRole
+from sphinx.locale import l_, _
+from sphinx.domains import Domain, ObjType, Index
+from sphinx.directives import ObjectDescription
+from sphinx.util.nodes import make_refnode
+from sphinx.util.compat import Directive
+from sphinx.util.docfields import Field, GroupedField, TypedField
+
+
+# REs for Python signatures
+py_sig_re = re.compile(
+ r'''^ ([\w.]*\.)? # class name(s)
+ (\w+) \s* # thing name
+ (?: \((.*)\) # optional: arguments
+ (?:\s* -> \s* (.*))? # return annotation
+ )? $ # and nothing more
+ ''', re.VERBOSE)
+
+
+def _pseudo_parse_arglist(signode, arglist):
+ """"Parse" a list of arguments separated by commas.
+
+ Arguments can have "optional" annotations given by enclosing them in
+ brackets. Currently, this will split at any comma, even if it's inside a
+ string literal (e.g. default argument value).
+ """
+ paramlist = addnodes.desc_parameterlist()
+ stack = [paramlist]
+ try:
+ for argument in arglist.split(','):
+ argument = argument.strip()
+ ends_open = ends_close = 0
+ while argument.startswith('['):
+ stack.append(addnodes.desc_optional())
+ stack[-2] += stack[-1]
+ argument = argument[1:].strip()
+ while argument.startswith(']'):
+ stack.pop()
+ argument = argument[1:].strip()
+ while argument.endswith(']') and not argument.endswith('[]'):
+ ends_close += 1
+ argument = argument[:-1].strip()
+ while argument.endswith('['):
+ ends_open += 1
+ argument = argument[:-1].strip()
+ if argument:
+ stack[-1] += addnodes.desc_parameter(argument, argument)
+ while ends_open:
+ stack.append(addnodes.desc_optional())
+ stack[-2] += stack[-1]
+ ends_open -= 1
+ while ends_close:
+ stack.pop()
+ ends_close -= 1
+ if len(stack) != 1:
+ raise IndexError
+ except IndexError:
+ # if there are too few or too many elements on the stack, just give up
+ # and treat the whole argument list as one argument, discarding the
+ # already partially populated paramlist node
+ signode += addnodes.desc_parameterlist()
+ signode[-1] += addnodes.desc_parameter(arglist, arglist)
+ else:
+ signode += paramlist
+
+
+class PyObject(ObjectDescription):
+ """
+ Description of a general Python object.
+ """
+ option_spec = {
+ 'noindex': directives.flag,
+ 'module': directives.unchanged,
+ 'annotation': directives.unchanged,
+ }
+
+ doc_field_types = [
+ TypedField('parameter', label=l_('Parameters'),
+ names=('param', 'parameter', 'arg', 'argument',
+ 'keyword', 'kwarg', 'kwparam'),
+ typerolename='obj', typenames=('paramtype', 'type'),
+ can_collapse=True),
+ TypedField('variable', label=l_('Variables'), rolename='obj',
+ names=('var', 'ivar', 'cvar'),
+ typerolename='obj', typenames=('vartype',),
+ can_collapse=True),
+ GroupedField('exceptions', label=l_('Raises'), rolename='exc',
+ names=('raises', 'raise', 'exception', 'except'),
+ can_collapse=True),
+ Field('returnvalue', label=l_('Returns'), has_arg=False,
+ names=('returns', 'return')),
+ Field('returntype', label=l_('Return type'), has_arg=False,
+ names=('rtype',)),
+ ]
+
+ def get_signature_prefix(self, sig):
+ """May return a prefix to put before the object name in the
+ signature.
+ """
+ return ''
+
+ def needs_arglist(self):
+ """May return true if an empty argument list is to be generated even if
+ the document contains none.
+ """
+ return False
+
+ def handle_signature(self, sig, signode):
+ """Transform a Python signature into RST nodes.
+
+ Return (fully qualified name of the thing, classname if any).
+
+ If inside a class, the current class name is handled intelligently:
+ * it is stripped from the displayed name if present
+ * it is added to the full name (return value) if not present
+ """
+ m = py_sig_re.match(sig)
+ if m is None:
+ raise ValueError
+ name_prefix, name, arglist, retann = m.groups()
+
+ # determine module and class name (if applicable), as well as full name
+ modname = self.options.get(
+ 'module', self.env.temp_data.get('py:module'))
+ classname = self.env.temp_data.get('py:class')
+ if classname:
+ add_module = False
+ if name_prefix and name_prefix.startswith(classname):
+ fullname = name_prefix + name
+ # class name is given again in the signature
+ name_prefix = name_prefix[len(classname):].lstrip('.')
+ elif name_prefix:
+ # class name is given in the signature, but different
+ # (shouldn't happen)
+ fullname = classname + '.' + name_prefix + name
+ else:
+ # class name is not given in the signature
+ fullname = classname + '.' + name
+ else:
+ add_module = True
+ if name_prefix:
+ classname = name_prefix.rstrip('.')
+ fullname = name_prefix + name
+ else:
+ classname = ''
+ fullname = name
+
+ signode['module'] = modname
+ signode['class'] = classname
+ signode['fullname'] = fullname
+
+ sig_prefix = self.get_signature_prefix(sig)
+ if sig_prefix:
+ signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
+
+ if name_prefix:
+ signode += addnodes.desc_addname(name_prefix, name_prefix)
+ # exceptions are a special case, since they are documented in the
+ # 'exceptions' module.
+ elif add_module and self.env.config.add_module_names:
+ modname = self.options.get(
+ 'module', self.env.temp_data.get('py:module'))
+ if modname and modname != 'exceptions':
+ nodetext = modname + '.'
+ signode += addnodes.desc_addname(nodetext, nodetext)
+
+ anno = self.options.get('annotation')
+
+ signode += addnodes.desc_name(name, name)
+ if not arglist:
+ if self.needs_arglist():
+ # for callables, add an empty parameter list
+ signode += addnodes.desc_parameterlist()
+ if retann:
+ signode += addnodes.desc_returns(retann, retann)
+ if anno:
+ signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
+ return fullname, name_prefix
+
+ _pseudo_parse_arglist(signode, arglist)
+ if retann:
+ signode += addnodes.desc_returns(retann, retann)
+ if anno:
+ signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
+ return fullname, name_prefix
+
+ def get_index_text(self, modname, name):
+ """Return the text for the index entry of the object."""
+ raise NotImplementedError('must be implemented in subclasses')
+
+ def add_target_and_index(self, name_cls, sig, signode):
+ modname = self.options.get(
+ 'module', self.env.temp_data.get('py:module'))
+ fullname = (modname and modname + '.' or '') + name_cls[0]
+ # note target
+ if fullname not in self.state.document.ids:
+ signode['names'].append(fullname)
+ signode['ids'].append(fullname)
+ signode['first'] = (not self.names)
+ self.state.document.note_explicit_target(signode)
+ objects = self.env.domaindata['py']['objects']
+ if fullname in objects:
+ self.state_machine.reporter.warning(
+ 'duplicate object description of %s, ' % fullname +
+ 'other instance in ' +
+ self.env.doc2path(objects[fullname][0]) +
+ ', use :noindex: for one of them',
+ line=self.lineno)
+ objects[fullname] = (self.env.docname, self.objtype)
+
+ indextext = self.get_index_text(modname, name_cls)
+ if indextext:
+ self.indexnode['entries'].append(('single', indextext,
+ fullname, ''))
+
+ def before_content(self):
+ # needed for automatic qualification of members (reset in subclasses)
+ self.clsname_set = False
+
+ def after_content(self):
+ if self.clsname_set:
+ self.env.temp_data['py:class'] = None
+
+
+class PyModulelevel(PyObject):
+ """
+ Description of an object on module level (functions, data).
+ """
+
+ def needs_arglist(self):
+ return self.objtype == 'function'
+
+ def get_index_text(self, modname, name_cls):
+ if self.objtype == 'function':
+ if not modname:
+ return _('%s() (built-in function)') % name_cls[0]
+ return _('%s() (in module %s)') % (name_cls[0], modname)
+ elif self.objtype == 'data':
+ if not modname:
+ return _('%s (built-in variable)') % name_cls[0]
+ return _('%s (in module %s)') % (name_cls[0], modname)
+ else:
+ return ''
+
+
+class PyClasslike(PyObject):
+ """
+ Description of a class-like object (classes, interfaces, exceptions).
+ """
+
+ def get_signature_prefix(self, sig):
+ return self.objtype + ' '
+
+ def get_index_text(self, modname, name_cls):
+ if self.objtype == 'class':
+ if not modname:
+ return _('%s (built-in class)') % name_cls[0]
+ return _('%s (class in %s)') % (name_cls[0], modname)
+ elif self.objtype == 'exception':
+ return name_cls[0]
+ else:
+ return ''
+
+ def before_content(self):
+ PyObject.before_content(self)
+ if self.names:
+ self.env.temp_data['py:class'] = self.names[0][0]
+ self.clsname_set = True
+
+
+class PyClassmember(PyObject):
+ """
+ Description of a class member (methods, attributes).
+ """
+
+ def needs_arglist(self):
+ return self.objtype.endswith('method')
+
+ def get_signature_prefix(self, sig):
+ if self.objtype == 'staticmethod':
+ return 'static '
+ elif self.objtype == 'classmethod':
+ return 'classmethod '
+ return ''
+
+ def get_index_text(self, modname, name_cls):
+ name, cls = name_cls
+ add_modules = self.env.config.add_module_names
+ if self.objtype == 'method':
+ try:
+ clsname, methname = name.rsplit('.', 1)
+ except ValueError:
+ if modname:
+ return _('%s() (in module %s)') % (name, modname)
+ else:
+ return '%s()' % name
+ if modname and add_modules:
+ return _('%s() (%s.%s method)') % (methname, modname, clsname)
+ else:
+ return _('%s() (%s method)') % (methname, clsname)
+ elif self.objtype == 'staticmethod':
+ try:
+ clsname, methname = name.rsplit('.', 1)
+ except ValueError:
+ if modname:
+ return _('%s() (in module %s)') % (name, modname)
+ else:
+ return '%s()' % name
+ if modname and add_modules:
+ return _('%s() (%s.%s static method)') % (methname, modname,
+ clsname)
+ else:
+ return _('%s() (%s static method)') % (methname, clsname)
+ elif self.objtype == 'classmethod':
+ try:
+ clsname, methname = name.rsplit('.', 1)
+ except ValueError:
+ if modname:
+ return _('%s() (in module %s)') % (name, modname)
+ else:
+ return '%s()' % name
+ if modname:
+ return _('%s() (%s.%s class method)') % (methname, modname,
+ clsname)
+ else:
+ return _('%s() (%s class method)') % (methname, clsname)
+ elif self.objtype == 'attribute':
+ try:
+ clsname, attrname = name.rsplit('.', 1)
+ except ValueError:
+ if modname:
+ return _('%s (in module %s)') % (name, modname)
+ else:
+ return name
+ if modname and add_modules:
+ return _('%s (%s.%s attribute)') % (attrname, modname, clsname)
+ else:
+ return _('%s (%s attribute)') % (attrname, clsname)
+ else:
+ return ''
+
+ def before_content(self):
+ PyObject.before_content(self)
+ lastname = self.names and self.names[-1][1]
+ if lastname and not self.env.temp_data.get('py:class'):
+ self.env.temp_data['py:class'] = lastname.strip('.')
+ self.clsname_set = True
+
+
+class PyDecoratorMixin(object):
+ """
+ Mixin for decorator directives.
+ """
+ def handle_signature(self, sig, signode):
+ ret = super(PyDecoratorMixin, self).handle_signature(sig, signode)
+ signode.insert(0, addnodes.desc_addname('@', '@'))
+ return ret
+
+ def needs_arglist(self):
+ return False
+
+
+class PyDecoratorFunction(PyDecoratorMixin, PyModulelevel):
+ """
+ Directive to mark functions meant to be used as decorators.
+ """
+ def run(self):
+ # a decorator function is a function after all
+ self.name = 'py:function'
+ return PyModulelevel.run(self)
+
+
+class PyDecoratorMethod(PyDecoratorMixin, PyClassmember):
+ """
+ Directive to mark methods meant to be used as decorators.
+ """
+ def run(self):
+ self.name = 'py:method'
+ return PyClassmember.run(self)
+
+
+class PyModule(Directive):
+ """
+ Directive to mark description of a new module.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {
+ 'platform': lambda x: x,
+ 'synopsis': lambda x: x,
+ 'noindex': directives.flag,
+ 'deprecated': directives.flag,
+ }
+
+ def run(self):
+ env = self.state.document.settings.env
+ modname = self.arguments[0].strip()
+ noindex = 'noindex' in self.options
+ env.temp_data['py:module'] = modname
+ ret = []
+ if not noindex:
+ env.domaindata['py']['modules'][modname] = \
+ (env.docname, self.options.get('synopsis', ''),
+ self.options.get('platform', ''), 'deprecated' in self.options)
+ # make a duplicate entry in 'objects' to facilitate searching for
+ # the module in PythonDomain.find_obj()
+ env.domaindata['py']['objects'][modname] = (env.docname, 'module')
+ targetnode = nodes.target('', '', ids=['module-' + modname],
+ ismod=True)
+ self.state.document.note_explicit_target(targetnode)
+ # the platform and synopsis aren't printed; in fact, they are only
+ # used in the modindex currently
+ ret.append(targetnode)
+ indextext = _('%s (module)') % modname
+ inode = addnodes.index(entries=[('single', indextext,
+ 'module-' + modname, '')])
+ ret.append(inode)
+ return ret
+
+
+class PyCurrentModule(Directive):
+ """
+ This directive is just to tell Sphinx that we're documenting
+ stuff in module foo, but links to module foo won't lead here.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ modname = self.arguments[0].strip()
+ if modname == 'None':
+ env.temp_data['py:module'] = None
+ else:
+ env.temp_data['py:module'] = modname
+ return []
+
+
+class PyXRefRole(XRefRole):
+ def process_link(self, env, refnode, has_explicit_title, title, target):
+ refnode['py:module'] = env.temp_data.get('py:module')
+ refnode['py:class'] = env.temp_data.get('py:class')
+ if not has_explicit_title:
+ title = title.lstrip('.') # only has a meaning for the target
+ target = target.lstrip('~') # only has a meaning for the title
+ # if the first character is a tilde, don't display the module/class
+ # parts of the contents
+ if title[0:1] == '~':
+ title = title[1:]
+ dot = title.rfind('.')
+ if dot != -1:
+ title = title[dot+1:]
+ # if the first character is a dot, search more specific namespaces first
+ # else search builtins first
+ if target[0:1] == '.':
+ target = target[1:]
+ refnode['refspecific'] = True
+ return title, target
+
+
+class PythonModuleIndex(Index):
+ """
+ Index subclass to provide the Python module index.
+ """
+
+ name = 'modindex'
+ localname = l_('Python Module Index')
+ shortname = l_('modules')
+
+ def generate(self, docnames=None):
+ content = {}
+ # list of prefixes to ignore
+ ignores = self.domain.env.config['modindex_common_prefix']
+ ignores = sorted(ignores, key=len, reverse=True)
+ # list of all modules, sorted by module name
+ modules = sorted(self.domain.data['modules'].iteritems(),
+ key=lambda x: x[0].lower())
+ # sort out collapsable modules
+ prev_modname = ''
+ num_toplevels = 0
+ for modname, (docname, synopsis, platforms, deprecated) in modules:
+ if docnames and docname not in docnames:
+ continue
+
+ for ignore in ignores:
+ if modname.startswith(ignore):
+ modname = modname[len(ignore):]
+ stripped = ignore
+ break
+ else:
+ stripped = ''
+
+ # we stripped the whole module name?
+ if not modname:
+ modname, stripped = stripped, ''
+
+ entries = content.setdefault(modname[0].lower(), [])
+
+ package = modname.split('.')[0]
+ if package != modname:
+ # it's a submodule
+ if prev_modname == package:
+ # first submodule - make parent a group head
+ if entries:
+ entries[-1][1] = 1
+ elif not prev_modname.startswith(package):
+ # submodule without parent in list, add dummy entry
+ entries.append([stripped + package, 1, '', '', '', '', ''])
+ subtype = 2
+ else:
+ num_toplevels += 1
+ subtype = 0
+
+ qualifier = deprecated and _('Deprecated') or ''
+ entries.append([stripped + modname, subtype, docname,
+ 'module-' + stripped + modname, platforms,
+ qualifier, synopsis])
+ prev_modname = modname
+
+ # apply heuristics when to collapse modindex at page load:
+ # only collapse if number of toplevel modules is larger than
+ # number of submodules
+ collapse = len(modules) - num_toplevels < num_toplevels
+
+ # sort by first letter
+ content = sorted(content.iteritems())
+
+ return content, collapse
+
+
+class PythonDomain(Domain):
+ """Python language domain."""
+ name = 'py'
+ label = 'Python'
+ object_types = {
+ 'function': ObjType(l_('function'), 'func', 'obj'),
+ 'data': ObjType(l_('data'), 'data', 'obj'),
+ 'class': ObjType(l_('class'), 'class', 'exc', 'obj'),
+ 'exception': ObjType(l_('exception'), 'exc', 'class', 'obj'),
+ 'method': ObjType(l_('method'), 'meth', 'obj'),
+ 'classmethod': ObjType(l_('class method'), 'meth', 'obj'),
+ 'staticmethod': ObjType(l_('static method'), 'meth', 'obj'),
+ 'attribute': ObjType(l_('attribute'), 'attr', 'obj'),
+ 'module': ObjType(l_('module'), 'mod', 'obj'),
+ }
+
+ directives = {
+ 'function': PyModulelevel,
+ 'data': PyModulelevel,
+ 'class': PyClasslike,
+ 'exception': PyClasslike,
+ 'method': PyClassmember,
+ 'classmethod': PyClassmember,
+ 'staticmethod': PyClassmember,
+ 'attribute': PyClassmember,
+ 'module': PyModule,
+ 'currentmodule': PyCurrentModule,
+ 'decorator': PyDecoratorFunction,
+ 'decoratormethod': PyDecoratorMethod,
+ }
+ roles = {
+ 'data': PyXRefRole(),
+ 'exc': PyXRefRole(),
+ 'func': PyXRefRole(fix_parens=True),
+ 'class': PyXRefRole(),
+ 'const': PyXRefRole(),
+ 'attr': PyXRefRole(),
+ 'meth': PyXRefRole(fix_parens=True),
+ 'mod': PyXRefRole(),
+ 'obj': PyXRefRole(),
+ }
+ initial_data = {
+ 'objects': {}, # fullname -> docname, objtype
+ 'modules': {}, # modname -> docname, synopsis, platform, deprecated
+ }
+ indices = [
+ PythonModuleIndex,
+ ]
+
+ def clear_doc(self, docname):
+ for fullname, (fn, _) in self.data['objects'].items():
+ if fn == docname:
+ del self.data['objects'][fullname]
+ for modname, (fn, _, _, _) in self.data['modules'].items():
+ if fn == docname:
+ del self.data['modules'][modname]
+
+ def find_obj(self, env, modname, classname, name, type, searchmode=0):
+ """Find a Python object for "name", perhaps using the given module
+ and/or classname. Returns a list of (name, object entry) tuples.
+ """
+ # skip parens
+ if name[-2:] == '()':
+ name = name[:-2]
+
+ if not name:
+ return []
+
+ objects = self.data['objects']
+ matches = []
+
+ newname = None
+ if searchmode == 1:
+ objtypes = self.objtypes_for_role(type)
+ if objtypes is not None:
+ if modname and classname:
+ fullname = modname + '.' + classname + '.' + name
+ if fullname in objects and objects[fullname][1] in objtypes:
+ newname = fullname
+ if not newname:
+ if modname and modname + '.' + name in objects and \
+ objects[modname + '.' + name][1] in objtypes:
+ newname = modname + '.' + name
+ elif name in objects and objects[name][1] in objtypes:
+ newname = name
+ else:
+ # "fuzzy" searching mode
+ searchname = '.' + name
+ matches = [(oname, objects[oname]) for oname in objects
+ if oname.endswith(searchname)
+ and objects[oname][1] in objtypes]
+ else:
+ # NOTE: searching for exact match, object type is not considered
+ if name in objects:
+ newname = name
+ elif type == 'mod':
+ # only exact matches allowed for modules
+ return []
+ elif classname and classname + '.' + name in objects:
+ newname = classname + '.' + name
+ elif modname and modname + '.' + name in objects:
+ newname = modname + '.' + name
+ elif modname and classname and \
+ modname + '.' + classname + '.' + name in objects:
+ newname = modname + '.' + classname + '.' + name
+ # special case: builtin exceptions have module "exceptions" set
+ elif type == 'exc' and '.' not in name and \
+ 'exceptions.' + name in objects:
+ newname = 'exceptions.' + name
+ # special case: object methods
+ elif type in ('func', 'meth') and '.' not in name and \
+ 'object.' + name in objects:
+ newname = 'object.' + name
+ if newname is not None:
+ matches.append((newname, objects[newname]))
+ return matches
+
+ def resolve_xref(self, env, fromdocname, builder,
+ type, target, node, contnode):
+ modname = node.get('py:module')
+ clsname = node.get('py:class')
+ searchmode = node.hasattr('refspecific') and 1 or 0
+ matches = self.find_obj(env, modname, clsname, target,
+ type, searchmode)
+ if not matches:
+ return None
+ elif len(matches) > 1:
+ env.warn_node(
+ 'more than one target found for cross-reference '
+ '%r: %s' % (target, ', '.join(match[0] for match in matches)),
+ node)
+ name, obj = matches[0]
+
+ if obj[1] == 'module':
+ # get additional info for modules
+ docname, synopsis, platform, deprecated = self.data['modules'][name]
+ assert docname == obj[0]
+ title = name
+ if synopsis:
+ title += ': ' + synopsis
+ if deprecated:
+ title += _(' (deprecated)')
+ if platform:
+ title += ' (' + platform + ')'
+ return make_refnode(builder, fromdocname, docname,
+ 'module-' + name, contnode, title)
+ else:
+ return make_refnode(builder, fromdocname, obj[0], name,
+ contnode, name)
+
+ def get_objects(self):
+ for modname, info in self.data['modules'].iteritems():
+ yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
+ for refname, (docname, type) in self.data['objects'].iteritems():
+ if type != 'module': # modules are already handled
+ yield (refname, refname, type, docname, refname, 1)
diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py
new file mode 100644
index 0000000..c51c85f
--- /dev/null
+++ b/sphinx/domains/rst.py
@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.domains.rst
+ ~~~~~~~~~~~~~~~~~~
+
+ The reStructuredText domain.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from sphinx import addnodes
+from sphinx.domains import Domain, ObjType
+from sphinx.locale import l_, _
+from sphinx.directives import ObjectDescription
+from sphinx.roles import XRefRole
+from sphinx.util.nodes import make_refnode
+
+
+dir_sig_re = re.compile(r'\.\. (.+?)::(.*)$')
+
+
+class ReSTMarkup(ObjectDescription):
+ """
+ Description of generic reST markup.
+ """
+
+ def add_target_and_index(self, name, sig, signode):
+ targetname = self.objtype + '-' + name
+ if targetname not in self.state.document.ids:
+ signode['names'].append(targetname)
+ signode['ids'].append(targetname)
+ signode['first'] = (not self.names)
+ self.state.document.note_explicit_target(signode)
+
+ objects = self.env.domaindata['rst']['objects']
+ key = (self.objtype, name)
+ if key in objects:
+ self.state_machine.reporter.warning(
+ 'duplicate description of %s %s, ' % (self.objtype, name) +
+ 'other instance in ' + self.env.doc2path(objects[key]),
+ line=self.lineno)
+ objects[key] = self.env.docname
+ indextext = self.get_index_text(self.objtype, name)
+ if indextext:
+ self.indexnode['entries'].append(('single', indextext,
+ targetname, ''))
+
+ def get_index_text(self, objectname, name):
+ if self.objtype == 'directive':
+ return _('%s (directive)') % name
+ elif self.objtype == 'role':
+ return _('%s (role)') % name
+ return ''
+
+
+def parse_directive(d):
+ """Parse a directive signature.
+
+ Returns (directive, arguments) string tuple. If no arguments are given,
+ returns (directive, '').
+ """
+ dir = d.strip()
+ if not dir.startswith('.'):
+ # Assume it is a directive without syntax
+ return (dir, '')
+ m = dir_sig_re.match(dir)
+ if not m:
+ return (dir, '')
+ parsed_dir, parsed_args = m.groups()
+ return (parsed_dir.strip(), ' ' + parsed_args.strip())
+
+
+class ReSTDirective(ReSTMarkup):
+ """
+ Description of a reST directive.
+ """
+ def handle_signature(self, sig, signode):
+ name, args = parse_directive(sig)
+ desc_name = '.. %s::' % name
+ signode += addnodes.desc_name(desc_name, desc_name)
+ if len(args) > 0:
+ signode += addnodes.desc_addname(args, args)
+ return name
+
+
+class ReSTRole(ReSTMarkup):
+ """
+ Description of a reST role.
+ """
+ def handle_signature(self, sig, signode):
+ signode += addnodes.desc_name(':%s:' % sig, ':%s:' % sig)
+ return sig
+
+
+class ReSTDomain(Domain):
+ """ReStructuredText domain."""
+ name = 'rst'
+ label = 'reStructuredText'
+
+ object_types = {
+ 'directive': ObjType(l_('directive'), 'dir'),
+ 'role': ObjType(l_('role'), 'role'),
+ }
+ directives = {
+ 'directive': ReSTDirective,
+ 'role': ReSTRole,
+ }
+ roles = {
+ 'dir': XRefRole(),
+ 'role': XRefRole(),
+ }
+ initial_data = {
+ 'objects': {}, # fullname -> docname, objtype
+ }
+
+ def clear_doc(self, docname):
+ for (typ, name), doc in self.data['objects'].items():
+ if doc == docname:
+ del self.data['objects'][typ, name]
+
+ def resolve_xref(self, env, fromdocname, builder, typ, target, node,
+ contnode):
+ objects = self.data['objects']
+ objtypes = self.objtypes_for_role(typ)
+ for objtype in objtypes:
+ if (objtype, target) in objects:
+ return make_refnode(builder, fromdocname,
+ objects[objtype, target],
+ objtype + '-' + target,
+ contnode, target + ' ' + objtype)
+
+ def get_objects(self):
+ for (typ, name), docname in self.data['objects'].iteritems():
+ yield name, name, typ, docname, typ + '-' + name, 1
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
new file mode 100644
index 0000000..43341e4
--- /dev/null
+++ b/sphinx/domains/std.py
@@ -0,0 +1,639 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.domains.std
+ ~~~~~~~~~~~~~~~~~~
+
+ The standard domain.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import unicodedata
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+from docutils.statemachine import ViewList
+
+from sphinx import addnodes
+from sphinx.roles import XRefRole
+from sphinx.locale import l_, _
+from sphinx.domains import Domain, ObjType
+from sphinx.directives import ObjectDescription
+from sphinx.util import ws_re
+from sphinx.util.nodes import clean_astext, make_refnode
+from sphinx.util.compat import Directive
+
+
+# RE for option descriptions
+option_desc_re = re.compile(r'((?:/|-|--)?[-_a-zA-Z0-9]+)(\s*.*)')
+
+
+class GenericObject(ObjectDescription):
+ """
+ A generic x-ref directive registered with Sphinx.add_object_type().
+ """
+ indextemplate = ''
+ parse_node = None
+
+ def handle_signature(self, sig, signode):
+ if self.parse_node:
+ name = self.parse_node(self.env, sig, signode)
+ else:
+ signode.clear()
+ signode += addnodes.desc_name(sig, sig)
+ # normalize whitespace like XRefRole does
+ name = ws_re.sub('', sig)
+ return name
+
+ def add_target_and_index(self, name, sig, signode):
+ targetname = '%s-%s' % (self.objtype, name)
+ signode['ids'].append(targetname)
+ self.state.document.note_explicit_target(signode)
+ if self.indextemplate:
+ colon = self.indextemplate.find(':')
+ if colon != -1:
+ indextype = self.indextemplate[:colon].strip()
+ indexentry = self.indextemplate[colon+1:].strip() % (name,)
+ else:
+ indextype = 'single'
+ indexentry = self.indextemplate % (name,)
+ self.indexnode['entries'].append((indextype, indexentry,
+ targetname, ''))
+ self.env.domaindata['std']['objects'][self.objtype, name] = \
+ self.env.docname, targetname
+
+
+class EnvVar(GenericObject):
+ indextemplate = l_('environment variable; %s')
+
+
+class EnvVarXRefRole(XRefRole):
+ """
+ Cross-referencing role for environment variables (adds an index entry).
+ """
+
+ def result_nodes(self, document, env, node, is_ref):
+ if not is_ref:
+ return [node], []
+ varname = node['reftarget']
+ tgtid = 'index-%s' % env.new_serialno('index')
+ indexnode = addnodes.index()
+ indexnode['entries'] = [
+ ('single', varname, tgtid, ''),
+ ('single', _('environment variable; %s') % varname, tgtid, '')
+ ]
+ targetnode = nodes.target('', '', ids=[tgtid])
+ document.note_explicit_target(targetnode)
+ return [indexnode, targetnode, node], []
+
+
+class Target(Directive):
+ """
+ Generic target for user-defined cross-reference types.
+ """
+ indextemplate = ''
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ # normalize whitespace in fullname like XRefRole does
+ fullname = ws_re.sub(' ', self.arguments[0].strip())
+ targetname = '%s-%s' % (self.name, fullname)
+ node = nodes.target('', '', ids=[targetname])
+ self.state.document.note_explicit_target(node)
+ ret = [node]
+ if self.indextemplate:
+ indexentry = self.indextemplate % (fullname,)
+ indextype = 'single'
+ colon = indexentry.find(':')
+ if colon != -1:
+ indextype = indexentry[:colon].strip()
+ indexentry = indexentry[colon+1:].strip()
+ inode = addnodes.index(entries=[(indextype, indexentry,
+ targetname, '')])
+ ret.insert(0, inode)
+ name = self.name
+ if ':' in self.name:
+ _, name = self.name.split(':', 1)
+ env.domaindata['std']['objects'][name, fullname] = \
+ env.docname, targetname
+ return ret
+
+
+class Cmdoption(ObjectDescription):
+ """
+ Description of a command-line option (.. option).
+ """
+
+ def handle_signature(self, sig, signode):
+ """Transform an option description into RST nodes."""
+ count = 0
+ firstname = ''
+ for potential_option in sig.split(', '):
+ potential_option = potential_option.strip()
+ m = option_desc_re.match(potential_option)
+ if not m:
+ self.env.warn(
+ self.env.docname,
+ 'Malformed option description %r, should '
+ 'look like "opt", "-opt args", "--opt args" or '
+ '"/opt args"' % potential_option, self.lineno)
+ continue
+ optname, args = m.groups()
+ if count:
+ signode += addnodes.desc_addname(', ', ', ')
+ signode += addnodes.desc_name(optname, optname)
+ signode += addnodes.desc_addname(args, args)
+ if not count:
+ firstname = optname
+ signode['allnames'] = [optname]
+ else:
+ signode['allnames'].append(optname)
+ count += 1
+ if not firstname:
+ raise ValueError
+ return firstname
+
+ def add_target_and_index(self, firstname, sig, signode):
+ currprogram = self.env.temp_data.get('std:program')
+ for optname in signode.get('allnames', []):
+ targetname = optname.replace('/', '-')
+ if not targetname.startswith('-'):
+ targetname = '-arg-' + targetname
+ if currprogram:
+ targetname = '-' + currprogram + targetname
+ targetname = 'cmdoption' + targetname
+ signode['ids'].append(targetname)
+ self.state.document.note_explicit_target(signode)
+ self.env.domaindata['std']['progoptions'][currprogram, optname] = \
+ self.env.docname, targetname
+ # create only one index entry for the whole option
+ if optname == firstname:
+ self.indexnode['entries'].append(
+ ('pair', _('%scommand line option; %s') %
+ ((currprogram and currprogram + ' ' or ''), sig),
+ targetname, ''))
+
+
+class Program(Directive):
+ """
+ Directive to name the program for which options are documented.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ program = ws_re.sub('-', self.arguments[0].strip())
+ if program == 'None':
+ env.temp_data['std:program'] = None
+ else:
+ env.temp_data['std:program'] = program
+ return []
+
+
+class OptionXRefRole(XRefRole):
+ innernodeclass = addnodes.literal_emphasis
+
+ def _split(self, text, refnode, env):
+ try:
+ program, target = re.split(' (?=-|--|/)', text, 1)
+ except ValueError:
+ env.warn_node('Malformed :option: %r, does not contain option '
+ 'marker - or -- or /' % text, refnode)
+ return None, text
+ else:
+ program = ws_re.sub('-', program)
+ return program, target
+
+ def process_link(self, env, refnode, has_explicit_title, title, target):
+ program = env.temp_data.get('std:program')
+ if not has_explicit_title:
+ if ' ' in title and not (title.startswith('/') or
+ title.startswith('-')):
+ program, target = self._split(title, refnode, env)
+ target = target.strip()
+ elif ' ' in target:
+ program, target = self._split(target, refnode, env)
+ refnode['refprogram'] = program
+ return title, target
+
+
+def make_termnodes_from_paragraph_node(env, node, new_id=None):
+ gloss_entries = env.temp_data.setdefault('gloss_entries', set())
+ objects = env.domaindata['std']['objects']
+
+ termtext = node.astext()
+ if new_id is None:
+ new_id = 'term-' + nodes.make_id(termtext)
+ if new_id in gloss_entries:
+ new_id = 'term-' + str(len(gloss_entries))
+ gloss_entries.add(new_id)
+ objects['term', termtext.lower()] = env.docname, new_id
+
+ # add an index entry too
+ indexnode = addnodes.index()
+ indexnode['entries'] = [('single', termtext, new_id, 'main')]
+ new_termnodes = []
+ new_termnodes.append(indexnode)
+ new_termnodes.extend(node.children)
+ new_termnodes.append(addnodes.termsep())
+ for termnode in new_termnodes:
+ termnode.source, termnode.line = node.source, node.line
+
+ return new_id, termtext, new_termnodes
+
+
+def make_term_from_paragraph_node(termnodes, ids):
+ # make a single "term" node with all the terms, separated by termsep
+ # nodes (remove the dangling trailing separator)
+ term = nodes.term('', '', *termnodes[:-1])
+ term.source, term.line = termnodes[0].source, termnodes[0].line
+ term.rawsource = term.astext()
+ term['ids'].extend(ids)
+ term['names'].extend(ids)
+ return term
+
+
+class Glossary(Directive):
+ """
+ Directive to create a glossary with cross-reference targets for :term:
+ roles.
+ """
+
+ has_content = True
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {
+ 'sorted': directives.flag,
+ }
+
+ def run(self):
+ env = self.state.document.settings.env
+ node = addnodes.glossary()
+ node.document = self.state.document
+
+ # This directive implements a custom format of the reST definition list
+ # that allows multiple lines of terms before the definition. This is
+ # easy to parse since we know that the contents of the glossary *must
+ # be* a definition list.
+
+ # first, collect single entries
+ entries = []
+ in_definition = True
+ was_empty = True
+ messages = []
+ for line, (source, lineno) in zip(self.content, self.content.items):
+ # empty line -> add to last definition
+ if not line:
+ if in_definition and entries:
+ entries[-1][1].append('', source, lineno)
+ was_empty = True
+ continue
+ # unindented line -> a term
+ if line and not line[0].isspace():
+ # enable comments
+ if line.startswith('.. '):
+ continue
+ # first term of definition
+ if in_definition:
+ if not was_empty:
+ messages.append(self.state.reporter.system_message(
+ 2, 'glossary term must be preceded by empty line',
+ source=source, line=lineno))
+ entries.append(([(line, source, lineno)], ViewList()))
+ in_definition = False
+ # second term and following
+ else:
+ if was_empty:
+ messages.append(self.state.reporter.system_message(
+ 2, 'glossary terms must not be separated by empty '
+ 'lines', source=source, line=lineno))
+ if entries:
+ entries[-1][0].append((line, source, lineno))
+ else:
+ messages.append(self.state.reporter.system_message(
+ 2, 'glossary seems to be misformatted, check '
+ 'indentation', source=source, line=lineno))
+ else:
+ if not in_definition:
+ # first line of definition, determines indentation
+ in_definition = True
+ indent_len = len(line) - len(line.lstrip())
+ if entries:
+ entries[-1][1].append(line[indent_len:], source, lineno)
+ else:
+ messages.append(self.state.reporter.system_message(
+ 2, 'glossary seems to be misformatted, check '
+ 'indentation', source=source, line=lineno))
+ was_empty = False
+
+ # now, parse all the entries into a big definition list
+ items = []
+ for terms, definition in entries:
+ termtexts = []
+ termnodes = []
+ system_messages = []
+ ids = []
+ for line, source, lineno in terms:
+ # parse the term with inline markup
+ res = self.state.inline_text(line, lineno)
+ system_messages.extend(res[1])
+
+ # get a text-only representation of the term and register it
+ # as a cross-reference target
+ tmp = nodes.paragraph('', '', *res[0])
+ tmp.source = source
+ tmp.line = lineno
+ new_id, termtext, new_termnodes = \
+ make_termnodes_from_paragraph_node(env, tmp)
+ ids.append(new_id)
+ termtexts.append(termtext)
+ termnodes.extend(new_termnodes)
+
+ term = make_term_from_paragraph_node(termnodes, ids)
+ term += system_messages
+
+ defnode = nodes.definition()
+ if definition:
+ self.state.nested_parse(definition, definition.items[0][1],
+ defnode)
+
+ items.append((termtexts,
+ nodes.definition_list_item('', term, defnode)))
+
+ if 'sorted' in self.options:
+ items.sort(key=lambda x:
+ unicodedata.normalize('NFD', x[0][0].lower()))
+
+ dlist = nodes.definition_list()
+ dlist['classes'].append('glossary')
+ dlist.extend(item[1] for item in items)
+ node += dlist
+ return messages + [node]
+
+
+token_re = re.compile('`(\w+)`', re.U)
+
+def token_xrefs(text):
+ retnodes = []
+ pos = 0
+ for m in token_re.finditer(text):
+ if m.start() > pos:
+ txt = text[pos:m.start()]
+ retnodes.append(nodes.Text(txt, txt))
+ refnode = addnodes.pending_xref(
+ m.group(1), reftype='token', refdomain='std', reftarget=m.group(1))
+ refnode += nodes.literal(m.group(1), m.group(1), classes=['xref'])
+ retnodes.append(refnode)
+ pos = m.end()
+ if pos < len(text):
+ retnodes.append(nodes.Text(text[pos:], text[pos:]))
+ return retnodes
+
+
+class ProductionList(Directive):
+ """
+ Directive to list grammar productions.
+ """
+
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ objects = env.domaindata['std']['objects']
+ node = addnodes.productionlist()
+ messages = []
+ i = 0
+
+ for rule in self.arguments[0].split('\n'):
+ if i == 0 and ':' not in rule:
+ # production group
+ continue
+ i += 1
+ try:
+ name, tokens = rule.split(':', 1)
+ except ValueError:
+ break
+ subnode = addnodes.production()
+ subnode['tokenname'] = name.strip()
+ if subnode['tokenname']:
+ idname = 'grammar-token-%s' % subnode['tokenname']
+ if idname not in self.state.document.ids:
+ subnode['ids'].append(idname)
+ self.state.document.note_implicit_target(subnode, subnode)
+ objects['token', subnode['tokenname']] = env.docname, idname
+ subnode.extend(token_xrefs(tokens))
+ node.append(subnode)
+ return [node] + messages
+
+
+class StandardDomain(Domain):
+ """
+ Domain for all objects that don't fit into another domain or are added
+ via the application interface.
+ """
+
+ name = 'std'
+ label = 'Default'
+
+ object_types = {
+ 'term': ObjType(l_('glossary term'), 'term', searchprio=-1),
+ 'token': ObjType(l_('grammar token'), 'token', searchprio=-1),
+ 'label': ObjType(l_('reference label'), 'ref', 'keyword',
+ searchprio=-1),
+ 'envvar': ObjType(l_('environment variable'), 'envvar'),
+ 'cmdoption': ObjType(l_('program option'), 'option'),
+ }
+
+ directives = {
+ 'program': Program,
+ 'cmdoption': Cmdoption, # old name for backwards compatibility
+ 'option': Cmdoption,
+ 'envvar': EnvVar,
+ 'glossary': Glossary,
+ 'productionlist': ProductionList,
+ }
+ roles = {
+ 'option': OptionXRefRole(innernodeclass=addnodes.literal_emphasis),
+ 'envvar': EnvVarXRefRole(),
+ # links to tokens in grammar productions
+ 'token': XRefRole(),
+ # links to terms in glossary
+ 'term': XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
+ warn_dangling=True),
+ # links to headings or arbitrary labels
+ 'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
+ warn_dangling=True),
+ # links to labels, without a different title
+ 'keyword': XRefRole(warn_dangling=True),
+ }
+
+ initial_data = {
+ 'progoptions': {}, # (program, name) -> docname, labelid
+ 'objects': {}, # (type, name) -> docname, labelid
+ 'labels': { # labelname -> docname, labelid, sectionname
+ 'genindex': ('genindex', '', l_('Index')),
+ 'modindex': ('py-modindex', '', l_('Module Index')),
+ 'search': ('search', '', l_('Search Page')),
+ },
+ 'anonlabels': { # labelname -> docname, labelid
+ 'genindex': ('genindex', ''),
+ 'modindex': ('py-modindex', ''),
+ 'search': ('search', ''),
+ },
+ }
+
+ dangling_warnings = {
+ 'term': 'term not in glossary: %(target)s',
+ 'ref': 'undefined label: %(target)s (if the link has no caption '
+ 'the label must precede a section header)',
+ 'keyword': 'unknown keyword: %(target)s',
+ }
+
+ def clear_doc(self, docname):
+ for key, (fn, _) in self.data['progoptions'].items():
+ if fn == docname:
+ del self.data['progoptions'][key]
+ for key, (fn, _) in self.data['objects'].items():
+ if fn == docname:
+ del self.data['objects'][key]
+ for key, (fn, _, _) in self.data['labels'].items():
+ if fn == docname:
+ del self.data['labels'][key]
+ for key, (fn, _) in self.data['anonlabels'].items():
+ if fn == docname:
+ del self.data['anonlabels'][key]
+
+ def process_doc(self, env, docname, document):
+ labels, anonlabels = self.data['labels'], self.data['anonlabels']
+ for name, explicit in document.nametypes.iteritems():
+ if not explicit:
+ continue
+ labelid = document.nameids[name]
+ if labelid is None:
+ continue
+ node = document.ids[labelid]
+ if name.isdigit() or node.has_key('refuri') or \
+ node.tagname.startswith('desc_'):
+ # ignore footnote labels, labels automatically generated from a
+ # link and object descriptions
+ continue
+ if name in labels:
+ env.warn_node('duplicate label %s, ' % name + 'other instance '
+ 'in ' + env.doc2path(labels[name][0]), node)
+ anonlabels[name] = docname, labelid
+ if node.tagname == 'section':
+ sectname = clean_astext(node[0]) # node[0] == title node
+ elif node.tagname == 'figure':
+ for n in node:
+ if n.tagname == 'caption':
+ sectname = clean_astext(n)
+ break
+ else:
+ continue
+ elif node.tagname == 'table':
+ for n in node:
+ if n.tagname == 'title':
+ sectname = clean_astext(n)
+ break
+ else:
+ continue
+ else:
+ # anonymous-only labels
+ continue
+ labels[name] = docname, labelid, sectname
+
+ def resolve_xref(self, env, fromdocname, builder,
+ typ, target, node, contnode):
+ if typ == 'ref':
+ if node['refexplicit']:
+ # reference to anonymous label; the reference uses
+ # the supplied link caption
+ docname, labelid = self.data['anonlabels'].get(target, ('',''))
+ sectname = node.astext()
+ else:
+ # reference to named label; the final node will
+ # contain the section name after the label
+ docname, labelid, sectname = self.data['labels'].get(target,
+ ('','',''))
+ if not docname:
+ return None
+ newnode = nodes.reference('', '', internal=True)
+ innernode = nodes.emphasis(sectname, sectname)
+ if docname == fromdocname:
+ newnode['refid'] = labelid
+ else:
+ # set more info in contnode; in case the
+ # get_relative_uri call raises NoUri,
+ # the builder will then have to resolve these
+ contnode = addnodes.pending_xref('')
+ contnode['refdocname'] = docname
+ contnode['refsectname'] = sectname
+ newnode['refuri'] = builder.get_relative_uri(
+ fromdocname, docname)
+ if labelid:
+ newnode['refuri'] += '#' + labelid
+ newnode.append(innernode)
+ return newnode
+ elif typ == 'keyword':
+ # keywords are oddballs: they are referenced by named labels
+ docname, labelid, _ = self.data['labels'].get(target, ('','',''))
+ if not docname:
+ return None
+ return make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
+ elif typ == 'option':
+ progname = node['refprogram']
+ docname, labelid = self.data['progoptions'].get((progname, target),
+ ('', ''))
+ if not docname:
+ return None
+ return make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
+ else:
+ objtypes = self.objtypes_for_role(typ) or []
+ for objtype in objtypes:
+ if (objtype, target) in self.data['objects']:
+ docname, labelid = self.data['objects'][objtype, target]
+ break
+ else:
+ docname, labelid = '', ''
+ if not docname:
+ return None
+ return make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
+
+ def get_objects(self):
+ for (prog, option), info in self.data['progoptions'].iteritems():
+ yield (option, option, 'option', info[0], info[1], 1)
+ for (type, name), info in self.data['objects'].iteritems():
+ yield (name, name, type, info[0], info[1],
+ self.object_types[type].attrs['searchprio'])
+ for name, info in self.data['labels'].iteritems():
+ yield (name, info[2], 'label', info[0], info[1], -1)
+ # add anonymous-only labels as well
+ non_anon_labels = set(self.data['labels'])
+ for name, info in self.data['anonlabels'].iteritems():
+ if name not in non_anon_labels:
+ yield (name, name, 'label', info[0], info[1], -1)
+
+ def get_type_name(self, type, primary=False):
+ # never prepend "Default"
+ return type.lname
diff --git a/sphinx/environment.py b/sphinx/environment.py
new file mode 100644
index 0000000..69a8b57
--- /dev/null
+++ b/sphinx/environment.py
@@ -0,0 +1,1677 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.environment
+ ~~~~~~~~~~~~~~~~~~
+
+ Global creation environment.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import os
+import sys
+import time
+import types
+import codecs
+import imghdr
+import string
+import unicodedata
+import cPickle as pickle
+from os import path
+from glob import glob
+from itertools import izip, groupby
+
+from docutils import nodes
+from docutils.io import FileInput, NullOutput
+from docutils.core import Publisher
+from docutils.utils import Reporter, relative_path, get_source_line
+from docutils.readers import standalone
+from docutils.parsers.rst import roles, directives
+from docutils.parsers.rst.languages import en as english
+from docutils.parsers.rst.directives.html import MetaBody
+from docutils.writers import UnfilteredWriter
+
+from sphinx import addnodes
+from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \
+ FilenameUniqDict
+from sphinx.util.nodes import clean_astext, make_refnode, WarningStream
+from sphinx.util.osutil import SEP, fs_encoding, find_catalog_files
+from sphinx.util.matching import compile_matchers
+from sphinx.util.pycompat import class_types
+from sphinx.util.compat import docutils_version
+from sphinx.util.websupport import is_commentable
+from sphinx.errors import SphinxError, ExtensionError
+from sphinx.locale import _
+from sphinx.versioning import add_uids, merge_doctrees
+from sphinx.transforms import DefaultSubstitutions, MoveModuleTargets, \
+ HandleCodeBlocks, SortIds, CitationReferences, Locale, \
+ RemoveTranslatableInline, SphinxContentsFilter
+
+
+orig_role_function = roles.role
+orig_directive_function = directives.directive
+
+class ElementLookupError(Exception): pass
+
+
+default_settings = {
+ 'embed_stylesheet': False,
+ 'cloak_email_addresses': True,
+ 'pep_base_url': 'http://www.python.org/dev/peps/',
+ 'rfc_base_url': 'http://tools.ietf.org/html/',
+ 'input_encoding': 'utf-8-sig',
+ 'doctitle_xform': False,
+ 'sectsubtitle_xform': False,
+ 'halt_level': 5,
+ 'file_insertion_enabled': True,
+}
+
+# This is increased every time an environment attribute is added
+# or changed to properly invalidate pickle files.
+ENV_VERSION = 42 + (sys.version_info[0] - 2)
+
+
+dummy_reporter = Reporter('', 4, 4)
+
+versioning_conditions = {
+ 'none': False,
+ 'text': nodes.TextElement,
+ 'commentable': is_commentable,
+}
+
+
+class NoUri(Exception):
+ """Raised by get_relative_uri if there is no URI available."""
+ pass
+
+
+class SphinxStandaloneReader(standalone.Reader):
+ """
+ Add our own transforms.
+ """
+ transforms = [Locale, CitationReferences, DefaultSubstitutions,
+ MoveModuleTargets, HandleCodeBlocks, SortIds,
+ RemoveTranslatableInline]
+
+ def get_transforms(self):
+ return standalone.Reader.get_transforms(self) + self.transforms
+
+
+class SphinxDummyWriter(UnfilteredWriter):
+ supported = ('html',) # needed to keep "meta" nodes
+
+ def translate(self):
+ pass
+
+
+class BuildEnvironment:
+ """
+ The environment in which the ReST files are translated.
+ Stores an inventory of cross-file targets and provides doctree
+ transformations to resolve links to them.
+ """
+
+ # --------- ENVIRONMENT PERSISTENCE ----------------------------------------
+
+ @staticmethod
+ def frompickle(config, filename):
+ picklefile = open(filename, 'rb')
+ try:
+ env = pickle.load(picklefile)
+ finally:
+ picklefile.close()
+ if env.version != ENV_VERSION:
+ raise IOError('env version not current')
+ env.config.values = config.values
+ return env
+
+ def topickle(self, filename):
+ # remove unpicklable attributes
+ warnfunc = self._warnfunc
+ self.set_warnfunc(None)
+ values = self.config.values
+ del self.config.values
+ domains = self.domains
+ del self.domains
+ picklefile = open(filename, 'wb')
+ # remove potentially pickling-problematic values from config
+ for key, val in vars(self.config).items():
+ if key.startswith('_') or \
+ isinstance(val, types.ModuleType) or \
+ isinstance(val, types.FunctionType) or \
+ isinstance(val, class_types):
+ del self.config[key]
+ try:
+ pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL)
+ finally:
+ picklefile.close()
+ # reset attributes
+ self.domains = domains
+ self.config.values = values
+ self.set_warnfunc(warnfunc)
+
+ # --------- ENVIRONMENT INITIALIZATION -------------------------------------
+
+ def __init__(self, srcdir, doctreedir, config):
+ self.doctreedir = doctreedir
+ self.srcdir = srcdir
+ self.config = config
+
+ # the method of doctree versioning; see set_versioning_method
+ self.versioning_condition = None
+
+ # the application object; only set while update() runs
+ self.app = None
+
+ # all the registered domains, set by the application
+ self.domains = {}
+
+ # the docutils settings for building
+ self.settings = default_settings.copy()
+ self.settings['env'] = self
+
+ # the function to write warning messages with
+ self._warnfunc = None
+
+ # this is to invalidate old pickles
+ self.version = ENV_VERSION
+
+ # All "docnames" here are /-separated and relative and exclude
+ # the source suffix.
+
+ self.found_docs = set() # contains all existing docnames
+ self.all_docs = {} # docname -> mtime at the time of build
+ # contains all built docnames
+ self.dependencies = {} # docname -> set of dependent file
+ # names, relative to documentation root
+ self.reread_always = set() # docnames to re-read unconditionally on
+ # next build
+
+ # File metadata
+ self.metadata = {} # docname -> dict of metadata items
+
+ # TOC inventory
+ self.titles = {} # docname -> title node
+ self.longtitles = {} # docname -> title node; only different if
+ # set differently with title directive
+ self.tocs = {} # docname -> table of contents nodetree
+ self.toc_num_entries = {} # docname -> number of real entries
+ # used to determine when to show the TOC
+ # in a sidebar (don't show if it's only one item)
+ self.toc_secnumbers = {} # docname -> dict of sectionid -> number
+
+ self.toctree_includes = {} # docname -> list of toctree includefiles
+ self.files_to_rebuild = {} # docname -> set of files
+ # (containing its TOCs) to rebuild too
+ self.glob_toctrees = set() # docnames that have :glob: toctrees
+ self.numbered_toctrees = set() # docnames that have :numbered: toctrees
+
+ # domain-specific inventories, here to be pickled
+ self.domaindata = {} # domainname -> domain-specific dict
+
+ # Other inventories
+ self.citations = {} # citation name -> docname, labelid
+ self.indexentries = {} # docname -> list of
+ # (type, string, target, aliasname)
+ self.versionchanges = {} # version -> list of (type, docname,
+ # lineno, module, descname, content)
+
+ # these map absolute path -> (docnames, unique filename)
+ self.images = FilenameUniqDict()
+ self.dlfiles = FilenameUniqDict()
+
+ # temporary data storage while reading a document
+ self.temp_data = {}
+
+ def set_warnfunc(self, func):
+ self._warnfunc = func
+ self.settings['warning_stream'] = WarningStream(func)
+
+ def set_versioning_method(self, method):
+ """This sets the doctree versioning method for this environment.
+
+ Versioning methods are a builder property; only builders with the same
+ versioning method can share the same doctree directory. Therefore, we
+ raise an exception if the user tries to use an environment with an
+ incompatible versioning method.
+ """
+ if method not in versioning_conditions:
+ raise ValueError('invalid versioning method: %r' % method)
+ condition = versioning_conditions[method]
+ if self.versioning_condition not in (None, condition):
+ raise SphinxError('This environment is incompatible with the '
+ 'selected builder, please choose another '
+ 'doctree directory.')
+ self.versioning_condition = condition
+
+ def warn(self, docname, msg, lineno=None):
+ """Emit a warning.
+
+ This differs from using ``app.warn()`` in that the warning may not
+ be emitted instantly, but collected for emitting all warnings after
+ the update of the environment.
+ """
+ # strange argument order is due to backwards compatibility
+ self._warnfunc(msg, (docname, lineno))
+
+ def warn_node(self, msg, node):
+ """Like :meth:`warn`, but with source information taken from *node*."""
+ self._warnfunc(msg, '%s:%s' % get_source_line(node))
+
+ def clear_doc(self, docname):
+ """Remove all traces of a source file in the inventory."""
+ if docname in self.all_docs:
+ self.all_docs.pop(docname, None)
+ self.reread_always.discard(docname)
+ self.metadata.pop(docname, None)
+ self.dependencies.pop(docname, None)
+ self.titles.pop(docname, None)
+ self.longtitles.pop(docname, None)
+ self.tocs.pop(docname, None)
+ self.toc_secnumbers.pop(docname, None)
+ self.toc_num_entries.pop(docname, None)
+ self.toctree_includes.pop(docname, None)
+ self.indexentries.pop(docname, None)
+ self.glob_toctrees.discard(docname)
+ self.numbered_toctrees.discard(docname)
+ self.images.purge_doc(docname)
+ self.dlfiles.purge_doc(docname)
+
+ for subfn, fnset in self.files_to_rebuild.items():
+ fnset.discard(docname)
+ if not fnset:
+ del self.files_to_rebuild[subfn]
+ for key, (fn, _) in self.citations.items():
+ if fn == docname:
+ del self.citations[key]
+ for version, changes in self.versionchanges.items():
+ new = [change for change in changes if change[1] != docname]
+ changes[:] = new
+
+ for domain in self.domains.values():
+ domain.clear_doc(docname)
+
+ def doc2path(self, docname, base=True, suffix=None):
+ """Return the filename for the document name.
+
+ If *base* is True, return absolute path under self.srcdir.
+ If *base* is None, return relative path to self.srcdir.
+ If *base* is a path string, return absolute path under that.
+ If *suffix* is not None, add it instead of config.source_suffix.
+ """
+ docname = docname.replace(SEP, path.sep)
+ suffix = suffix or self.config.source_suffix
+ if base is True:
+ return path.join(self.srcdir, docname) + suffix
+ elif base is None:
+ return docname + suffix
+ else:
+ return path.join(base, docname) + suffix
+
+ def relfn2path(self, filename, docname=None):
+ """Return paths to a file referenced from a document, relative to
+ documentation root and absolute.
+
+ In the input "filename", absolute filenames are taken as relative to the
+ source dir, while relative filenames are relative to the dir of the
+ containing document.
+ """
+ if filename.startswith('/') or filename.startswith(os.sep):
+ rel_fn = filename[1:]
+ else:
+ docdir = path.dirname(self.doc2path(docname or self.docname,
+ base=None))
+ rel_fn = path.join(docdir, filename)
+ try:
+ # the path.abspath() might seem redundant, but otherwise artifacts
+ # such as ".." will remain in the path
+ return rel_fn, path.abspath(path.join(self.srcdir, rel_fn))
+ except UnicodeDecodeError:
+ # the source directory is a bytestring with non-ASCII characters;
+ # let's try to encode the rel_fn in the file system encoding
+ enc_rel_fn = rel_fn.encode(sys.getfilesystemencoding())
+ return rel_fn, path.abspath(path.join(self.srcdir, enc_rel_fn))
+
+ def find_files(self, config):
+ """Find all source files in the source dir and put them in
+ self.found_docs.
+ """
+ matchers = compile_matchers(
+ config.exclude_patterns[:] +
+ config.html_extra_path +
+ config.exclude_trees +
+ [d + config.source_suffix for d in config.unused_docs] +
+ ['**/' + d for d in config.exclude_dirnames] +
+ ['**/_sources', '.#*']
+ )
+ self.found_docs = set(get_matching_docs(
+ self.srcdir, config.source_suffix, exclude_matchers=matchers))
+
+ # add catalog mo file dependency
+ for docname in self.found_docs:
+ catalog_files = find_catalog_files(
+ docname,
+ self.srcdir,
+ self.config.locale_dirs,
+ self.config.language,
+ self.config.gettext_compact)
+ for filename in catalog_files:
+ self.dependencies.setdefault(docname, set()).add(filename)
+
+ def get_outdated_files(self, config_changed):
+ """Return (added, changed, removed) sets."""
+ # clear all files no longer present
+ removed = set(self.all_docs) - self.found_docs
+
+ added = set()
+ changed = set()
+
+ if config_changed:
+ # config values affect e.g. substitutions
+ added = self.found_docs
+ else:
+ for docname in self.found_docs:
+ if docname not in self.all_docs:
+ added.add(docname)
+ continue
+ # if the doctree file is not there, rebuild
+ if not path.isfile(self.doc2path(docname, self.doctreedir,
+ '.doctree')):
+ changed.add(docname)
+ continue
+ # check the "reread always" list
+ if docname in self.reread_always:
+ changed.add(docname)
+ continue
+ # check the mtime of the document
+ mtime = self.all_docs[docname]
+ newmtime = path.getmtime(self.doc2path(docname))
+ if newmtime > mtime:
+ changed.add(docname)
+ continue
+ # finally, check the mtime of dependencies
+ for dep in self.dependencies.get(docname, ()):
+ try:
+ # this will do the right thing when dep is absolute too
+ deppath = path.join(self.srcdir, dep)
+ if not path.isfile(deppath):
+ changed.add(docname)
+ break
+ depmtime = path.getmtime(deppath)
+ if depmtime > mtime:
+ changed.add(docname)
+ break
+ except EnvironmentError:
+ # give it another chance
+ changed.add(docname)
+ break
+
+ return added, changed, removed
+
+ def update(self, config, srcdir, doctreedir, app=None):
+ """(Re-)read all files new or changed since last update.
+
+ Returns a summary, the total count of documents to reread and an
+ iterator that yields docnames as it processes them. Store all
+ environment docnames in the canonical format (ie using SEP as a
+ separator in place of os.path.sep).
+ """
+ config_changed = False
+ if self.config is None:
+ msg = '[new config] '
+ config_changed = True
+ else:
+ # check if a config value was changed that affects how
+ # doctrees are read
+ for key, descr in config.values.iteritems():
+ if descr[1] != 'env':
+ continue
+ if self.config[key] != config[key]:
+ msg = '[config changed] '
+ config_changed = True
+ break
+ else:
+ msg = ''
+ # this value is not covered by the above loop because it is handled
+ # specially by the config class
+ if self.config.extensions != config.extensions:
+ msg = '[extensions changed] '
+ config_changed = True
+ # the source and doctree directories may have been relocated
+ self.srcdir = srcdir
+ self.doctreedir = doctreedir
+ self.find_files(config)
+ self.config = config
+
+ # this cache also needs to be updated every time
+ self._nitpick_ignore = set(self.config.nitpick_ignore)
+
+ added, changed, removed = self.get_outdated_files(config_changed)
+
+ # allow user intervention as well
+ for docs in app.emit('env-get-outdated', self, added, changed, removed):
+ changed.update(set(docs) & self.found_docs)
+
+ # if files were added or removed, all documents with globbed toctrees
+ # must be reread
+ if added or removed:
+ # ... but not those that already were removed
+ changed.update(self.glob_toctrees & self.found_docs)
+
+ msg += '%s added, %s changed, %s removed' % (len(added), len(changed),
+ len(removed))
+
+ def update_generator():
+ self.app = app
+
+ # clear all files no longer present
+ for docname in removed:
+ if app:
+ app.emit('env-purge-doc', self, docname)
+ self.clear_doc(docname)
+
+ # read all new and changed files
+ for docname in sorted(added | changed):
+ yield docname
+ self.read_doc(docname, app=app)
+
+ if config.master_doc not in self.all_docs:
+ self.warn(None, 'master file %s not found' %
+ self.doc2path(config.master_doc))
+
+ self.app = None
+ if app:
+ app.emit('env-updated', self)
+
+ return msg, len(added | changed), update_generator()
+
+ def check_dependents(self, already):
+ to_rewrite = self.assign_section_numbers()
+ for docname in to_rewrite:
+ if docname not in already:
+ yield docname
+
+ # --------- SINGLE FILE READING --------------------------------------------
+
+ def warn_and_replace(self, error):
+ """Custom decoding error handler that warns and replaces."""
+ linestart = error.object.rfind('\n', 0, error.start)
+ lineend = error.object.find('\n', error.start)
+ if lineend == -1: lineend = len(error.object)
+ lineno = error.object.count('\n', 0, error.start) + 1
+ self.warn(self.docname, 'undecodable source characters, '
+ 'replacing with "?": %r' %
+ (error.object[linestart+1:error.start] + '>>>' +
+ error.object[error.start:error.end] + '<<<' +
+ error.object[error.end:lineend]), lineno)
+ return (u'?', error.end)
+
+ def lookup_domain_element(self, type, name):
+ """Lookup a markup element (directive or role), given its name which can
+ be a full name (with domain).
+ """
+ name = name.lower()
+ # explicit domain given?
+ if ':' in name:
+ domain_name, name = name.split(':', 1)
+ if domain_name in self.domains:
+ domain = self.domains[domain_name]
+ element = getattr(domain, type)(name)
+ if element is not None:
+ return element, []
+ # else look in the default domain
+ else:
+ def_domain = self.temp_data.get('default_domain')
+ if def_domain is not None:
+ element = getattr(def_domain, type)(name)
+ if element is not None:
+ return element, []
+ # always look in the std domain
+ element = getattr(self.domains['std'], type)(name)
+ if element is not None:
+ return element, []
+ raise ElementLookupError
+
+ def patch_lookup_functions(self):
+ """Monkey-patch directive and role dispatch, so that domain-specific
+ markup takes precedence.
+ """
+ def directive(name, lang_module, document):
+ try:
+ return self.lookup_domain_element('directive', name)
+ except ElementLookupError:
+ return orig_directive_function(name, lang_module, document)
+
+ def role(name, lang_module, lineno, reporter):
+ try:
+ return self.lookup_domain_element('role', name)
+ except ElementLookupError:
+ return orig_role_function(name, lang_module, lineno, reporter)
+
+ directives.directive = directive
+ roles.role = role
+
+ def read_doc(self, docname, src_path=None, save_parsed=True, app=None):
+ """Parse a file and add/update inventory entries for the doctree.
+
+ If srcpath is given, read from a different source file.
+ """
+ # remove all inventory entries for that file
+ if app:
+ app.emit('env-purge-doc', self, docname)
+
+ self.clear_doc(docname)
+
+ if src_path is None:
+ src_path = self.doc2path(docname)
+
+ self.temp_data['docname'] = docname
+ # defaults to the global default, but can be re-set in a document
+ self.temp_data['default_domain'] = \
+ self.domains.get(self.config.primary_domain)
+
+ self.settings['input_encoding'] = self.config.source_encoding
+ self.settings['trim_footnote_reference_space'] = \
+ self.config.trim_footnote_reference_space
+ self.settings['gettext_compact'] = self.config.gettext_compact
+
+ self.patch_lookup_functions()
+
+ if self.config.default_role:
+ role_fn, messages = roles.role(self.config.default_role, english,
+ 0, dummy_reporter)
+ if role_fn:
+ roles._roles[''] = role_fn
+ else:
+ self.warn(docname, 'default role %s not found' %
+ self.config.default_role)
+
+ codecs.register_error('sphinx', self.warn_and_replace)
+
+ class SphinxSourceClass(FileInput):
+ def __init__(self_, *args, **kwds):
+ # don't call sys.exit() on IOErrors
+ kwds['handle_io_errors'] = False
+ FileInput.__init__(self_, *args, **kwds)
+
+ def decode(self_, data):
+ if isinstance(data, unicode):
+ return data
+ return data.decode(self_.encoding, 'sphinx')
+
+ def read(self_):
+ data = FileInput.read(self_)
+ if app:
+ arg = [data]
+ app.emit('source-read', docname, arg)
+ data = arg[0]
+ if self.config.rst_epilog:
+ data = data + '\n' + self.config.rst_epilog + '\n'
+ if self.config.rst_prolog:
+ data = self.config.rst_prolog + '\n' + data
+ return data
+
+ # publish manually
+ pub = Publisher(reader=SphinxStandaloneReader(),
+ writer=SphinxDummyWriter(),
+ source_class=SphinxSourceClass,
+ destination_class=NullOutput)
+ pub.set_components(None, 'restructuredtext', None)
+ pub.process_programmatic_settings(None, self.settings, None)
+ if docutils_version < (0, 8): #1531
+ pub.set_source(None, src_path.encode(fs_encoding))
+ else:
+ pub.set_source(None, src_path)
+ pub.set_destination(None, None)
+ pub.publish()
+ doctree = pub.document
+
+ # post-processing
+ self.filter_messages(doctree)
+ self.process_dependencies(docname, doctree)
+ self.process_images(docname, doctree)
+ self.process_downloads(docname, doctree)
+ self.process_metadata(docname, doctree)
+ self.process_refonly_bullet_lists(docname, doctree)
+ self.create_title_from(docname, doctree)
+ self.note_indexentries_from(docname, doctree)
+ self.note_citations_from(docname, doctree)
+ self.build_toc_from(docname, doctree)
+ for domain in self.domains.itervalues():
+ domain.process_doc(self, docname, doctree)
+
+ # allow extension-specific post-processing
+ if app:
+ app.emit('doctree-read', doctree)
+
+ # store time of build, for outdated files detection
+ # (Some filesystems have coarse timestamp resolution;
+ # therefore time.time() can be older than filesystem's timestamp.
+ # For example, FAT32 has 2sec timestamp resolution.)
+ self.all_docs[docname] = max(
+ time.time(), path.getmtime(self.doc2path(docname)))
+
+ if self.versioning_condition:
+ # get old doctree
+ try:
+ f = open(self.doc2path(docname,
+ self.doctreedir, '.doctree'), 'rb')
+ try:
+ old_doctree = pickle.load(f)
+ finally:
+ f.close()
+ except EnvironmentError:
+ old_doctree = None
+
+ # add uids for versioning
+ if old_doctree is None:
+ list(add_uids(doctree, self.versioning_condition))
+ else:
+ list(merge_doctrees(
+ old_doctree, doctree, self.versioning_condition))
+
+ # make it picklable
+ doctree.reporter = None
+ doctree.transformer = None
+ doctree.settings.warning_stream = None
+ doctree.settings.env = None
+ doctree.settings.record_dependencies = None
+ for metanode in doctree.traverse(MetaBody.meta):
+ # docutils' meta nodes aren't picklable because the class is nested
+ metanode.__class__ = addnodes.meta
+
+ # cleanup
+ self.temp_data.clear()
+
+ if save_parsed:
+ # save the parsed doctree
+ doctree_filename = self.doc2path(docname, self.doctreedir,
+ '.doctree')
+ dirname = path.dirname(doctree_filename)
+ if not path.isdir(dirname):
+ os.makedirs(dirname)
+ f = open(doctree_filename, 'wb')
+ try:
+ pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
+ finally:
+ f.close()
+ else:
+ return doctree
+
+ # utilities to use while reading a document
+
+ @property
+ def docname(self):
+ """Returns the docname of the document currently being parsed."""
+ return self.temp_data['docname']
+
+ @property
+ def currmodule(self):
+ """Backwards compatible alias."""
+ return self.temp_data.get('py:module')
+
+ @property
+ def currclass(self):
+ """Backwards compatible alias."""
+ return self.temp_data.get('py:class')
+
+ def new_serialno(self, category=''):
+ """Return a serial number, e.g. for index entry targets.
+
+ The number is guaranteed to be unique in the current document.
+ """
+ key = category + 'serialno'
+ cur = self.temp_data.get(key, 0)
+ self.temp_data[key] = cur + 1
+ return cur
+
+ def note_dependency(self, filename):
+ """Add *filename* as a dependency of the current document.
+
+ This means that the document will be rebuilt if this file changes.
+
+ *filename* should be absolute or relative to the source directory.
+ """
+ self.dependencies.setdefault(self.docname, set()).add(filename)
+
+ def note_reread(self):
+ """Add the current document to the list of documents that will
+ automatically be re-read at the next build.
+ """
+ self.reread_always.add(self.docname)
+
+ def note_versionchange(self, type, version, node, lineno):
+ self.versionchanges.setdefault(version, []).append(
+ (type, self.temp_data['docname'], lineno,
+ self.temp_data.get('py:module'),
+ self.temp_data.get('object'), node.astext()))
+
+ # post-processing of read doctrees
+
+ def filter_messages(self, doctree):
+ """Filter system messages from a doctree."""
+ filterlevel = self.config.keep_warnings and 2 or 5
+ for node in doctree.traverse(nodes.system_message):
+ if node['level'] < filterlevel:
+ self.app.debug('%s [filtered system message]', node.astext())
+ node.parent.remove(node)
+
+ def process_dependencies(self, docname, doctree):
+ """Process docutils-generated dependency info."""
+ cwd = os.getcwd()
+ frompath = path.join(path.normpath(self.srcdir), 'dummy')
+ deps = doctree.settings.record_dependencies
+ if not deps:
+ return
+ for dep in deps.list:
+ # the dependency path is relative to the working dir, so get
+ # one relative to the srcdir
+ relpath = relative_path(frompath,
+ path.normpath(path.join(cwd, dep)))
+ self.dependencies.setdefault(docname, set()).add(relpath)
+
+ def process_downloads(self, docname, doctree):
+ """Process downloadable file paths. """
+ for node in doctree.traverse(addnodes.download_reference):
+ targetname = node['reftarget']
+ rel_filename, filename = self.relfn2path(targetname, docname)
+ self.dependencies.setdefault(docname, set()).add(rel_filename)
+ if not os.access(filename, os.R_OK):
+ self.warn_node('download file not readable: %s' % filename,
+ node)
+ continue
+ uniquename = self.dlfiles.add_file(docname, filename)
+ node['filename'] = uniquename
+
+ def process_images(self, docname, doctree):
+ """Process and rewrite image URIs."""
+ for node in doctree.traverse(nodes.image):
+ # Map the mimetype to the corresponding image. The writer may
+ # choose the best image from these candidates. The special key * is
+ # set if there is only single candidate to be used by a writer.
+ # The special key ? is set for nonlocal URIs.
+ node['candidates'] = candidates = {}
+ imguri = node['uri']
+ if imguri.find('://') != -1:
+ self.warn_node('nonlocal image URI found: %s' % imguri, node)
+ candidates['?'] = imguri
+ continue
+ rel_imgpath, full_imgpath = self.relfn2path(imguri, docname)
+ # set imgpath as default URI
+ node['uri'] = rel_imgpath
+ if rel_imgpath.endswith(os.extsep + '*'):
+ for filename in glob(full_imgpath):
+ new_imgpath = relative_path(path.join(self.srcdir, 'dummy'),
+ filename)
+ if filename.lower().endswith('.pdf'):
+ candidates['application/pdf'] = new_imgpath
+ elif filename.lower().endswith('.svg'):
+ candidates['image/svg+xml'] = new_imgpath
+ else:
+ try:
+ f = open(filename, 'rb')
+ try:
+ imgtype = imghdr.what(f)
+ finally:
+ f.close()
+ except (OSError, IOError), err:
+ self.warn_node('image file %s not readable: %s' %
+ (filename, err), node)
+ if imgtype:
+ candidates['image/' + imgtype] = new_imgpath
+ else:
+ candidates['*'] = rel_imgpath
+ # map image paths to unique image names (so that they can be put
+ # into a single directory)
+ for imgpath in candidates.itervalues():
+ self.dependencies.setdefault(docname, set()).add(imgpath)
+ if not os.access(path.join(self.srcdir, imgpath), os.R_OK):
+ self.warn_node('image file not readable: %s' % imgpath,
+ node)
+ continue
+ self.images.add_file(docname, imgpath)
+
+ def process_metadata(self, docname, doctree):
+ """Process the docinfo part of the doctree as metadata.
+
+ Keep processing minimal -- just return what docutils says.
+ """
+ self.metadata[docname] = md = {}
+ try:
+ docinfo = doctree[0]
+ except IndexError:
+ # probably an empty document
+ return
+ if docinfo.__class__ is not nodes.docinfo:
+ # nothing to see here
+ return
+ for node in docinfo:
+ # nodes are multiply inherited...
+ if isinstance(node, nodes.authors):
+ md['authors'] = [author.astext() for author in node]
+ elif isinstance(node, nodes.TextElement): # e.g. author
+ md[node.__class__.__name__] = node.astext()
+ else:
+ name, body = node
+ md[name.astext()] = body.astext()
+ del doctree[0]
+
+ def process_refonly_bullet_lists(self, docname, doctree):
+ """Change refonly bullet lists to use compact_paragraphs.
+
+ Specifically implemented for 'Indices and Tables' section, which looks
+ odd when html_compact_lists is false.
+ """
+ if self.config.html_compact_lists:
+ return
+
+ class RefOnlyListChecker(nodes.GenericNodeVisitor):
+ """Raise `nodes.NodeFound` if non-simple list item is encountered.
+
+ Here 'simple' means a list item containing only a paragraph with a
+ single reference in it.
+ """
+
+ def default_visit(self, node):
+ raise nodes.NodeFound
+
+ def visit_bullet_list(self, node):
+ pass
+
+ def visit_list_item(self, node):
+ children = []
+ for child in node.children:
+ if not isinstance(child, nodes.Invisible):
+ children.append(child)
+ if len(children) != 1:
+ raise nodes.NodeFound
+ if not isinstance(children[0], nodes.paragraph):
+ raise nodes.NodeFound
+ para = children[0]
+ if len(para) != 1:
+ raise nodes.NodeFound
+ if not isinstance(para[0], addnodes.pending_xref):
+ raise nodes.NodeFound
+ raise nodes.SkipChildren
+
+ def invisible_visit(self, node):
+ """Invisible nodes should be ignored."""
+ pass
+
+ def check_refonly_list(node):
+ """Check for list with only references in it."""
+ visitor = RefOnlyListChecker(doctree)
+ try:
+ node.walk(visitor)
+ except nodes.NodeFound:
+ return False
+ else:
+ return True
+
+ for node in doctree.traverse(nodes.bullet_list):
+ if check_refonly_list(node):
+ for item in node.traverse(nodes.list_item):
+ para = item[0]
+ ref = para[0]
+ compact_para = addnodes.compact_paragraph()
+ compact_para += ref
+ item.replace(para, compact_para)
+
+ def create_title_from(self, docname, document):
+ """Add a title node to the document (just copy the first section title),
+ and store that title in the environment.
+ """
+ titlenode = nodes.title()
+ longtitlenode = titlenode
+ # explicit title set with title directive; use this only for
+ # the <title> tag in HTML output
+ if document.has_key('title'):
+ longtitlenode = nodes.title()
+ longtitlenode += nodes.Text(document['title'])
+ # look for first section title and use that as the title
+ for node in document.traverse(nodes.section):
+ visitor = SphinxContentsFilter(document)
+ node[0].walkabout(visitor)
+ titlenode += visitor.get_entry_text()
+ break
+ else:
+ # document has no title
+ titlenode += nodes.Text('<no title>')
+ self.titles[docname] = titlenode
+ self.longtitles[docname] = longtitlenode
+
+ def note_indexentries_from(self, docname, document):
+ entries = self.indexentries[docname] = []
+ for node in document.traverse(addnodes.index):
+ entries.extend(node['entries'])
+
+ def note_citations_from(self, docname, document):
+ for node in document.traverse(nodes.citation):
+ label = node[0].astext()
+ if label in self.citations:
+ self.warn_node('duplicate citation %s, ' % label +
+ 'other instance in %s' % self.doc2path(
+ self.citations[label][0]), node)
+ self.citations[label] = (docname, node['ids'][0])
+
+ def note_toctree(self, docname, toctreenode):
+ """Note a TOC tree directive in a document and gather information about
+ file relations from it.
+ """
+ if toctreenode['glob']:
+ self.glob_toctrees.add(docname)
+ if toctreenode.get('numbered'):
+ self.numbered_toctrees.add(docname)
+ includefiles = toctreenode['includefiles']
+ for includefile in includefiles:
+ # note that if the included file is rebuilt, this one must be
+ # too (since the TOC of the included file could have changed)
+ self.files_to_rebuild.setdefault(includefile, set()).add(docname)
+ self.toctree_includes.setdefault(docname, []).extend(includefiles)
+
+ def build_toc_from(self, docname, document):
+ """Build a TOC from the doctree and store it in the inventory."""
+ numentries = [0] # nonlocal again...
+
+ try:
+ maxdepth = int(self.metadata[docname].get('tocdepth', 0))
+ except ValueError:
+ maxdepth = 0
+
+ def traverse_in_section(node, cls):
+ """Like traverse(), but stay within the same section."""
+ result = []
+ if isinstance(node, cls):
+ result.append(node)
+ for child in node.children:
+ if isinstance(child, nodes.section):
+ continue
+ result.extend(traverse_in_section(child, cls))
+ return result
+
+ def build_toc(node, depth=1):
+ entries = []
+ for sectionnode in node:
+ # find all toctree nodes in this section and add them
+ # to the toc (just copying the toctree node which is then
+ # resolved in self.get_and_resolve_doctree)
+ if isinstance(sectionnode, addnodes.only):
+ onlynode = addnodes.only(expr=sectionnode['expr'])
+ blist = build_toc(sectionnode, depth)
+ if blist:
+ onlynode += blist.children
+ entries.append(onlynode)
+ if not isinstance(sectionnode, nodes.section):
+ for toctreenode in traverse_in_section(sectionnode,
+ addnodes.toctree):
+ item = toctreenode.copy()
+ entries.append(item)
+ # important: do the inventory stuff
+ self.note_toctree(docname, toctreenode)
+ continue
+ title = sectionnode[0]
+ # copy the contents of the section title, but without references
+ # and unnecessary stuff
+ visitor = SphinxContentsFilter(document)
+ title.walkabout(visitor)
+ nodetext = visitor.get_entry_text()
+ if not numentries[0]:
+ # for the very first toc entry, don't add an anchor
+ # as it is the file's title anyway
+ anchorname = ''
+ else:
+ anchorname = '#' + sectionnode['ids'][0]
+ numentries[0] += 1
+ # make these nodes:
+ # list_item -> compact_paragraph -> reference
+ reference = nodes.reference(
+ '', '', internal=True, refuri=docname,
+ anchorname=anchorname, *nodetext)
+ para = addnodes.compact_paragraph('', '', reference)
+ item = nodes.list_item('', para)
+ sub_item = build_toc(sectionnode, depth + 1)
+ if maxdepth == 0 or depth < maxdepth:
+ item += sub_item
+ entries.append(item)
+ if entries:
+ return nodes.bullet_list('', *entries)
+ return []
+ toc = build_toc(document)
+ if toc:
+ self.tocs[docname] = toc
+ else:
+ self.tocs[docname] = nodes.bullet_list('')
+ self.toc_num_entries[docname] = numentries[0]
+
+ def get_toc_for(self, docname, builder):
+ """Return a TOC nodetree -- for use on the same page only!"""
+ try:
+ toc = self.tocs[docname].deepcopy()
+ except KeyError:
+ # the document does not exist anymore: return a dummy node that
+ # renders to nothing
+ return nodes.paragraph()
+ self.process_only_nodes(toc, builder, docname)
+ for node in toc.traverse(nodes.reference):
+ node['refuri'] = node['anchorname'] or '#'
+ return toc
+
+ def get_toctree_for(self, docname, builder, collapse, **kwds):
+ """Return the global TOC nodetree."""
+ doctree = self.get_doctree(self.config.master_doc)
+ toctrees = []
+ if 'includehidden' not in kwds:
+ kwds['includehidden'] = True
+ if 'maxdepth' not in kwds:
+ kwds['maxdepth'] = 0
+ kwds['collapse'] = collapse
+ for toctreenode in doctree.traverse(addnodes.toctree):
+ toctree = self.resolve_toctree(docname, builder, toctreenode,
+ prune=True, **kwds)
+ if toctree:
+ toctrees.append(toctree)
+ if not toctrees:
+ return None
+ result = toctrees[0]
+ for toctree in toctrees[1:]:
+ result.extend(toctree.children)
+ return result
+
+ def get_domain(self, domainname):
+ """Return the domain instance with the specified name.
+
+ Raises an ExtensionError if the domain is not registered.
+ """
+ try:
+ return self.domains[domainname]
+ except KeyError:
+ raise ExtensionError('Domain %r is not registered' % domainname)
+
+ # --------- RESOLVING REFERENCES AND TOCTREES ------------------------------
+
+ def get_doctree(self, docname):
+ """Read the doctree for a file from the pickle and return it."""
+ doctree_filename = self.doc2path(docname, self.doctreedir, '.doctree')
+ f = open(doctree_filename, 'rb')
+ try:
+ doctree = pickle.load(f)
+ finally:
+ f.close()
+ doctree.settings.env = self
+ doctree.reporter = Reporter(self.doc2path(docname), 2, 5,
+ stream=WarningStream(self._warnfunc))
+ return doctree
+
+
+ def get_and_resolve_doctree(self, docname, builder, doctree=None,
+ prune_toctrees=True, includehidden=False):
+ """Read the doctree from the pickle, resolve cross-references and
+ toctrees and return it.
+ """
+ if doctree is None:
+ doctree = self.get_doctree(docname)
+
+ # resolve all pending cross-references
+ self.resolve_references(doctree, docname, builder)
+
+ # now, resolve all toctree nodes
+ for toctreenode in doctree.traverse(addnodes.toctree):
+ result = self.resolve_toctree(docname, builder, toctreenode,
+ prune=prune_toctrees, includehidden=includehidden)
+ if result is None:
+ toctreenode.replace_self([])
+ else:
+ toctreenode.replace_self(result)
+
+ return doctree
+
+ def resolve_toctree(self, docname, builder, toctree, prune=True, maxdepth=0,
+ titles_only=False, collapse=False, includehidden=False):
+ """Resolve a *toctree* node into individual bullet lists with titles
+ as items, returning None (if no containing titles are found) or
+ a new node.
+
+ If *prune* is True, the tree is pruned to *maxdepth*, or if that is 0,
+ to the value of the *maxdepth* option on the *toctree* node.
+ If *titles_only* is True, only toplevel document titles will be in the
+ resulting tree.
+ If *collapse* is True, all branches not containing docname will
+ be collapsed.
+ """
+ if toctree.get('hidden', False) and not includehidden:
+ return None
+
+ # For reading the following two helper function, it is useful to keep
+ # in mind the node structure of a toctree (using HTML-like node names
+ # for brevity):
+ #
+ # <ul>
+ # <li>
+ # <p><a></p>
+ # <p><a></p>
+ # ...
+ # <ul>
+ # ...
+ # </ul>
+ # </li>
+ # </ul>
+ #
+ # The transformation is made in two passes in order to avoid
+ # interactions between marking and pruning the tree (see bug #1046).
+
+ def _toctree_prune(node, depth, maxdepth):
+ """Utility: Cut a TOC at a specified depth."""
+ for subnode in node.children[:]:
+ if isinstance(subnode, (addnodes.compact_paragraph,
+ nodes.list_item)):
+ # for <p> and <li>, just recurse
+ _toctree_prune(subnode, depth, maxdepth)
+ elif isinstance(subnode, nodes.bullet_list):
+ # for <ul>, determine if the depth is too large or if the
+ # entry is to be collapsed
+ if maxdepth > 0 and depth > maxdepth:
+ subnode.parent.replace(subnode, [])
+ else:
+ # cull sub-entries whose parents aren't 'current'
+ if (collapse and depth > 1 and
+ 'iscurrent' not in subnode.parent):
+ subnode.parent.remove(subnode)
+ else:
+ # recurse on visible children
+ _toctree_prune(subnode, depth+1, maxdepth)
+
+ def _toctree_add_classes(node, depth):
+ """Add 'toctree-l%d' and 'current' classes to the toctree."""
+ for subnode in node.children:
+ if isinstance(subnode, (addnodes.compact_paragraph,
+ nodes.list_item)):
+ # for <p> and <li>, indicate the depth level and recurse
+ subnode['classes'].append('toctree-l%d' % (depth-1))
+ _toctree_add_classes(subnode, depth)
+ elif isinstance(subnode, nodes.bullet_list):
+ # for <ul>, just recurse
+ _toctree_add_classes(subnode, depth+1)
+ elif isinstance(subnode, nodes.reference):
+ # for <a>, identify which entries point to the current
+ # document and therefore may not be collapsed
+ if subnode['refuri'] == docname:
+ if not subnode['anchorname']:
+ # give the whole branch a 'current' class
+ # (useful for styling it differently)
+ branchnode = subnode
+ while branchnode:
+ branchnode['classes'].append('current')
+ branchnode = branchnode.parent
+ # mark the list_item as "on current page"
+ if subnode.parent.parent.get('iscurrent'):
+ # but only if it's not already done
+ return
+ while subnode:
+ subnode['iscurrent'] = True
+ subnode = subnode.parent
+
+ def _entries_from_toctree(toctreenode, parents,
+ separate=False, subtree=False):
+ """Return TOC entries for a toctree node."""
+ refs = [(e[0], e[1]) for e in toctreenode['entries']]
+ entries = []
+ for (title, ref) in refs:
+ try:
+ refdoc = None
+ if url_re.match(ref):
+ reference = nodes.reference('', '', internal=False,
+ refuri=ref, anchorname='',
+ *[nodes.Text(title)])
+ para = addnodes.compact_paragraph('', '', reference)
+ item = nodes.list_item('', para)
+ toc = nodes.bullet_list('', item)
+ elif ref == 'self':
+ # 'self' refers to the document from which this
+ # toctree originates
+ ref = toctreenode['parent']
+ if not title:
+ title = clean_astext(self.titles[ref])
+ reference = nodes.reference('', '', internal=True,
+ refuri=ref,
+ anchorname='',
+ *[nodes.Text(title)])
+ para = addnodes.compact_paragraph('', '', reference)
+ item = nodes.list_item('', para)
+ # don't show subitems
+ toc = nodes.bullet_list('', item)
+ else:
+ if ref in parents:
+ self.warn(ref, 'circular toctree references '
+ 'detected, ignoring: %s <- %s' %
+ (ref, ' <- '.join(parents)))
+ continue
+ refdoc = ref
+ toc = self.tocs[ref].deepcopy()
+ self.process_only_nodes(toc, builder, ref)
+ if title and toc.children and len(toc.children) == 1:
+ child = toc.children[0]
+ for refnode in child.traverse(nodes.reference):
+ if refnode['refuri'] == ref and \
+ not refnode['anchorname']:
+ refnode.children = [nodes.Text(title)]
+ if not toc.children:
+ # empty toc means: no titles will show up in the toctree
+ self.warn_node(
+ 'toctree contains reference to document %r that '
+ 'doesn\'t have a title: no link will be generated'
+ % ref, toctreenode)
+ except KeyError:
+ # this is raised if the included file does not exist
+ self.warn_node(
+ 'toctree contains reference to nonexisting document %r'
+ % ref, toctreenode)
+ else:
+ # if titles_only is given, only keep the main title and
+ # sub-toctrees
+ if titles_only:
+ # delete everything but the toplevel title(s)
+ # and toctrees
+ for toplevel in toc:
+ # nodes with length 1 don't have any children anyway
+ if len(toplevel) > 1:
+ subtrees = toplevel.traverse(addnodes.toctree)
+ toplevel[1][:] = subtrees
+ # resolve all sub-toctrees
+ for toctreenode in toc.traverse(addnodes.toctree):
+ if not (toctreenode.get('hidden', False)
+ and not includehidden):
+ i = toctreenode.parent.index(toctreenode) + 1
+ for item in _entries_from_toctree(
+ toctreenode, [refdoc] + parents,
+ subtree=True):
+ toctreenode.parent.insert(i, item)
+ i += 1
+ toctreenode.parent.remove(toctreenode)
+ if separate:
+ entries.append(toc)
+ else:
+ entries.extend(toc.children)
+ if not subtree and not separate:
+ ret = nodes.bullet_list()
+ ret += entries
+ return [ret]
+ return entries
+
+ maxdepth = maxdepth or toctree.get('maxdepth', -1)
+ if not titles_only and toctree.get('titlesonly', False):
+ titles_only = True
+ if not includehidden and toctree.get('includehidden', False):
+ includehidden = True
+
+ # NOTE: previously, this was separate=True, but that leads to artificial
+ # separation when two or more toctree entries form a logical unit, so
+ # separating mode is no longer used -- it's kept here for history's sake
+ tocentries = _entries_from_toctree(toctree, [], separate=False)
+ if not tocentries:
+ return None
+
+ newnode = addnodes.compact_paragraph('', '', *tocentries)
+ newnode['toctree'] = True
+
+ # prune the tree to maxdepth, also set toc depth and current classes
+ _toctree_add_classes(newnode, 1)
+ _toctree_prune(newnode, 1, prune and maxdepth or 0)
+
+ # set the target paths in the toctrees (they are not known at TOC
+ # generation time)
+ for refnode in newnode.traverse(nodes.reference):
+ if not url_re.match(refnode['refuri']):
+ refnode['refuri'] = builder.get_relative_uri(
+ docname, refnode['refuri']) + refnode['anchorname']
+ return newnode
+
+ def resolve_references(self, doctree, fromdocname, builder):
+ for node in doctree.traverse(addnodes.pending_xref):
+ contnode = node[0].deepcopy()
+ newnode = None
+
+ typ = node['reftype']
+ target = node['reftarget']
+ refdoc = node.get('refdoc', fromdocname)
+ domain = None
+
+ try:
+ if 'refdomain' in node and node['refdomain']:
+ # let the domain try to resolve the reference
+ try:
+ domain = self.domains[node['refdomain']]
+ except KeyError:
+ raise NoUri
+ newnode = domain.resolve_xref(self, fromdocname, builder,
+ typ, target, node, contnode)
+ # really hardwired reference types
+ elif typ == 'doc':
+ # directly reference to document by source name;
+ # can be absolute or relative
+ docname = docname_join(refdoc, target)
+ if docname in self.all_docs:
+ if node['refexplicit']:
+ # reference with explicit title
+ caption = node.astext()
+ else:
+ caption = clean_astext(self.titles[docname])
+ innernode = nodes.emphasis(caption, caption)
+ newnode = nodes.reference('', '', internal=True)
+ newnode['refuri'] = builder.get_relative_uri(
+ fromdocname, docname)
+ newnode.append(innernode)
+ elif typ == 'citation':
+ docname, labelid = self.citations.get(target, ('', ''))
+ if docname:
+ try:
+ newnode = make_refnode(builder, fromdocname,
+ docname, labelid, contnode)
+ except NoUri:
+ # remove the ids we added in the CitationReferences
+ # transform since they can't be transfered to
+ # the contnode (if it's a Text node)
+ if not isinstance(contnode, nodes.Element):
+ del node['ids'][:]
+ raise
+ elif 'ids' in node:
+ # remove ids attribute that annotated at
+ # transforms.CitationReference.apply.
+ del node['ids'][:]
+ # no new node found? try the missing-reference event
+ if newnode is None:
+ newnode = builder.app.emit_firstresult(
+ 'missing-reference', self, node, contnode)
+ # still not found? warn if in nit-picky mode
+ if newnode is None:
+ self._warn_missing_reference(
+ fromdocname, typ, target, node, domain)
+ except NoUri:
+ newnode = contnode
+ node.replace_self(newnode or contnode)
+
+ # remove only-nodes that do not belong to our builder
+ self.process_only_nodes(doctree, builder, fromdocname)
+
+ # allow custom references to be resolved
+ builder.app.emit('doctree-resolved', doctree, fromdocname)
+
+ def _warn_missing_reference(self, fromdoc, typ, target, node, domain):
+ warn = node.get('refwarn')
+ if self.config.nitpicky:
+ warn = True
+ if self._nitpick_ignore:
+ dtype = domain and '%s:%s' % (domain.name, typ) or typ
+ if (dtype, target) in self._nitpick_ignore:
+ warn = False
+ # for "std" types also try without domain name
+ if domain.name == 'std' and (typ, target) in self._nitpick_ignore:
+ warn = False
+ if not warn:
+ return
+ if domain and typ in domain.dangling_warnings:
+ msg = domain.dangling_warnings[typ]
+ elif typ == 'doc':
+ msg = 'unknown document: %(target)s'
+ elif typ == 'citation':
+ msg = 'citation not found: %(target)s'
+ elif node.get('refdomain', 'std') != 'std':
+ msg = '%s:%s reference target not found: %%(target)s' % \
+ (node['refdomain'], typ)
+ else:
+ msg = '%s reference target not found: %%(target)s' % typ
+ self.warn_node(msg % {'target': target}, node)
+
+ def process_only_nodes(self, doctree, builder, fromdocname=None):
+ # A comment on the comment() nodes being inserted: replacing by [] would
+ # result in a "Losing ids" exception if there is a target node before
+ # the only node, so we make sure docutils can transfer the id to
+ # something, even if it's just a comment and will lose the id anyway...
+ for node in doctree.traverse(addnodes.only):
+ try:
+ ret = builder.tags.eval_condition(node['expr'])
+ except Exception, err:
+ self.warn_node('exception while evaluating only '
+ 'directive expression: %s' % err, node)
+ node.replace_self(node.children or nodes.comment())
+ else:
+ if ret:
+ node.replace_self(node.children or nodes.comment())
+ else:
+ node.replace_self(nodes.comment())
+
+ def assign_section_numbers(self):
+ """Assign a section number to each heading under a numbered toctree."""
+ # a list of all docnames whose section numbers changed
+ rewrite_needed = []
+
+ old_secnumbers = self.toc_secnumbers
+ self.toc_secnumbers = {}
+
+ def _walk_toc(node, secnums, depth, titlenode=None):
+ # titlenode is the title of the document, it will get assigned a
+ # secnumber too, so that it shows up in next/prev/parent rellinks
+ for subnode in node.children:
+ if isinstance(subnode, nodes.bullet_list):
+ numstack.append(0)
+ _walk_toc(subnode, secnums, depth-1, titlenode)
+ numstack.pop()
+ titlenode = None
+ elif isinstance(subnode, nodes.list_item):
+ _walk_toc(subnode, secnums, depth, titlenode)
+ titlenode = None
+ elif isinstance(subnode, addnodes.only):
+ # at this stage we don't know yet which sections are going
+ # to be included; just include all of them, even if it leads
+ # to gaps in the numbering
+ _walk_toc(subnode, secnums, depth, titlenode)
+ titlenode = None
+ elif isinstance(subnode, addnodes.compact_paragraph):
+ numstack[-1] += 1
+ if depth > 0:
+ number = tuple(numstack)
+ else:
+ number = None
+ secnums[subnode[0]['anchorname']] = \
+ subnode[0]['secnumber'] = number
+ if titlenode:
+ titlenode['secnumber'] = number
+ titlenode = None
+ elif isinstance(subnode, addnodes.toctree):
+ _walk_toctree(subnode, depth)
+
+ def _walk_toctree(toctreenode, depth):
+ if depth == 0:
+ return
+ for (title, ref) in toctreenode['entries']:
+ if url_re.match(ref) or ref == 'self':
+ # don't mess with those
+ continue
+ if ref in self.tocs:
+ secnums = self.toc_secnumbers[ref] = {}
+ _walk_toc(self.tocs[ref], secnums, depth,
+ self.titles.get(ref))
+ if secnums != old_secnumbers.get(ref):
+ rewrite_needed.append(ref)
+
+ for docname in self.numbered_toctrees:
+ doctree = self.get_doctree(docname)
+ for toctreenode in doctree.traverse(addnodes.toctree):
+ depth = toctreenode.get('numbered', 0)
+ if depth:
+ # every numbered toctree gets new numbering
+ numstack = [0]
+ _walk_toctree(toctreenode, depth)
+
+ return rewrite_needed
+
+ def create_index(self, builder, group_entries=True,
+ _fixre=re.compile(r'(.*) ([(][^()]*[)])')):
+ """Create the real index from the collected index entries."""
+ new = {}
+
+ def add_entry(word, subword, link=True, dic=new):
+ # Force the word to be unicode if it's a ASCII bytestring.
+ # This will solve problems with unicode normalization later.
+ # For instance the RFC role will add bytestrings at the moment
+ word = unicode(word)
+ entry = dic.get(word)
+ if not entry:
+ dic[word] = entry = [[], {}]
+ if subword:
+ add_entry(subword, '', link=link, dic=entry[1])
+ elif link:
+ try:
+ uri = builder.get_relative_uri('genindex', fn) + '#' + tid
+ except NoUri:
+ pass
+ else:
+ entry[0].append((main, uri))
+
+ for fn, entries in self.indexentries.iteritems():
+ # new entry types must be listed in directives/other.py!
+ for type, value, tid, main in entries:
+ try:
+ if type == 'single':
+ try:
+ entry, subentry = split_into(2, 'single', value)
+ except ValueError:
+ entry, = split_into(1, 'single', value)
+ subentry = ''
+ add_entry(entry, subentry)
+ elif type == 'pair':
+ first, second = split_into(2, 'pair', value)
+ add_entry(first, second)
+ add_entry(second, first)
+ elif type == 'triple':
+ first, second, third = split_into(3, 'triple', value)
+ add_entry(first, second+' '+third)
+ add_entry(second, third+', '+first)
+ add_entry(third, first+' '+second)
+ elif type == 'see':
+ first, second = split_into(2, 'see', value)
+ add_entry(first, _('see %s') % second, link=False)
+ elif type == 'seealso':
+ first, second = split_into(2, 'see', value)
+ add_entry(first, _('see also %s') % second, link=False)
+ else:
+ self.warn(fn, 'unknown index entry type %r' % type)
+ except ValueError, err:
+ self.warn(fn, str(err))
+
+ # sort the index entries; put all symbols at the front, even those
+ # following the letters in ASCII, this is where the chr(127) comes from
+ def keyfunc(entry, lcletters=string.ascii_lowercase + '_'):
+ lckey = unicodedata.normalize('NFD', entry[0].lower())
+ if lckey[0:1] in lcletters:
+ return chr(127) + lckey
+ return lckey
+ newlist = new.items()
+ newlist.sort(key=keyfunc)
+
+ if group_entries:
+ # fixup entries: transform
+ # func() (in module foo)
+ # func() (in module bar)
+ # into
+ # func()
+ # (in module foo)
+ # (in module bar)
+ oldkey = ''
+ oldsubitems = None
+ i = 0
+ while i < len(newlist):
+ key, (targets, subitems) = newlist[i]
+ # cannot move if it has subitems; structure gets too complex
+ if not subitems:
+ m = _fixre.match(key)
+ if m:
+ if oldkey == m.group(1):
+ # prefixes match: add entry as subitem of the
+ # previous entry
+ oldsubitems.setdefault(m.group(2), [[], {}])[0].\
+ extend(targets)
+ del newlist[i]
+ continue
+ oldkey = m.group(1)
+ else:
+ oldkey = key
+ oldsubitems = subitems
+ i += 1
+
+ # group the entries by letter
+ def keyfunc2(item, letters=string.ascii_uppercase + '_'):
+ # hack: mutating the subitems dicts to a list in the keyfunc
+ k, v = item
+ v[1] = sorted((si, se) for (si, (se, void)) in v[1].iteritems())
+ # now calculate the key
+ letter = unicodedata.normalize('NFD', k[0])[0].upper()
+ if letter in letters:
+ return letter
+ else:
+ # get all other symbols under one heading
+ return _('Symbols')
+ return [(key, list(group))
+ for (key, group) in groupby(newlist, keyfunc2)]
+
+ def collect_relations(self):
+ relations = {}
+ getinc = self.toctree_includes.get
+ def collect(parents, parents_set, docname, previous, next):
+ # circular relationship?
+ if docname in parents_set:
+ # we will warn about this in resolve_toctree()
+ return
+ includes = getinc(docname)
+ # previous
+ if not previous:
+ # if no previous sibling, go to parent
+ previous = parents[0][0]
+ else:
+ # else, go to previous sibling, or if it has children, to
+ # the last of its children, or if that has children, to the
+ # last of those, and so forth
+ while 1:
+ previncs = getinc(previous)
+ if previncs:
+ previous = previncs[-1]
+ else:
+ break
+ # next
+ if includes:
+ # if it has children, go to first of them
+ next = includes[0]
+ elif next:
+ # else, if next sibling, go to it
+ pass
+ else:
+ # else, go to the next sibling of the parent, if present,
+ # else the grandparent's sibling, if present, and so forth
+ for parname, parindex in parents:
+ parincs = getinc(parname)
+ if parincs and parindex + 1 < len(parincs):
+ next = parincs[parindex+1]
+ break
+ # else it will stay None
+ # same for children
+ if includes:
+ for subindex, args in enumerate(izip(includes,
+ [None] + includes,
+ includes[1:] + [None])):
+ collect([(docname, subindex)] + parents,
+ parents_set.union([docname]), *args)
+ relations[docname] = [parents[0][0], previous, next]
+ collect([(None, 0)], set(), self.config.master_doc, None, None)
+ return relations
+
+ def check_consistency(self):
+ """Do consistency checks."""
+ for docname in sorted(self.all_docs):
+ if docname not in self.files_to_rebuild:
+ if docname == self.config.master_doc:
+ # the master file is not included anywhere ;)
+ continue
+ if 'orphan' in self.metadata[docname]:
+ continue
+ self.warn(docname, 'document isn\'t included in any toctree')
diff --git a/sphinx/errors.py b/sphinx/errors.py
new file mode 100644
index 0000000..4d737e5
--- /dev/null
+++ b/sphinx/errors.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.errors
+ ~~~~~~~~~~~~~
+
+ Contains SphinxError and a few subclasses (in an extra module to avoid
+ circular import problems).
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+class SphinxError(Exception):
+ """
+ Base class for Sphinx errors that are shown to the user in a nicer
+ way than normal exceptions.
+ """
+ category = 'Sphinx error'
+
+
+class SphinxWarning(SphinxError):
+ """Raised for warnings if warnings are treated as errors."""
+ category = 'Warning, treated as error'
+
+
+class ExtensionError(SphinxError):
+ """Raised if something's wrong with the configuration."""
+ category = 'Extension error'
+
+ def __init__(self, message, orig_exc=None):
+ SphinxError.__init__(self, message)
+ self.orig_exc = orig_exc
+
+ def __repr__(self):
+ if self.orig_exc:
+ return '%s(%r, %r)' % (self.__class__.__name__,
+ self.message, self.orig_exc)
+ return '%s(%r)' % (self.__class__.__name__, self.message)
+
+ def __str__(self):
+ parent_str = SphinxError.__str__(self)
+ if self.orig_exc:
+ return '%s (exception: %s)' % (parent_str, self.orig_exc)
+ return parent_str
+
+
+class ConfigError(SphinxError):
+ category = 'Configuration error'
+
+
+class ThemeError(SphinxError):
+ category = 'Theme error'
+
+
+class VersionRequirementError(SphinxError):
+ category = 'Sphinx version error'
+
+
+class PycodeError(Exception):
+ def __str__(self):
+ res = self.args[0]
+ if len(self.args) > 1:
+ res += ' (exception was: %r)' % self.args[1]
+ return res
diff --git a/sphinx/ext/__init__.py b/sphinx/ext/__init__.py
new file mode 100644
index 0000000..5a807ba
--- /dev/null
+++ b/sphinx/ext/__init__.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext
+ ~~~~~~~~~~
+
+ Contains Sphinx features not activated by default.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
new file mode 100644
index 0000000..423f921
--- /dev/null
+++ b/sphinx/ext/autodoc.py
@@ -0,0 +1,1480 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.autodoc
+ ~~~~~~~~~~~~~~~~~~
+
+ Automatically insert docstrings for functions, classes or whole modules into
+ the doctree, thus avoiding duplication between docstrings and documentation
+ for those who like elaborate docstrings.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import sys
+import inspect
+import traceback
+from types import FunctionType, BuiltinFunctionType, MethodType
+
+from docutils import nodes
+from docutils.utils import assemble_option_dict
+from docutils.statemachine import ViewList
+
+from sphinx.util import rpartition, force_decode
+from sphinx.locale import _
+from sphinx.pycode import ModuleAnalyzer, PycodeError
+from sphinx.application import ExtensionError
+from sphinx.util.nodes import nested_parse_with_titles
+from sphinx.util.compat import Directive
+from sphinx.util.inspect import getargspec, isdescriptor, safe_getmembers, \
+ safe_getattr, safe_repr, is_builtin_class_method
+from sphinx.util.pycompat import base_exception, class_types
+from sphinx.util.docstrings import prepare_docstring
+
+
+#: extended signature RE: with explicit module name separated by ::
+py_ext_sig_re = re.compile(
+ r'''^ ([\w.]+::)? # explicit module name
+ ([\w.]+\.)? # module and/or class name(s)
+ (\w+) \s* # thing name
+ (?: \((.*)\) # optional: arguments
+ (?:\s* -> \s* (.*))? # return annotation
+ )? $ # and nothing more
+ ''', re.VERBOSE)
+
+
+class DefDict(dict):
+ """A dict that returns a default on nonexisting keys."""
+ def __init__(self, default):
+ dict.__init__(self)
+ self.default = default
+ def __getitem__(self, key):
+ try:
+ return dict.__getitem__(self, key)
+ except KeyError:
+ return self.default
+ def __nonzero__(self):
+ # docutils check "if option_spec"
+ return True
+
+identity = lambda x: x
+
+
+class Options(dict):
+ """A dict/attribute hybrid that returns None on nonexisting keys."""
+ def __getattr__(self, name):
+ try:
+ return self[name.replace('_', '-')]
+ except KeyError:
+ return None
+
+
+ALL = object()
+INSTANCEATTR = object()
+
+def members_option(arg):
+ """Used to convert the :members: option to auto directives."""
+ if arg is None:
+ return ALL
+ return [x.strip() for x in arg.split(',')]
+
+def members_set_option(arg):
+ """Used to convert the :members: option to auto directives."""
+ if arg is None:
+ return ALL
+ return set(x.strip() for x in arg.split(','))
+
+SUPPRESS = object()
+
+def annotation_option(arg):
+ if arg is None:
+ # suppress showing the representation of the object
+ return SUPPRESS
+ else:
+ return arg
+
+def bool_option(arg):
+ """Used to convert flag options to auto directives. (Instead of
+ directives.flag(), which returns None).
+ """
+ return True
+
+
+class AutodocReporter(object):
+ """
+ A reporter replacement that assigns the correct source name
+ and line number to a system message, as recorded in a ViewList.
+ """
+ def __init__(self, viewlist, reporter):
+ self.viewlist = viewlist
+ self.reporter = reporter
+
+ def __getattr__(self, name):
+ return getattr(self.reporter, name)
+
+ def system_message(self, level, message, *children, **kwargs):
+ if 'line' in kwargs and 'source' not in kwargs:
+ try:
+ source, line = self.viewlist.items[kwargs['line']]
+ except IndexError:
+ pass
+ else:
+ kwargs['source'] = source
+ kwargs['line'] = line
+ return self.reporter.system_message(level, message,
+ *children, **kwargs)
+
+ def debug(self, *args, **kwargs):
+ if self.reporter.debug_flag:
+ return self.system_message(0, *args, **kwargs)
+
+ def info(self, *args, **kwargs):
+ return self.system_message(1, *args, **kwargs)
+
+ def warning(self, *args, **kwargs):
+ return self.system_message(2, *args, **kwargs)
+
+ def error(self, *args, **kwargs):
+ return self.system_message(3, *args, **kwargs)
+
+ def severe(self, *args, **kwargs):
+ return self.system_message(4, *args, **kwargs)
+
+
+# Some useful event listener factories for autodoc-process-docstring.
+
+def cut_lines(pre, post=0, what=None):
+ """Return a listener that removes the first *pre* and last *post*
+ lines of every docstring. If *what* is a sequence of strings,
+ only docstrings of a type in *what* will be processed.
+
+ Use like this (e.g. in the ``setup()`` function of :file:`conf.py`)::
+
+ from sphinx.ext.autodoc import cut_lines
+ app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
+
+ This can (and should) be used in place of :confval:`automodule_skip_lines`.
+ """
+ def process(app, what_, name, obj, options, lines):
+ if what and what_ not in what:
+ return
+ del lines[:pre]
+ if post:
+ # remove one trailing blank line.
+ if lines and not lines[-1]:
+ lines.pop(-1)
+ del lines[-post:]
+ # make sure there is a blank line at the end
+ if lines and lines[-1]:
+ lines.append('')
+ return process
+
+def between(marker, what=None, keepempty=False, exclude=False):
+ """Return a listener that either keeps, or if *exclude* is True excludes,
+ lines between lines that match the *marker* regular expression. If no line
+ matches, the resulting docstring would be empty, so no change will be made
+ unless *keepempty* is true.
+
+ If *what* is a sequence of strings, only docstrings of a type in *what* will
+ be processed.
+ """
+ marker_re = re.compile(marker)
+ def process(app, what_, name, obj, options, lines):
+ if what and what_ not in what:
+ return
+ deleted = 0
+ delete = not exclude
+ orig_lines = lines[:]
+ for i, line in enumerate(orig_lines):
+ if delete:
+ lines.pop(i - deleted)
+ deleted += 1
+ if marker_re.match(line):
+ delete = not delete
+ if delete:
+ lines.pop(i - deleted)
+ deleted += 1
+ if not lines and not keepempty:
+ lines[:] = orig_lines
+ # make sure there is a blank line at the end
+ if lines and lines[-1]:
+ lines.append('')
+ return process
+
+
+class Documenter(object):
+ """
+ A Documenter knows how to autodocument a single object type. When
+ registered with the AutoDirective, it will be used to document objects
+ of that type when needed by autodoc.
+
+ Its *objtype* attribute selects what auto directive it is assigned to
+ (the directive name is 'auto' + objtype), and what directive it generates
+ by default, though that can be overridden by an attribute called
+ *directivetype*.
+
+ A Documenter has an *option_spec* that works like a docutils directive's;
+ in fact, it will be used to parse an auto directive's options that matches
+ the documenter.
+ """
+ #: name by which the directive is called (auto...) and the default
+ #: generated directive name
+ objtype = 'object'
+ #: indentation by which to indent the directive content
+ content_indent = u' '
+ #: priority if multiple documenters return True from can_document_member
+ priority = 0
+ #: order if autodoc_member_order is set to 'groupwise'
+ member_order = 0
+ #: true if the generated content may contain titles
+ titles_allowed = False
+
+ option_spec = {'noindex': bool_option}
+
+ @staticmethod
+ def get_attr(obj, name, *defargs):
+ """getattr() override for types such as Zope interfaces."""
+ for typ, func in AutoDirective._special_attrgetters.iteritems():
+ if isinstance(obj, typ):
+ return func(obj, name, *defargs)
+ return safe_getattr(obj, name, *defargs)
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ """Called to see if a member can be documented by this documenter."""
+ raise NotImplementedError('must be implemented in subclasses')
+
+ def __init__(self, directive, name, indent=u''):
+ self.directive = directive
+ self.env = directive.env
+ self.options = directive.genopt
+ self.name = name
+ self.indent = indent
+ # the module and object path within the module, and the fully
+ # qualified name (all set after resolve_name succeeds)
+ self.modname = None
+ self.module = None
+ self.objpath = None
+ self.fullname = None
+ # extra signature items (arguments and return annotation,
+ # also set after resolve_name succeeds)
+ self.args = None
+ self.retann = None
+ # the object to document (set after import_object succeeds)
+ self.object = None
+ self.object_name = None
+ # the parent/owner of the object to document
+ self.parent = None
+ # the module analyzer to get at attribute docs, or None
+ self.analyzer = None
+
+ def add_line(self, line, source, *lineno):
+ """Append one line of generated reST to the output."""
+ self.directive.result.append(self.indent + line, source, *lineno)
+
+ def resolve_name(self, modname, parents, path, base):
+ """Resolve the module and name of the object to document given by the
+ arguments and the current module/class.
+
+ Must return a pair of the module name and a chain of attributes; for
+ example, it would return ``('zipfile', ['ZipFile', 'open'])`` for the
+ ``zipfile.ZipFile.open`` method.
+ """
+ raise NotImplementedError('must be implemented in subclasses')
+
+ def parse_name(self):
+ """Determine what module to import and what attribute to document.
+
+ Returns True and sets *self.modname*, *self.objpath*, *self.fullname*,
+ *self.args* and *self.retann* if parsing and resolving was successful.
+ """
+ # first, parse the definition -- auto directives for classes and
+ # functions can contain a signature which is then used instead of
+ # an autogenerated one
+ try:
+ explicit_modname, path, base, args, retann = \
+ py_ext_sig_re.match(self.name).groups()
+ except AttributeError:
+ self.directive.warn('invalid signature for auto%s (%r)' %
+ (self.objtype, self.name))
+ return False
+
+ # support explicit module and class name separation via ::
+ if explicit_modname is not None:
+ modname = explicit_modname[:-2]
+ parents = path and path.rstrip('.').split('.') or []
+ else:
+ modname = None
+ parents = []
+
+ self.modname, self.objpath = \
+ self.resolve_name(modname, parents, path, base)
+
+ if not self.modname:
+ return False
+
+ self.args = args
+ self.retann = retann
+ self.fullname = (self.modname or '') + \
+ (self.objpath and '.' + '.'.join(self.objpath) or '')
+ return True
+
+ def import_object(self):
+ """Import the object given by *self.modname* and *self.objpath* and set
+ it as *self.object*.
+
+ Returns True if successful, False if an error occurred.
+ """
+ dbg = self.env.app.debug
+ if self.objpath:
+ dbg('[autodoc] from %s import %s',
+ self.modname, '.'.join(self.objpath))
+ try:
+ dbg('[autodoc] import %s', self.modname)
+ __import__(self.modname)
+ parent = None
+ obj = self.module = sys.modules[self.modname]
+ dbg('[autodoc] => %r', obj)
+ for part in self.objpath:
+ parent = obj
+ dbg('[autodoc] getattr(_, %r)', part)
+ obj = self.get_attr(obj, part)
+ dbg('[autodoc] => %r', obj)
+ self.object_name = part
+ self.parent = parent
+ self.object = obj
+ return True
+ # this used to only catch SyntaxError, ImportError and AttributeError,
+ # but importing modules with side effects can raise all kinds of errors
+ except (Exception, SystemExit) as e:
+ if self.objpath:
+ errmsg = 'autodoc: failed to import %s %r from module %r' % \
+ (self.objtype, '.'.join(self.objpath), self.modname)
+ else:
+ errmsg = 'autodoc: failed to import %s %r' % \
+ (self.objtype, self.fullname)
+ if isinstance(e, SystemExit):
+ errmsg += ('; the module executes module level statement ' +
+ 'and it might call sys.exit().')
+ else:
+ errmsg += '; the following exception was raised:\n%s' % \
+ traceback.format_exc()
+ dbg(errmsg)
+ self.directive.warn(errmsg)
+ self.env.note_reread()
+ return False
+
+ def get_real_modname(self):
+ """Get the real module name of an object to document.
+
+ It can differ from the name of the module through which the object was
+ imported.
+ """
+ return self.get_attr(self.object, '__module__', None) or self.modname
+
+ def check_module(self):
+ """Check if *self.object* is really defined in the module given by
+ *self.modname*.
+ """
+ if self.options.imported_members:
+ return True
+
+ modname = self.get_attr(self.object, '__module__', None)
+ if modname and modname != self.modname:
+ return False
+ return True
+
+ def format_args(self):
+ """Format the argument signature of *self.object*.
+
+ Should return None if the object does not have a signature.
+ """
+ return None
+
+ def format_name(self):
+ """Format the name of *self.object*.
+
+ This normally should be something that can be parsed by the generated
+ directive, but doesn't need to be (Sphinx will display it unparsed
+ then).
+ """
+ # normally the name doesn't contain the module (except for module
+ # directives of course)
+ return '.'.join(self.objpath) or self.modname
+
+ def format_signature(self):
+ """Format the signature (arguments and return annotation) of the object.
+
+ Let the user process it via the ``autodoc-process-signature`` event.
+ """
+ if self.args is not None:
+ # signature given explicitly
+ args = "(%s)" % self.args
+ else:
+ # try to introspect the signature
+ try:
+ args = self.format_args()
+ except Exception, err:
+ self.directive.warn('error while formatting arguments for '
+ '%s: %s' % (self.fullname, err))
+ args = None
+
+ retann = self.retann
+
+ result = self.env.app.emit_firstresult(
+ 'autodoc-process-signature', self.objtype, self.fullname,
+ self.object, self.options, args, retann)
+ if result:
+ args, retann = result
+
+ if args is not None:
+ return args + (retann and (' -> %s' % retann) or '')
+ else:
+ return ''
+
+ def add_directive_header(self, sig):
+ """Add the directive header and options to the generated content."""
+ domain = getattr(self, 'domain', 'py')
+ directive = getattr(self, 'directivetype', self.objtype)
+ name = self.format_name()
+ self.add_line(u'.. %s:%s:: %s%s' % (domain, directive, name, sig),
+ '<autodoc>')
+ if self.options.noindex:
+ self.add_line(u' :noindex:', '<autodoc>')
+ if self.objpath:
+ # Be explicit about the module, this is necessary since .. class::
+ # etc. don't support a prepended module name
+ self.add_line(u' :module: %s' % self.modname, '<autodoc>')
+
+ def get_doc(self, encoding=None, ignore=1):
+ """Decode and return lines of the docstring(s) for the object."""
+ docstring = self.get_attr(self.object, '__doc__', None)
+ # make sure we have Unicode docstrings, then sanitize and split
+ # into lines
+ if isinstance(docstring, unicode):
+ return [prepare_docstring(docstring, ignore)]
+ elif isinstance(docstring, str): # this will not trigger on Py3
+ return [prepare_docstring(force_decode(docstring, encoding),
+ ignore)]
+ # ... else it is something strange, let's ignore it
+ return []
+
+ def process_doc(self, docstrings):
+ """Let the user process the docstrings before adding them."""
+ for docstringlines in docstrings:
+ if self.env.app:
+ # let extensions preprocess docstrings
+ self.env.app.emit('autodoc-process-docstring',
+ self.objtype, self.fullname, self.object,
+ self.options, docstringlines)
+ for line in docstringlines:
+ yield line
+
+ def add_content(self, more_content, no_docstring=False):
+ """Add content from docstrings, attribute documentation and user."""
+ # set sourcename and add content from attribute documentation
+ if self.analyzer:
+ # prevent encoding errors when the file name is non-ASCII
+ if not isinstance(self.analyzer.srcname, unicode):
+ filename = unicode(self.analyzer.srcname,
+ sys.getfilesystemencoding(), 'replace')
+ else:
+ filename = self.analyzer.srcname
+ sourcename = u'%s:docstring of %s' % (filename, self.fullname)
+
+ attr_docs = self.analyzer.find_attr_docs()
+ if self.objpath:
+ key = ('.'.join(self.objpath[:-1]), self.objpath[-1])
+ if key in attr_docs:
+ no_docstring = True
+ docstrings = [attr_docs[key]]
+ for i, line in enumerate(self.process_doc(docstrings)):
+ self.add_line(line, sourcename, i)
+ else:
+ sourcename = u'docstring of %s' % self.fullname
+
+ # add content from docstrings
+ if not no_docstring:
+ encoding = self.analyzer and self.analyzer.encoding
+ docstrings = self.get_doc(encoding)
+ if not docstrings:
+ # append at least a dummy docstring, so that the event
+ # autodoc-process-docstring is fired and can add some
+ # content if desired
+ docstrings.append([])
+ for i, line in enumerate(self.process_doc(docstrings)):
+ self.add_line(line, sourcename, i)
+
+ # add additional content (e.g. from document), if present
+ if more_content:
+ for line, src in zip(more_content.data, more_content.items):
+ self.add_line(line, src[0], src[1])
+
+ def get_object_members(self, want_all):
+ """Return `(members_check_module, members)` where `members` is a
+ list of `(membername, member)` pairs of the members of *self.object*.
+
+ If *want_all* is True, return all members. Else, only return those
+ members given by *self.options.members* (which may also be none).
+ """
+ analyzed_member_names = set()
+ if self.analyzer:
+ attr_docs = self.analyzer.find_attr_docs()
+ namespace = '.'.join(self.objpath)
+ for item in attr_docs.iteritems():
+ if item[0][0] == namespace:
+ analyzed_member_names.add(item[0][1])
+ if not want_all:
+ if not self.options.members:
+ return False, []
+ # specific members given
+ members = []
+ for mname in self.options.members:
+ try:
+ members.append((mname, self.get_attr(self.object, mname)))
+ except AttributeError:
+ if mname not in analyzed_member_names:
+ self.directive.warn('missing attribute %s in object %s'
+ % (mname, self.fullname))
+ elif self.options.inherited_members:
+ # safe_getmembers() uses dir() which pulls in members from all
+ # base classes
+ members = safe_getmembers(self.object, attr_getter=self.get_attr)
+ else:
+ # __dict__ contains only the members directly defined in
+ # the class (but get them via getattr anyway, to e.g. get
+ # unbound method objects instead of function objects);
+ # using keys() because apparently there are objects for which
+ # __dict__ changes while getting attributes
+ try:
+ obj_dict = self.get_attr(self.object, '__dict__')
+ except AttributeError:
+ members = []
+ else:
+ members = [(mname, self.get_attr(self.object, mname, None))
+ for mname in obj_dict.keys()]
+ membernames = set(m[0] for m in members)
+ # add instance attributes from the analyzer
+ for aname in analyzed_member_names:
+ if aname not in membernames and \
+ (want_all or aname in self.options.members):
+ members.append((aname, INSTANCEATTR))
+ return False, sorted(members)
+
+ def filter_members(self, members, want_all):
+ """Filter the given member list.
+
+ Members are skipped if
+
+ - they are private (except if given explicitly or the private-members
+ option is set)
+ - they are special methods (except if given explicitly or the
+ special-members option is set)
+ - they are undocumented (except if the undoc-members option is set)
+
+ The user can override the skipping decision by connecting to the
+ ``autodoc-skip-member`` event.
+ """
+ ret = []
+
+ # search for members in source code too
+ namespace = '.'.join(self.objpath) # will be empty for modules
+
+ if self.analyzer:
+ attr_docs = self.analyzer.find_attr_docs()
+ else:
+ attr_docs = {}
+
+ # process members and determine which to skip
+ for (membername, member) in members:
+ # if isattr is True, the member is documented as an attribute
+ isattr = False
+
+ doc = self.get_attr(member, '__doc__', None)
+ # if the member __doc__ is the same as self's __doc__, it's just
+ # inherited and therefore not the member's doc
+ cls = self.get_attr(member, '__class__', None)
+ if cls:
+ cls_doc = self.get_attr(cls, '__doc__', None)
+ if cls_doc == doc:
+ doc = None
+ has_doc = bool(doc)
+
+ keep = False
+ if want_all and membername.startswith('__') and \
+ membername.endswith('__') and len(membername) > 4:
+ # special __methods__
+ if self.options.special_members is ALL and \
+ membername != '__doc__':
+ keep = has_doc or self.options.undoc_members
+ elif self.options.special_members and \
+ self.options.special_members is not ALL and \
+ membername in self.options.special_members:
+ keep = has_doc or self.options.undoc_members
+ elif want_all and membername.startswith('_'):
+ # ignore members whose name starts with _ by default
+ keep = self.options.private_members and \
+ (has_doc or self.options.undoc_members)
+ elif (namespace, membername) in attr_docs:
+ # keep documented attributes
+ keep = True
+ isattr = True
+ else:
+ # ignore undocumented members if :undoc-members: is not given
+ keep = has_doc or self.options.undoc_members
+
+ # give the user a chance to decide whether this member
+ # should be skipped
+ if self.env.app:
+ # let extensions preprocess docstrings
+ skip_user = self.env.app.emit_firstresult(
+ 'autodoc-skip-member', self.objtype, membername, member,
+ not keep, self.options)
+ if skip_user is not None:
+ keep = not skip_user
+
+ if keep:
+ ret.append((membername, member, isattr))
+
+ return ret
+
+ def document_members(self, all_members=False):
+ """Generate reST for member documentation.
+
+ If *all_members* is True, do all members, else those given by
+ *self.options.members*.
+ """
+ # set current namespace for finding members
+ self.env.temp_data['autodoc:module'] = self.modname
+ if self.objpath:
+ self.env.temp_data['autodoc:class'] = self.objpath[0]
+
+ want_all = all_members or self.options.inherited_members or \
+ self.options.members is ALL
+ # find out which members are documentable
+ members_check_module, members = self.get_object_members(want_all)
+
+ # remove members given by exclude-members
+ if self.options.exclude_members:
+ members = [(membername, member) for (membername, member) in members
+ if membername not in self.options.exclude_members]
+
+ # document non-skipped members
+ memberdocumenters = []
+ for (mname, member, isattr) in self.filter_members(members, want_all):
+ classes = [cls for cls in AutoDirective._registry.itervalues()
+ if cls.can_document_member(member, mname, isattr, self)]
+ if not classes:
+ # don't know how to document this member
+ continue
+ # prefer the documenter with the highest priority
+ classes.sort(key=lambda cls: cls.priority)
+ # give explicitly separated module name, so that members
+ # of inner classes can be documented
+ full_mname = self.modname + '::' + \
+ '.'.join(self.objpath + [mname])
+ documenter = classes[-1](self.directive, full_mname, self.indent)
+ memberdocumenters.append((documenter, isattr))
+ member_order = self.options.member_order or \
+ self.env.config.autodoc_member_order
+ if member_order == 'groupwise':
+ # sort by group; relies on stable sort to keep items in the
+ # same group sorted alphabetically
+ memberdocumenters.sort(key=lambda e: e[0].member_order)
+ elif member_order == 'bysource' and self.analyzer:
+ # sort by source order, by virtue of the module analyzer
+ tagorder = self.analyzer.tagorder
+ def keyfunc(entry):
+ fullname = entry[0].name.split('::')[1]
+ return tagorder.get(fullname, len(tagorder))
+ memberdocumenters.sort(key=keyfunc)
+
+ for documenter, isattr in memberdocumenters:
+ documenter.generate(
+ all_members=True, real_modname=self.real_modname,
+ check_module=members_check_module and not isattr)
+
+ # reset current objects
+ self.env.temp_data['autodoc:module'] = None
+ self.env.temp_data['autodoc:class'] = None
+
+ def generate(self, more_content=None, real_modname=None,
+ check_module=False, all_members=False):
+ """Generate reST for the object given by *self.name*, and possibly for
+ its members.
+
+ If *more_content* is given, include that content. If *real_modname* is
+ given, use that module name to find attribute docs. If *check_module* is
+ True, only generate if the object is defined in the module name it is
+ imported from. If *all_members* is True, document all members.
+ """
+ if not self.parse_name():
+ # need a module to import
+ self.directive.warn(
+ 'don\'t know which module to import for autodocumenting '
+ '%r (try placing a "module" or "currentmodule" directive '
+ 'in the document, or giving an explicit module name)'
+ % self.name)
+ return
+
+ # now, import the module and get object to document
+ if not self.import_object():
+ return
+
+ # If there is no real module defined, figure out which to use.
+ # The real module is used in the module analyzer to look up the module
+ # where the attribute documentation would actually be found in.
+ # This is used for situations where you have a module that collects the
+ # functions and classes of internal submodules.
+ self.real_modname = real_modname or self.get_real_modname()
+
+ # try to also get a source code analyzer for attribute docs
+ try:
+ self.analyzer = ModuleAnalyzer.for_module(self.real_modname)
+ # parse right now, to get PycodeErrors on parsing (results will
+ # be cached anyway)
+ self.analyzer.find_attr_docs()
+ except PycodeError, err:
+ self.env.app.debug('[autodoc] module analyzer failed: %s', err)
+ # no source file -- e.g. for builtin and C modules
+ self.analyzer = None
+ # at least add the module.__file__ as a dependency
+ if hasattr(self.module, '__file__') and self.module.__file__:
+ self.directive.filename_set.add(self.module.__file__)
+ else:
+ self.directive.filename_set.add(self.analyzer.srcname)
+
+ # check __module__ of object (for members not given explicitly)
+ if check_module:
+ if not self.check_module():
+ return
+
+ # make sure that the result starts with an empty line. This is
+ # necessary for some situations where another directive preprocesses
+ # reST and no starting newline is present
+ self.add_line(u'', '<autodoc>')
+
+ # format the object's signature, if any
+ sig = self.format_signature()
+
+ # generate the directive header and options, if applicable
+ self.add_directive_header(sig)
+ self.add_line(u'', '<autodoc>')
+
+ # e.g. the module directive doesn't have content
+ self.indent += self.content_indent
+
+ # add all content (from docstrings, attribute docs etc.)
+ self.add_content(more_content)
+
+ # document members, if possible
+ self.document_members(all_members)
+
+
+class ModuleDocumenter(Documenter):
+ """
+ Specialized Documenter subclass for modules.
+ """
+ objtype = 'module'
+ content_indent = u''
+ titles_allowed = True
+
+ option_spec = {
+ 'members': members_option, 'undoc-members': bool_option,
+ 'noindex': bool_option, 'inherited-members': bool_option,
+ 'show-inheritance': bool_option, 'synopsis': identity,
+ 'platform': identity, 'deprecated': bool_option,
+ 'member-order': identity, 'exclude-members': members_set_option,
+ 'private-members': bool_option, 'special-members': members_option,
+ 'imported-members': bool_option,
+ }
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ # don't document submodules automatically
+ return False
+
+ def resolve_name(self, modname, parents, path, base):
+ if modname is not None:
+ self.directive.warn('"::" in automodule name doesn\'t make sense')
+ return (path or '') + base, []
+
+ def parse_name(self):
+ ret = Documenter.parse_name(self)
+ if self.args or self.retann:
+ self.directive.warn('signature arguments or return annotation '
+ 'given for automodule %s' % self.fullname)
+ return ret
+
+ def add_directive_header(self, sig):
+ Documenter.add_directive_header(self, sig)
+
+ # add some module-specific options
+ if self.options.synopsis:
+ self.add_line(
+ u' :synopsis: ' + self.options.synopsis, '<autodoc>')
+ if self.options.platform:
+ self.add_line(
+ u' :platform: ' + self.options.platform, '<autodoc>')
+ if self.options.deprecated:
+ self.add_line(u' :deprecated:', '<autodoc>')
+
+ def get_object_members(self, want_all):
+ if want_all:
+ if not hasattr(self.object, '__all__'):
+ # for implicit module members, check __module__ to avoid
+ # documenting imported objects
+ return True, safe_getmembers(self.object)
+ else:
+ memberlist = self.object.__all__
+ else:
+ memberlist = self.options.members or []
+ ret = []
+ for mname in memberlist:
+ try:
+ ret.append((mname, safe_getattr(self.object, mname)))
+ except AttributeError:
+ self.directive.warn(
+ 'missing attribute mentioned in :members: or __all__: '
+ 'module %s, attribute %s' % (
+ safe_getattr(self.object, '__name__', '???'), mname))
+ return False, ret
+
+
+class ModuleLevelDocumenter(Documenter):
+ """
+ Specialized Documenter subclass for objects on module level (functions,
+ classes, data/constants).
+ """
+ def resolve_name(self, modname, parents, path, base):
+ if modname is None:
+ if path:
+ modname = path.rstrip('.')
+ else:
+ # if documenting a toplevel object without explicit module,
+ # it can be contained in another auto directive ...
+ modname = self.env.temp_data.get('autodoc:module')
+ # ... or in the scope of a module directive
+ if not modname:
+ modname = self.env.temp_data.get('py:module')
+ # ... else, it stays None, which means invalid
+ return modname, parents + [base]
+
+
+class ClassLevelDocumenter(Documenter):
+ """
+ Specialized Documenter subclass for objects on class level (methods,
+ attributes).
+ """
+ def resolve_name(self, modname, parents, path, base):
+ if modname is None:
+ if path:
+ mod_cls = path.rstrip('.')
+ else:
+ mod_cls = None
+ # if documenting a class-level object without path,
+ # there must be a current class, either from a parent
+ # auto directive ...
+ mod_cls = self.env.temp_data.get('autodoc:class')
+ # ... or from a class directive
+ if mod_cls is None:
+ mod_cls = self.env.temp_data.get('py:class')
+ # ... if still None, there's no way to know
+ if mod_cls is None:
+ return None, []
+ modname, cls = rpartition(mod_cls, '.')
+ parents = [cls]
+ # if the module name is still missing, get it like above
+ if not modname:
+ modname = self.env.temp_data.get('autodoc:module')
+ if not modname:
+ modname = self.env.temp_data.get('py:module')
+ # ... else, it stays None, which means invalid
+ return modname, parents + [base]
+
+
+class DocstringSignatureMixin(object):
+ """
+ Mixin for FunctionDocumenter and MethodDocumenter to provide the
+ feature of reading the signature from the docstring.
+ """
+
+ def _find_signature(self, encoding=None):
+ docstrings = Documenter.get_doc(self, encoding)
+ if len(docstrings) != 1:
+ return
+ doclines = docstrings[0]
+ setattr(self, '__new_doclines', doclines)
+ if not doclines:
+ return
+ # match first line of docstring against signature RE
+ match = py_ext_sig_re.match(doclines[0])
+ if not match:
+ return
+ exmod, path, base, args, retann = match.groups()
+ # the base name must match ours
+ if not self.objpath or base != self.objpath[-1]:
+ return
+ # re-prepare docstring to ignore indentation after signature
+ docstrings = Documenter.get_doc(self, encoding, 2)
+ doclines = docstrings[0]
+ # ok, now jump over remaining empty lines and set the remaining
+ # lines as the new doclines
+ i = 1
+ while i < len(doclines) and not doclines[i].strip():
+ i += 1
+ setattr(self, '__new_doclines', doclines[i:])
+ return args, retann
+
+ def get_doc(self, encoding=None, ignore=1):
+ lines = getattr(self, '__new_doclines', None)
+ if lines is not None:
+ return [lines]
+ return Documenter.get_doc(self, encoding, ignore)
+
+ def format_signature(self):
+ if self.args is None and self.env.config.autodoc_docstring_signature:
+ # only act if a signature is not explicitly given already, and if
+ # the feature is enabled
+ result = self._find_signature()
+ if result is not None:
+ self.args, self.retann = result
+ return Documenter.format_signature(self)
+
+
+class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
+ """
+ Specialized Documenter subclass for functions.
+ """
+ objtype = 'function'
+ member_order = 30
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ return isinstance(member, (FunctionType, BuiltinFunctionType))
+
+ def format_args(self):
+ if inspect.isbuiltin(self.object) or \
+ inspect.ismethoddescriptor(self.object):
+ # cannot introspect arguments of a C function or method
+ return None
+ try:
+ argspec = getargspec(self.object)
+ except TypeError:
+ if (is_builtin_class_method(self.object, '__new__') and
+ is_builtin_class_method(self.object, '__init__')):
+ raise TypeError('%r is a builtin class' % self.object)
+
+ # if a class should be documented as function (yay duck
+ # typing) we try to use the constructor signature as function
+ # signature without the first argument.
+ try:
+ argspec = getargspec(self.object.__new__)
+ except TypeError:
+ argspec = getargspec(self.object.__init__)
+ if argspec[0]:
+ del argspec[0][0]
+ args = inspect.formatargspec(*argspec)
+ # escape backslashes for reST
+ args = args.replace('\\', '\\\\')
+ return args
+
+ def document_members(self, all_members=False):
+ pass
+
+
+class ClassDocumenter(ModuleLevelDocumenter):
+ """
+ Specialized Documenter subclass for classes.
+ """
+ objtype = 'class'
+ member_order = 20
+ option_spec = {
+ 'members': members_option, 'undoc-members': bool_option,
+ 'noindex': bool_option, 'inherited-members': bool_option,
+ 'show-inheritance': bool_option, 'member-order': identity,
+ 'exclude-members': members_set_option,
+ 'private-members': bool_option, 'special-members': members_option,
+ }
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ return isinstance(member, class_types)
+
+ def import_object(self):
+ ret = ModuleLevelDocumenter.import_object(self)
+ # if the class is documented under another name, document it
+ # as data/attribute
+ if ret:
+ if hasattr(self.object, '__name__'):
+ self.doc_as_attr = (self.objpath[-1] != self.object.__name__)
+ else:
+ self.doc_as_attr = True
+ return ret
+
+ def format_args(self):
+ # for classes, the relevant signature is the __init__ method's
+ initmeth = self.get_attr(self.object, '__init__', None)
+ # classes without __init__ method, default __init__ or
+ # __init__ written in C?
+ if initmeth is None or \
+ is_builtin_class_method(self.object, '__init__') or \
+ not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
+ return None
+ try:
+ argspec = getargspec(initmeth)
+ except TypeError:
+ # still not possible: happens e.g. for old-style classes
+ # with __init__ in C
+ return None
+ if argspec[0] and argspec[0][0] in ('cls', 'self'):
+ del argspec[0][0]
+ return inspect.formatargspec(*argspec)
+
+ def format_signature(self):
+ if self.doc_as_attr:
+ return ''
+
+ # get __init__ method signature from __init__.__doc__
+ if self.env.config.autodoc_docstring_signature:
+ # only act if the feature is enabled
+ init_doc = MethodDocumenter(self.directive, '__init__')
+ init_doc.object = self.get_attr(self.object, '__init__', None)
+ init_doc.objpath = ['__init__']
+ result = init_doc._find_signature()
+ if result is not None:
+ # use args only for Class signature
+ return '(%s)' % result[0]
+
+ return ModuleLevelDocumenter.format_signature(self)
+
+ def add_directive_header(self, sig):
+ if self.doc_as_attr:
+ self.directivetype = 'attribute'
+ Documenter.add_directive_header(self, sig)
+
+ # add inheritance info, if wanted
+ if not self.doc_as_attr and self.options.show_inheritance:
+ self.add_line(u'', '<autodoc>')
+ if hasattr(self.object, '__bases__') and len(self.object.__bases__):
+ bases = [b.__module__ == '__builtin__' and
+ u':class:`%s`' % b.__name__ or
+ u':class:`%s.%s`' % (b.__module__, b.__name__)
+ for b in self.object.__bases__]
+ self.add_line(_(u' Bases: %s') % ', '.join(bases),
+ '<autodoc>')
+
+ def get_doc(self, encoding=None, ignore=1):
+ content = self.env.config.autoclass_content
+
+ docstrings = []
+ attrdocstring = self.get_attr(self.object, '__doc__', None)
+ if attrdocstring:
+ docstrings.append(attrdocstring)
+
+ # for classes, what the "docstring" is can be controlled via a
+ # config value; the default is only the class docstring
+ if content in ('both', 'init'):
+ # get __init__ method document from __init__.__doc__
+ if self.env.config.autodoc_docstring_signature:
+ # only act if the feature is enabled
+ init_doc = MethodDocumenter(self.directive, '__init__')
+ init_doc.object = self.get_attr(self.object, '__init__', None)
+ init_doc.objpath = ['__init__']
+ init_doc._find_signature() # this effects to get_doc() result
+ initdocstring = '\n'.join(
+ ['\n'.join(l) for l in init_doc.get_doc(encoding)])
+ else:
+ initdocstring = self.get_attr(
+ self.get_attr(self.object, '__init__', None), '__doc__')
+ # for new-style classes, no __init__ means default __init__
+ if (initdocstring is not None and
+ (initdocstring == object.__init__.__doc__ or # for pypy
+ initdocstring.strip() == object.__init__.__doc__)): #for !pypy
+ initdocstring = None
+ if initdocstring:
+ if content == 'init':
+ docstrings = [initdocstring]
+ else:
+ docstrings.append(initdocstring)
+ doc = []
+ for docstring in docstrings:
+ if not isinstance(docstring, unicode):
+ docstring = force_decode(docstring, encoding)
+ doc.append(prepare_docstring(docstring))
+ return doc
+
+ def add_content(self, more_content, no_docstring=False):
+ if self.doc_as_attr:
+ classname = safe_getattr(self.object, '__name__', None)
+ if classname:
+ content = ViewList(
+ [_('alias of :class:`%s`') % classname], source='')
+ ModuleLevelDocumenter.add_content(self, content,
+ no_docstring=True)
+ else:
+ ModuleLevelDocumenter.add_content(self, more_content)
+
+ def document_members(self, all_members=False):
+ if self.doc_as_attr:
+ return
+ ModuleLevelDocumenter.document_members(self, all_members)
+
+
+class ExceptionDocumenter(ClassDocumenter):
+ """
+ Specialized ClassDocumenter subclass for exceptions.
+ """
+ objtype = 'exception'
+ member_order = 10
+
+ # needs a higher priority than ClassDocumenter
+ priority = 10
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ return isinstance(member, class_types) and \
+ issubclass(member, base_exception)
+
+
+class DataDocumenter(ModuleLevelDocumenter):
+ """
+ Specialized Documenter subclass for data items.
+ """
+ objtype = 'data'
+ member_order = 40
+ priority = -10
+ option_spec = dict(ModuleLevelDocumenter.option_spec)
+ option_spec["annotation"] = annotation_option
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ return isinstance(parent, ModuleDocumenter) and isattr
+
+ def add_directive_header(self, sig):
+ ModuleLevelDocumenter.add_directive_header(self, sig)
+ if not self.options.annotation:
+ try:
+ objrepr = safe_repr(self.object)
+ except ValueError:
+ pass
+ else:
+ self.add_line(u' :annotation: = ' + objrepr, '<autodoc>')
+ elif self.options.annotation is SUPPRESS:
+ pass
+ else:
+ self.add_line(u' :annotation: %s' % self.options.annotation,
+ '<autodoc>')
+
+ def document_members(self, all_members=False):
+ pass
+
+
+class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
+ """
+ Specialized Documenter subclass for methods (normal, static and class).
+ """
+ objtype = 'method'
+ member_order = 50
+ priority = 1 # must be more than FunctionDocumenter
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ return inspect.isroutine(member) and \
+ not isinstance(parent, ModuleDocumenter)
+
+ if sys.version_info >= (3, 0):
+ def import_object(self):
+ ret = ClassLevelDocumenter.import_object(self)
+ if not ret:
+ return ret
+ obj_from_parent = self.parent.__dict__.get(self.object_name)
+ if isinstance(obj_from_parent, classmethod):
+ self.directivetype = 'classmethod'
+ self.member_order = self.member_order - 1
+ elif isinstance(obj_from_parent, staticmethod):
+ self.directivetype = 'staticmethod'
+ self.member_order = self.member_order - 1
+ else:
+ self.directivetype = 'method'
+ return ret
+ else:
+ def import_object(self):
+ ret = ClassLevelDocumenter.import_object(self)
+ if not ret:
+ return ret
+ if isinstance(self.object, classmethod) or \
+ (isinstance(self.object, MethodType) and
+ self.object.im_self is not None):
+ self.directivetype = 'classmethod'
+ # document class and static members before ordinary ones
+ self.member_order = self.member_order - 1
+ elif isinstance(self.object, FunctionType) or \
+ (isinstance(self.object, BuiltinFunctionType) and
+ hasattr(self.object, '__self__') and
+ self.object.__self__ is not None):
+ self.directivetype = 'staticmethod'
+ # document class and static members before ordinary ones
+ self.member_order = self.member_order - 1
+ else:
+ self.directivetype = 'method'
+ return ret
+
+ def format_args(self):
+ if inspect.isbuiltin(self.object) or \
+ inspect.ismethoddescriptor(self.object):
+ # can never get arguments of a C function or method
+ return None
+ argspec = getargspec(self.object)
+ if argspec[0] and argspec[0][0] in ('cls', 'self'):
+ del argspec[0][0]
+ args = inspect.formatargspec(*argspec)
+ # escape backslashes for reST
+ args = args.replace('\\', '\\\\')
+ return args
+
+ def document_members(self, all_members=False):
+ pass
+
+
+class AttributeDocumenter(ClassLevelDocumenter):
+ """
+ Specialized Documenter subclass for attributes.
+ """
+ objtype = 'attribute'
+ member_order = 60
+ option_spec = dict(ModuleLevelDocumenter.option_spec)
+ option_spec["annotation"] = annotation_option
+
+ # must be higher than the MethodDocumenter, else it will recognize
+ # some non-data descriptors as methods
+ priority = 10
+
+ method_types = (FunctionType, BuiltinFunctionType, MethodType)
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ isdatadesc = isdescriptor(member) and not \
+ isinstance(member, cls.method_types) and not \
+ type(member).__name__ in ("type", "method_descriptor",
+ "instancemethod")
+ return isdatadesc or (not isinstance(parent, ModuleDocumenter)
+ and not inspect.isroutine(member)
+ and not isinstance(member, class_types))
+
+ def document_members(self, all_members=False):
+ pass
+
+ def import_object(self):
+ ret = ClassLevelDocumenter.import_object(self)
+ if isdescriptor(self.object) and \
+ not isinstance(self.object, self.method_types):
+ self._datadescriptor = True
+ else:
+ # if it's not a data descriptor
+ self._datadescriptor = False
+ return ret
+
+ def get_real_modname(self):
+ return self.get_attr(self.parent or self.object, '__module__', None) \
+ or self.modname
+
+ def add_directive_header(self, sig):
+ ClassLevelDocumenter.add_directive_header(self, sig)
+ if not self.options.annotation:
+ if not self._datadescriptor:
+ try:
+ objrepr = safe_repr(self.object)
+ except ValueError:
+ pass
+ else:
+ self.add_line(u' :annotation: = ' + objrepr, '<autodoc>')
+ elif self.options.annotation is SUPPRESS:
+ pass
+ else:
+ self.add_line(u' :annotation: %s' % self.options.annotation,
+ '<autodoc>')
+
+ def add_content(self, more_content, no_docstring=False):
+ if not self._datadescriptor:
+ # if it's not a data descriptor, its docstring is very probably the
+ # wrong thing to display
+ no_docstring = True
+ ClassLevelDocumenter.add_content(self, more_content, no_docstring)
+
+
+class InstanceAttributeDocumenter(AttributeDocumenter):
+ """
+ Specialized Documenter subclass for attributes that cannot be imported
+ because they are instance attributes (e.g. assigned in __init__).
+ """
+ objtype = 'instanceattribute'
+ directivetype = 'attribute'
+ member_order = 60
+
+ # must be higher than AttributeDocumenter
+ priority = 11
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ """This documents only INSTANCEATTR members."""
+ return isattr and (member is INSTANCEATTR)
+
+ def import_object(self):
+ """Never import anything."""
+ # disguise as an attribute
+ self.objtype = 'attribute'
+ self._datadescriptor = False
+ return True
+
+ def add_content(self, more_content, no_docstring=False):
+ """Never try to get a docstring from the object."""
+ AttributeDocumenter.add_content(self, more_content, no_docstring=True)
+
+
+class AutoDirective(Directive):
+ """
+ The AutoDirective class is used for all autodoc directives. It dispatches
+ most of the work to one of the Documenters, which it selects through its
+ *_registry* dictionary.
+
+ The *_special_attrgetters* attribute is used to customize ``getattr()``
+ calls that the Documenters make; its entries are of the form ``type:
+ getattr_function``.
+
+ Note: When importing an object, all items along the import chain are
+ accessed using the descendant's *_special_attrgetters*, thus this
+ dictionary should include all necessary functions for accessing
+ attributes of the parents.
+ """
+ # a registry of objtype -> documenter class
+ _registry = {}
+
+ # a registry of type -> getattr function
+ _special_attrgetters = {}
+
+ # flags that can be given in autodoc_default_flags
+ _default_flags = set([
+ 'members', 'undoc-members', 'inherited-members', 'show-inheritance',
+ 'private-members', 'special-members',
+ ])
+
+ # standard docutils directive settings
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ # allow any options to be passed; the options are parsed further
+ # by the selected Documenter
+ option_spec = DefDict(identity)
+
+ def warn(self, msg):
+ self.warnings.append(self.reporter.warning(msg, line=self.lineno))
+
+ def run(self):
+ self.filename_set = set() # a set of dependent filenames
+ self.reporter = self.state.document.reporter
+ self.env = self.state.document.settings.env
+ self.warnings = []
+ self.result = ViewList()
+
+ try:
+ source, lineno = self.reporter.get_source_and_line(self.lineno)
+ except AttributeError:
+ source = lineno = None
+ self.env.app.debug('[autodoc] %s:%s: input:\n%s',
+ source, lineno, self.block_text)
+
+ # find out what documenter to call
+ objtype = self.name[4:]
+ doc_class = self._registry[objtype]
+ # add default flags
+ for flag in self._default_flags:
+ if flag not in doc_class.option_spec:
+ continue
+ negated = self.options.pop('no-' + flag, 'not given') is None
+ if flag in self.env.config.autodoc_default_flags and \
+ not negated:
+ self.options[flag] = None
+ # process the options with the selected documenter's option_spec
+ try:
+ self.genopt = Options(assemble_option_dict(
+ self.options.items(), doc_class.option_spec))
+ except (KeyError, ValueError, TypeError), err:
+ # an option is either unknown or has a wrong type
+ msg = self.reporter.error('An option to %s is either unknown or '
+ 'has an invalid value: %s' % (self.name, err),
+ line=self.lineno)
+ return [msg]
+ # generate the output
+ documenter = doc_class(self, self.arguments[0])
+ documenter.generate(more_content=self.content)
+ if not self.result:
+ return self.warnings
+
+ self.env.app.debug2('[autodoc] output:\n%s', '\n'.join(self.result))
+
+ # record all filenames as dependencies -- this will at least
+ # partially make automatic invalidation possible
+ for fn in self.filename_set:
+ self.state.document.settings.record_dependencies.add(fn)
+
+ # use a custom reporter that correctly assigns lines to source
+ # filename/description and lineno
+ old_reporter = self.state.memo.reporter
+ self.state.memo.reporter = AutodocReporter(self.result,
+ self.state.memo.reporter)
+
+ if documenter.titles_allowed:
+ node = nodes.section()
+ # necessary so that the child nodes get the right source/line set
+ node.document = self.state.document
+ nested_parse_with_titles(self.state, self.result, node)
+ else:
+ node = nodes.paragraph()
+ node.document = self.state.document
+ self.state.nested_parse(self.result, 0, node)
+ self.state.memo.reporter = old_reporter
+ return self.warnings + node.children
+
+
+def add_documenter(cls):
+ """Register a new Documenter."""
+ if not issubclass(cls, Documenter):
+ raise ExtensionError('autodoc documenter %r must be a subclass '
+ 'of Documenter' % cls)
+ # actually, it should be possible to override Documenters
+ #if cls.objtype in AutoDirective._registry:
+ # raise ExtensionError('autodoc documenter for %r is already '
+ # 'registered' % cls.objtype)
+ AutoDirective._registry[cls.objtype] = cls
+
+
+def setup(app):
+ app.add_autodocumenter(ModuleDocumenter)
+ app.add_autodocumenter(ClassDocumenter)
+ app.add_autodocumenter(ExceptionDocumenter)
+ app.add_autodocumenter(DataDocumenter)
+ app.add_autodocumenter(FunctionDocumenter)
+ app.add_autodocumenter(MethodDocumenter)
+ app.add_autodocumenter(AttributeDocumenter)
+ app.add_autodocumenter(InstanceAttributeDocumenter)
+
+ app.add_config_value('autoclass_content', 'class', True)
+ app.add_config_value('autodoc_member_order', 'alphabetic', True)
+ app.add_config_value('autodoc_default_flags', [], True)
+ app.add_config_value('autodoc_docstring_signature', True, True)
+ app.add_event('autodoc-process-docstring')
+ app.add_event('autodoc-process-signature')
+ app.add_event('autodoc-skip-member')
+
+
+class testcls:
+ """test doc string"""
+
+ def __getattr__(self, x):
+ return x
+
+ def __setattr__(self, x, y):
+ """Attr setter."""
diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py
new file mode 100644
index 0000000..c5c8f15
--- /dev/null
+++ b/sphinx/ext/autosummary/__init__.py
@@ -0,0 +1,570 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.autosummary
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx extension that adds an autosummary:: directive, which can be
+ used to generate function/method/attribute/etc. summary lists, similar
+ to those output eg. by Epydoc and other API doc generation tools.
+
+ An :autolink: role is also provided.
+
+ autosummary directive
+ ---------------------
+
+ The autosummary directive has the form::
+
+ .. autosummary::
+ :nosignatures:
+ :toctree: generated/
+
+ module.function_1
+ module.function_2
+ ...
+
+ and it generates an output table (containing signatures, optionally)
+
+ ======================== =============================================
+ module.function_1(args) Summary line from the docstring of function_1
+ module.function_2(args) Summary line from the docstring
+ ...
+ ======================== =============================================
+
+ If the :toctree: option is specified, files matching the function names
+ are inserted to the toctree with the given prefix:
+
+ generated/module.function_1
+ generated/module.function_2
+ ...
+
+ Note: The file names contain the module:: or currentmodule:: prefixes.
+
+ .. seealso:: autosummary_generate.py
+
+
+ autolink role
+ -------------
+
+ The autolink role functions as ``:obj:`` when the name referred can be
+ resolved to a Python object, and otherwise it becomes simple emphasis.
+ This can be used as the default role to make links 'smart'.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import sys
+import inspect
+import posixpath
+
+from docutils.parsers.rst import directives
+from docutils.statemachine import ViewList
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.util.compat import Directive
+from sphinx.pycode import ModuleAnalyzer, PycodeError
+
+
+# -- autosummary_toc node ------------------------------------------------------
+
+class autosummary_toc(nodes.comment):
+ pass
+
+def process_autosummary_toc(app, doctree):
+ """Insert items described in autosummary:: to the TOC tree, but do
+ not generate the toctree:: list.
+ """
+ env = app.builder.env
+ crawled = {}
+ def crawl_toc(node, depth=1):
+ crawled[node] = True
+ for j, subnode in enumerate(node):
+ try:
+ if (isinstance(subnode, autosummary_toc)
+ and isinstance(subnode[0], addnodes.toctree)):
+ env.note_toctree(env.docname, subnode[0])
+ continue
+ except IndexError:
+ continue
+ if not isinstance(subnode, nodes.section):
+ continue
+ if subnode not in crawled:
+ crawl_toc(subnode, depth+1)
+ crawl_toc(doctree)
+
+def autosummary_toc_visit_html(self, node):
+ """Hide autosummary toctree list in HTML output."""
+ raise nodes.SkipNode
+
+def autosummary_noop(self, node):
+ pass
+
+
+# -- autosummary_table node ----------------------------------------------------
+
+class autosummary_table(nodes.comment):
+ pass
+
+def autosummary_table_visit_html(self, node):
+ """Make the first column of the table non-breaking."""
+ try:
+ tbody = node[0][0][-1]
+ for row in tbody:
+ col1_entry = row[0]
+ par = col1_entry[0]
+ for j, subnode in enumerate(list(par)):
+ if isinstance(subnode, nodes.Text):
+ new_text = unicode(subnode.astext())
+ new_text = new_text.replace(u" ", u"\u00a0")
+ par[j] = nodes.Text(new_text)
+ except IndexError:
+ pass
+
+
+# -- autodoc integration -------------------------------------------------------
+
+class FakeDirective:
+ env = {}
+ genopt = {}
+
+def get_documenter(obj, parent):
+ """Get an autodoc.Documenter class suitable for documenting the given
+ object.
+
+ *obj* is the Python object to be documented, and *parent* is an
+ another Python object (e.g. a module or a class) to which *obj*
+ belongs to.
+ """
+ from sphinx.ext.autodoc import AutoDirective, DataDocumenter, \
+ ModuleDocumenter
+
+ if inspect.ismodule(obj):
+ # ModuleDocumenter.can_document_member always returns False
+ return ModuleDocumenter
+
+ # Construct a fake documenter for *parent*
+ if parent is not None:
+ parent_doc_cls = get_documenter(parent, None)
+ else:
+ parent_doc_cls = ModuleDocumenter
+
+ if hasattr(parent, '__name__'):
+ parent_doc = parent_doc_cls(FakeDirective(), parent.__name__)
+ else:
+ parent_doc = parent_doc_cls(FakeDirective(), "")
+
+ # Get the corrent documenter class for *obj*
+ classes = [cls for cls in AutoDirective._registry.values()
+ if cls.can_document_member(obj, '', False, parent_doc)]
+ if classes:
+ classes.sort(key=lambda cls: cls.priority)
+ return classes[-1]
+ else:
+ return DataDocumenter
+
+
+# -- .. autosummary:: ----------------------------------------------------------
+
+class Autosummary(Directive):
+ """
+ Pretty table containing short signatures and summaries of functions etc.
+
+ autosummary can also optionally generate a hidden toctree:: node.
+ """
+
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = False
+ has_content = True
+ option_spec = {
+ 'toctree': directives.unchanged,
+ 'nosignatures': directives.flag,
+ 'template': directives.unchanged,
+ }
+
+ def warn(self, msg):
+ self.warnings.append(self.state.document.reporter.warning(
+ msg, line=self.lineno))
+
+ def run(self):
+ self.env = env = self.state.document.settings.env
+ self.genopt = {}
+ self.warnings = []
+ self.result = ViewList()
+
+ names = [x.strip().split()[0] for x in self.content
+ if x.strip() and re.search(r'^[~a-zA-Z_]', x.strip()[0])]
+ items = self.get_items(names)
+ nodes = self.get_table(items)
+
+ if 'toctree' in self.options:
+ dirname = posixpath.dirname(env.docname)
+
+ tree_prefix = self.options['toctree'].strip()
+ docnames = []
+ for name, sig, summary, real_name in items:
+ docname = posixpath.join(tree_prefix, real_name)
+ docname = posixpath.normpath(posixpath.join(dirname, docname))
+ if docname not in env.found_docs:
+ self.warn('toctree references unknown document %r'
+ % docname)
+ docnames.append(docname)
+
+ tocnode = addnodes.toctree()
+ tocnode['includefiles'] = docnames
+ tocnode['entries'] = [(None, docname) for docname in docnames]
+ tocnode['maxdepth'] = -1
+ tocnode['glob'] = None
+
+ tocnode = autosummary_toc('', '', tocnode)
+ nodes.append(tocnode)
+
+ return self.warnings + nodes
+
+ def get_items(self, names):
+ """Try to import the given names, and return a list of
+ ``[(name, signature, summary_string, real_name), ...]``.
+ """
+ env = self.state.document.settings.env
+
+ prefixes = get_import_prefixes_from_env(env)
+
+ items = []
+
+ max_item_chars = 50
+
+ for name in names:
+ display_name = name
+ if name.startswith('~'):
+ name = name[1:]
+ display_name = name.split('.')[-1]
+
+ try:
+ real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes)
+ except ImportError:
+ self.warn('failed to import %s' % name)
+ items.append((name, '', '', name))
+ continue
+
+ self.result = ViewList() # initialize for each documenter
+ full_name = real_name
+ if full_name.startswith(modname + '.'):
+ # give explicitly separated module name, so that members
+ # of inner classes can be documented
+ full_name = modname + '::' + full_name[len(modname)+1:]
+ # NB. using full_name here is important, since Documenters
+ # handle module prefixes slightly differently
+ documenter = get_documenter(obj, parent)(self, full_name)
+ if not documenter.parse_name():
+ self.warn('failed to parse name %s' % real_name)
+ items.append((display_name, '', '', real_name))
+ continue
+ if not documenter.import_object():
+ self.warn('failed to import object %s' % real_name)
+ items.append((display_name, '', '', real_name))
+ continue
+
+ # try to also get a source code analyzer for attribute docs
+ try:
+ documenter.analyzer = ModuleAnalyzer.for_module(
+ documenter.get_real_modname())
+ # parse right now, to get PycodeErrors on parsing (results will
+ # be cached anyway)
+ documenter.analyzer.find_attr_docs()
+ except PycodeError, err:
+ documenter.env.app.debug(
+ '[autodoc] module analyzer failed: %s', err)
+ # no source file -- e.g. for builtin and C modules
+ documenter.analyzer = None
+
+ # -- Grab the signature
+
+ sig = documenter.format_signature()
+ if not sig:
+ sig = ''
+ else:
+ max_chars = max(10, max_item_chars - len(display_name))
+ sig = mangle_signature(sig, max_chars=max_chars)
+ sig = sig.replace('*', r'\*')
+
+ # -- Grab the summary
+
+ documenter.add_content(None)
+ doc = list(documenter.process_doc([self.result.data]))
+
+ while doc and not doc[0].strip():
+ doc.pop(0)
+
+ # If there's a blank line, then we can assume the first sentence /
+ # paragraph has ended, so anything after shouldn't be part of the
+ # summary
+ for i, piece in enumerate(doc):
+ if not piece.strip():
+ doc = doc[:i]
+ break
+
+ # Try to find the "first sentence", which may span multiple lines
+ m = re.search(r"^([A-Z].*?\.)(?:\s|$)", " ".join(doc).strip())
+ if m:
+ summary = m.group(1).strip()
+ elif doc:
+ summary = doc[0].strip()
+ else:
+ summary = ''
+
+ items.append((display_name, sig, summary, real_name))
+
+ return items
+
+ def get_table(self, items):
+ """Generate a proper list of table nodes for autosummary:: directive.
+
+ *items* is a list produced by :meth:`get_items`.
+ """
+ table_spec = addnodes.tabular_col_spec()
+ table_spec['spec'] = 'll'
+
+ table = autosummary_table('')
+ real_table = nodes.table('', classes=['longtable'])
+ table.append(real_table)
+ group = nodes.tgroup('', cols=2)
+ real_table.append(group)
+ group.append(nodes.colspec('', colwidth=10))
+ group.append(nodes.colspec('', colwidth=90))
+ body = nodes.tbody('')
+ group.append(body)
+
+ def append_row(*column_texts):
+ row = nodes.row('')
+ for text in column_texts:
+ node = nodes.paragraph('')
+ vl = ViewList()
+ vl.append(text, '<autosummary>')
+ self.state.nested_parse(vl, 0, node)
+ try:
+ if isinstance(node[0], nodes.paragraph):
+ node = node[0]
+ except IndexError:
+ pass
+ row.append(nodes.entry('', node))
+ body.append(row)
+
+ for name, sig, summary, real_name in items:
+ qualifier = 'obj'
+ if 'nosignatures' not in self.options:
+ col1 = ':%s:`%s <%s>`\ %s' % (qualifier, name, real_name, sig)
+ else:
+ col1 = ':%s:`%s <%s>`' % (qualifier, name, real_name)
+ col2 = summary
+ append_row(col1, col2)
+
+ return [table_spec, table]
+
+def mangle_signature(sig, max_chars=30):
+ """Reformat a function signature to a more compact form."""
+ s = re.sub(r"^\((.*)\)$", r"\1", sig).strip()
+
+ # Strip strings (which can contain things that confuse the code below)
+ s = re.sub(r"\\\\", "", s)
+ s = re.sub(r"\\'", "", s)
+ s = re.sub(r"'[^']*'", "", s)
+
+ # Parse the signature to arguments + options
+ args = []
+ opts = []
+
+ opt_re = re.compile(r"^(.*, |)([a-zA-Z0-9_*]+)=")
+ while s:
+ m = opt_re.search(s)
+ if not m:
+ # The rest are arguments
+ args = s.split(', ')
+ break
+
+ opts.insert(0, m.group(2))
+ s = m.group(1)[:-2]
+
+ # Produce a more compact signature
+ sig = limited_join(", ", args, max_chars=max_chars-2)
+ if opts:
+ if not sig:
+ sig = "[%s]" % limited_join(", ", opts, max_chars=max_chars-4)
+ elif len(sig) < max_chars - 4 - 2 - 3:
+ sig += "[, %s]" % limited_join(", ", opts,
+ max_chars=max_chars-len(sig)-4-2)
+
+ return u"(%s)" % sig
+
+def limited_join(sep, items, max_chars=30, overflow_marker="..."):
+ """Join a number of strings to one, limiting the length to *max_chars*.
+
+ If the string overflows this limit, replace the last fitting item by
+ *overflow_marker*.
+
+ Returns: joined_string
+ """
+ full_str = sep.join(items)
+ if len(full_str) < max_chars:
+ return full_str
+
+ n_chars = 0
+ n_items = 0
+ for j, item in enumerate(items):
+ n_chars += len(item) + len(sep)
+ if n_chars < max_chars - len(overflow_marker):
+ n_items += 1
+ else:
+ break
+
+ return sep.join(list(items[:n_items]) + [overflow_marker])
+
+# -- Importing items -----------------------------------------------------------
+
+def get_import_prefixes_from_env(env):
+ """
+ Obtain current Python import prefixes (for `import_by_name`)
+ from ``document.env``
+ """
+ prefixes = [None]
+
+ currmodule = env.temp_data.get('py:module')
+ if currmodule:
+ prefixes.insert(0, currmodule)
+
+ currclass = env.temp_data.get('py:class')
+ if currclass:
+ if currmodule:
+ prefixes.insert(0, currmodule + "." + currclass)
+ else:
+ prefixes.insert(0, currclass)
+
+ return prefixes
+
+def import_by_name(name, prefixes=[None]):
+ """Import a Python object that has the given *name*, under one of the
+ *prefixes*. The first name that succeeds is used.
+ """
+ tried = []
+ for prefix in prefixes:
+ try:
+ if prefix:
+ prefixed_name = '.'.join([prefix, name])
+ else:
+ prefixed_name = name
+ obj, parent, modname = _import_by_name(prefixed_name)
+ return prefixed_name, obj, parent, modname
+ except ImportError:
+ tried.append(prefixed_name)
+ raise ImportError('no module named %s' % ' or '.join(tried))
+
+def _import_by_name(name):
+ """Import a Python object given its full name."""
+ try:
+ name_parts = name.split('.')
+
+ # try first interpret `name` as MODNAME.OBJ
+ modname = '.'.join(name_parts[:-1])
+ if modname:
+ try:
+ __import__(modname)
+ mod = sys.modules[modname]
+ return getattr(mod, name_parts[-1]), mod, modname
+ except (ImportError, IndexError, AttributeError):
+ pass
+
+ # ... then as MODNAME, MODNAME.OBJ1, MODNAME.OBJ1.OBJ2, ...
+ last_j = 0
+ modname = None
+ for j in reversed(range(1, len(name_parts)+1)):
+ last_j = j
+ modname = '.'.join(name_parts[:j])
+ try:
+ __import__(modname)
+ except ImportError:
+ continue
+ if modname in sys.modules:
+ break
+
+ if last_j < len(name_parts):
+ parent = None
+ obj = sys.modules[modname]
+ for obj_name in name_parts[last_j:]:
+ parent = obj
+ obj = getattr(obj, obj_name)
+ return obj, parent, modname
+ else:
+ return sys.modules[modname], None, modname
+ except (ValueError, ImportError, AttributeError, KeyError), e:
+ raise ImportError(*e.args)
+
+
+# -- :autolink: (smart default role) -------------------------------------------
+
+def autolink_role(typ, rawtext, etext, lineno, inliner,
+ options={}, content=[]):
+ """Smart linking role.
+
+ Expands to ':obj:`text`' if `text` is an object that can be imported;
+ otherwise expands to '*text*'.
+ """
+ env = inliner.document.settings.env
+ r = env.get_domain('py').role('obj')(
+ 'obj', rawtext, etext, lineno, inliner, options, content)
+ pnode = r[0][0]
+
+ prefixes = get_import_prefixes_from_env(env)
+ try:
+ name, obj, parent, modname = import_by_name(pnode['reftarget'], prefixes)
+ except ImportError:
+ content = pnode[0]
+ r[0][0] = nodes.emphasis(rawtext, content[0].astext(),
+ classes=content['classes'])
+ return r
+
+
+def process_generate_options(app):
+ genfiles = app.config.autosummary_generate
+
+ ext = app.config.source_suffix
+
+ if genfiles and not hasattr(genfiles, '__len__'):
+ env = app.builder.env
+ genfiles = [x + ext for x in env.found_docs
+ if os.path.isfile(env.doc2path(x))]
+
+ if not genfiles:
+ return
+
+ from sphinx.ext.autosummary.generate import generate_autosummary_docs
+
+ genfiles = [genfile + (not genfile.endswith(ext) and ext or '')
+ for genfile in genfiles]
+
+ generate_autosummary_docs(genfiles, builder=app.builder,
+ warn=app.warn, info=app.info, suffix=ext,
+ base_path=app.srcdir)
+
+
+def setup(app):
+ # I need autodoc
+ app.setup_extension('sphinx.ext.autodoc')
+ app.add_node(autosummary_toc,
+ html=(autosummary_toc_visit_html, autosummary_noop),
+ latex=(autosummary_noop, autosummary_noop),
+ text=(autosummary_noop, autosummary_noop),
+ man=(autosummary_noop, autosummary_noop),
+ texinfo=(autosummary_noop, autosummary_noop))
+ app.add_node(autosummary_table,
+ html=(autosummary_table_visit_html, autosummary_noop),
+ latex=(autosummary_noop, autosummary_noop),
+ text=(autosummary_noop, autosummary_noop),
+ man=(autosummary_noop, autosummary_noop),
+ texinfo=(autosummary_noop, autosummary_noop))
+ app.add_directive('autosummary', Autosummary)
+ app.add_role('autolink', autolink_role)
+ app.connect('doctree-read', process_autosummary_toc)
+ app.connect('builder-inited', process_generate_options)
+ app.add_config_value('autosummary_generate', [], True)
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
new file mode 100644
index 0000000..47ef986
--- /dev/null
+++ b/sphinx/ext/autosummary/generate.py
@@ -0,0 +1,337 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.autosummary.generate
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Usable as a library or script to generate automatic RST source files for
+ items referred to in autosummary:: directives.
+
+ Each generated RST file contains a single auto*:: directive which
+ extracts the docstring of the referred item.
+
+ Example Makefile rule::
+
+ generate:
+ sphinx-autogen -o source/generated source/*.rst
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import sys
+import pydoc
+import optparse
+
+from jinja2 import FileSystemLoader, TemplateNotFound
+from jinja2.sandbox import SandboxedEnvironment
+
+from sphinx import package_dir
+from sphinx.ext.autosummary import import_by_name, get_documenter
+from sphinx.jinja2glue import BuiltinTemplateLoader
+from sphinx.util.osutil import ensuredir
+from sphinx.util.inspect import safe_getattr
+
+# Add documenters to AutoDirective registry
+from sphinx.ext.autodoc import add_documenter, \
+ ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, \
+ FunctionDocumenter, MethodDocumenter, AttributeDocumenter, \
+ InstanceAttributeDocumenter
+add_documenter(ModuleDocumenter)
+add_documenter(ClassDocumenter)
+add_documenter(ExceptionDocumenter)
+add_documenter(DataDocumenter)
+add_documenter(FunctionDocumenter)
+add_documenter(MethodDocumenter)
+add_documenter(AttributeDocumenter)
+add_documenter(InstanceAttributeDocumenter)
+
+
+def main(argv=sys.argv):
+ usage = """%prog [OPTIONS] SOURCEFILE ..."""
+ p = optparse.OptionParser(usage.strip())
+ p.add_option("-o", "--output-dir", action="store", type="string",
+ dest="output_dir", default=None,
+ help="Directory to place all output in")
+ p.add_option("-s", "--suffix", action="store", type="string",
+ dest="suffix", default="rst",
+ help="Default suffix for files (default: %default)")
+ p.add_option("-t", "--templates", action="store", type="string",
+ dest="templates", default=None,
+ help="Custom template directory (default: %default)")
+ options, args = p.parse_args(argv[1:])
+
+ if len(args) < 1:
+ p.error('no input files given')
+
+ generate_autosummary_docs(args, options.output_dir,
+ "." + options.suffix,
+ template_dir=options.templates)
+
+def _simple_info(msg):
+ print msg
+
+def _simple_warn(msg):
+ print >> sys.stderr, 'WARNING: ' + msg
+
+# -- Generating output ---------------------------------------------------------
+
+def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
+ warn=_simple_warn, info=_simple_info,
+ base_path=None, builder=None, template_dir=None):
+
+ showed_sources = list(sorted(sources))
+ if len(showed_sources) > 20:
+ showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:]
+ info('[autosummary] generating autosummary for: %s' %
+ ', '.join(showed_sources))
+
+ if output_dir:
+ info('[autosummary] writing to %s' % output_dir)
+
+ if base_path is not None:
+ sources = [os.path.join(base_path, filename) for filename in sources]
+
+ # create our own templating environment
+ template_dirs = [os.path.join(package_dir, 'ext',
+ 'autosummary', 'templates')]
+ if builder is not None:
+ # allow the user to override the templates
+ template_loader = BuiltinTemplateLoader()
+ template_loader.init(builder, dirs=template_dirs)
+ else:
+ if template_dir:
+ template_dirs.insert(0, template_dir)
+ template_loader = FileSystemLoader(template_dirs)
+ template_env = SandboxedEnvironment(loader=template_loader)
+
+ # read
+ items = find_autosummary_in_files(sources)
+
+ # remove possible duplicates
+ items = dict([(item, True) for item in items]).keys()
+
+ # keep track of new files
+ new_files = []
+
+ # write
+ for name, path, template_name in sorted(items, key=str):
+ if path is None:
+ # The corresponding autosummary:: directive did not have
+ # a :toctree: option
+ continue
+
+ path = output_dir or os.path.abspath(path)
+ ensuredir(path)
+
+ try:
+ name, obj, parent, mod_name = import_by_name(name)
+ except ImportError, e:
+ warn('[autosummary] failed to import %r: %s' % (name, e))
+ continue
+
+ fn = os.path.join(path, name + suffix)
+
+ # skip it if it exists
+ if os.path.isfile(fn):
+ continue
+
+ new_files.append(fn)
+
+ f = open(fn, 'w')
+
+ try:
+ doc = get_documenter(obj, parent)
+
+ if template_name is not None:
+ template = template_env.get_template(template_name)
+ else:
+ try:
+ template = template_env.get_template('autosummary/%s.rst'
+ % doc.objtype)
+ except TemplateNotFound:
+ template = template_env.get_template('autosummary/base.rst')
+
+ def get_members(obj, typ, include_public=[]):
+ items = []
+ for name in dir(obj):
+ try:
+ documenter = get_documenter(safe_getattr(obj, name),
+ obj)
+ except AttributeError:
+ continue
+ if documenter.objtype == typ:
+ items.append(name)
+ public = [x for x in items
+ if x in include_public or not x.startswith('_')]
+ return public, items
+
+ ns = {}
+
+ if doc.objtype == 'module':
+ ns['members'] = dir(obj)
+ ns['functions'], ns['all_functions'] = \
+ get_members(obj, 'function')
+ ns['classes'], ns['all_classes'] = \
+ get_members(obj, 'class')
+ ns['exceptions'], ns['all_exceptions'] = \
+ get_members(obj, 'exception')
+ elif doc.objtype == 'class':
+ ns['members'] = dir(obj)
+ ns['methods'], ns['all_methods'] = \
+ get_members(obj, 'method', ['__init__'])
+ ns['attributes'], ns['all_attributes'] = \
+ get_members(obj, 'attribute')
+
+ parts = name.split('.')
+ if doc.objtype in ('method', 'attribute'):
+ mod_name = '.'.join(parts[:-2])
+ cls_name = parts[-2]
+ obj_name = '.'.join(parts[-2:])
+ ns['class'] = cls_name
+ else:
+ mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]
+
+ ns['fullname'] = name
+ ns['module'] = mod_name
+ ns['objname'] = obj_name
+ ns['name'] = parts[-1]
+
+ ns['objtype'] = doc.objtype
+ ns['underline'] = len(name) * '='
+
+ rendered = template.render(**ns)
+ f.write(rendered)
+ finally:
+ f.close()
+
+ # descend recursively to new files
+ if new_files:
+ generate_autosummary_docs(new_files, output_dir=output_dir,
+ suffix=suffix, warn=warn, info=info,
+ base_path=base_path, builder=builder,
+ template_dir=template_dir)
+
+
+# -- Finding documented entries in files ---------------------------------------
+
+def find_autosummary_in_files(filenames):
+ """Find out what items are documented in source/*.rst.
+
+ See `find_autosummary_in_lines`.
+ """
+ documented = []
+ for filename in filenames:
+ f = open(filename, 'r')
+ lines = f.read().splitlines()
+ documented.extend(find_autosummary_in_lines(lines, filename=filename))
+ f.close()
+ return documented
+
+def find_autosummary_in_docstring(name, module=None, filename=None):
+ """Find out what items are documented in the given object's docstring.
+
+ See `find_autosummary_in_lines`.
+ """
+ try:
+ real_name, obj, parent, modname = import_by_name(name)
+ lines = pydoc.getdoc(obj).splitlines()
+ return find_autosummary_in_lines(lines, module=name, filename=filename)
+ except AttributeError:
+ pass
+ except ImportError, e:
+ print "Failed to import '%s': %s" % (name, e)
+ except SystemExit, e:
+ print("Failed to import '%s'; the module executes module level "
+ "statement and it might call sys.exit()." % name)
+ return []
+
+def find_autosummary_in_lines(lines, module=None, filename=None):
+ """Find out what items appear in autosummary:: directives in the
+ given lines.
+
+ Returns a list of (name, toctree, template) where *name* is a name
+ of an object and *toctree* the :toctree: path of the corresponding
+ autosummary directive (relative to the root of the file name), and
+ *template* the value of the :template: option. *toctree* and
+ *template* ``None`` if the directive does not have the
+ corresponding options set.
+ """
+ autosummary_re = re.compile(r'^(\s*)\.\.\s+autosummary::\s*')
+ automodule_re = re.compile(
+ r'^\s*\.\.\s+automodule::\s*([A-Za-z0-9_.]+)\s*$')
+ module_re = re.compile(
+ r'^\s*\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$')
+ autosummary_item_re = re.compile(r'^\s+(~?[_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?')
+ toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$')
+ template_arg_re = re.compile(r'^\s+:template:\s*(.*?)\s*$')
+
+ documented = []
+
+ toctree = None
+ template = None
+ current_module = module
+ in_autosummary = False
+ base_indent = ""
+
+ for line in lines:
+ if in_autosummary:
+ m = toctree_arg_re.match(line)
+ if m:
+ toctree = m.group(1)
+ if filename:
+ toctree = os.path.join(os.path.dirname(filename),
+ toctree)
+ continue
+
+ m = template_arg_re.match(line)
+ if m:
+ template = m.group(1).strip()
+ continue
+
+ if line.strip().startswith(':'):
+ continue # skip options
+
+ m = autosummary_item_re.match(line)
+ if m:
+ name = m.group(1).strip()
+ if name.startswith('~'):
+ name = name[1:]
+ if current_module and \
+ not name.startswith(current_module + '.'):
+ name = "%s.%s" % (current_module, name)
+ documented.append((name, toctree, template))
+ continue
+
+ if not line.strip() or line.startswith(base_indent + " "):
+ continue
+
+ in_autosummary = False
+
+ m = autosummary_re.match(line)
+ if m:
+ in_autosummary = True
+ base_indent = m.group(1)
+ toctree = None
+ template = None
+ continue
+
+ m = automodule_re.search(line)
+ if m:
+ current_module = m.group(1).strip()
+ # recurse into the automodule docstring
+ documented.extend(find_autosummary_in_docstring(
+ current_module, filename=filename))
+ continue
+
+ m = module_re.match(line)
+ if m:
+ current_module = m.group(2)
+ continue
+
+ return documented
+
+
+if __name__ == '__main__':
+ main()
diff --git a/sphinx/ext/autosummary/templates/autosummary/base.rst b/sphinx/ext/autosummary/templates/autosummary/base.rst
new file mode 100644
index 0000000..21a0ccd
--- /dev/null
+++ b/sphinx/ext/autosummary/templates/autosummary/base.rst
@@ -0,0 +1,6 @@
+{{ fullname }}
+{{ underline }}
+
+.. currentmodule:: {{ module }}
+
+.. auto{{ objtype }}:: {{ objname }}
diff --git a/sphinx/ext/autosummary/templates/autosummary/class.rst b/sphinx/ext/autosummary/templates/autosummary/class.rst
new file mode 100644
index 0000000..40494da
--- /dev/null
+++ b/sphinx/ext/autosummary/templates/autosummary/class.rst
@@ -0,0 +1,30 @@
+{{ fullname }}
+{{ underline }}
+
+.. currentmodule:: {{ module }}
+
+.. autoclass:: {{ objname }}
+
+ {% block methods %}
+ .. automethod:: __init__
+
+ {% if methods %}
+ .. rubric:: Methods
+
+ .. autosummary::
+ {% for item in methods %}
+ ~{{ name }}.{{ item }}
+ {%- endfor %}
+ {% endif %}
+ {% endblock %}
+
+ {% block attributes %}
+ {% if attributes %}
+ .. rubric:: Attributes
+
+ .. autosummary::
+ {% for item in attributes %}
+ ~{{ name }}.{{ item }}
+ {%- endfor %}
+ {% endif %}
+ {% endblock %}
diff --git a/sphinx/ext/autosummary/templates/autosummary/module.rst b/sphinx/ext/autosummary/templates/autosummary/module.rst
new file mode 100644
index 0000000..c14456b
--- /dev/null
+++ b/sphinx/ext/autosummary/templates/autosummary/module.rst
@@ -0,0 +1,37 @@
+{{ fullname }}
+{{ underline }}
+
+.. automodule:: {{ fullname }}
+
+ {% block functions %}
+ {% if functions %}
+ .. rubric:: Functions
+
+ .. autosummary::
+ {% for item in functions %}
+ {{ item }}
+ {%- endfor %}
+ {% endif %}
+ {% endblock %}
+
+ {% block classes %}
+ {% if classes %}
+ .. rubric:: Classes
+
+ .. autosummary::
+ {% for item in classes %}
+ {{ item }}
+ {%- endfor %}
+ {% endif %}
+ {% endblock %}
+
+ {% block exceptions %}
+ {% if exceptions %}
+ .. rubric:: Exceptions
+
+ .. autosummary::
+ {% for item in exceptions %}
+ {{ item }}
+ {%- endfor %}
+ {% endif %}
+ {% endblock %}
diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py
new file mode 100644
index 0000000..52be1bd
--- /dev/null
+++ b/sphinx/ext/coverage.py
@@ -0,0 +1,265 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.coverage
+ ~~~~~~~~~~~~~~~~~~~
+
+ Check Python modules and C API for coverage. Mostly written by Josip
+ Dzolonga for the Google Highly Open Participation contest.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import glob
+import inspect
+import cPickle as pickle
+from os import path
+
+from sphinx.builders import Builder
+
+
+# utility
+def write_header(f, text, char='-'):
+ f.write(text + '\n')
+ f.write(char * len(text) + '\n')
+
+def compile_regex_list(name, exps, warnfunc):
+ lst = []
+ for exp in exps:
+ try:
+ lst.append(re.compile(exp))
+ except Exception:
+ warnfunc('invalid regex %r in %s' % (exp, name))
+ return lst
+
+
+class CoverageBuilder(Builder):
+
+ name = 'coverage'
+
+ def init(self):
+ self.c_sourcefiles = []
+ for pattern in self.config.coverage_c_path:
+ pattern = path.join(self.srcdir, pattern)
+ self.c_sourcefiles.extend(glob.glob(pattern))
+
+ self.c_regexes = []
+ for (name, exp) in self.config.coverage_c_regexes.items():
+ try:
+ self.c_regexes.append((name, re.compile(exp)))
+ except Exception:
+ self.warn('invalid regex %r in coverage_c_regexes' % exp)
+
+ self.c_ignorexps = {}
+ for (name, exps) in self.config.coverage_ignore_c_items.iteritems():
+ self.c_ignorexps[name] = compile_regex_list(
+ 'coverage_ignore_c_items', exps, self.warn)
+ self.mod_ignorexps = compile_regex_list(
+ 'coverage_ignore_modules', self.config.coverage_ignore_modules,
+ self.warn)
+ self.cls_ignorexps = compile_regex_list(
+ 'coverage_ignore_classes', self.config.coverage_ignore_classes,
+ self.warn)
+ self.fun_ignorexps = compile_regex_list(
+ 'coverage_ignore_functions', self.config.coverage_ignore_functions,
+ self.warn)
+
+ def get_outdated_docs(self):
+ return 'coverage overview'
+
+ def write(self, *ignored):
+ self.py_undoc = {}
+ self.build_py_coverage()
+ self.write_py_coverage()
+
+ self.c_undoc = {}
+ self.build_c_coverage()
+ self.write_c_coverage()
+
+ def build_c_coverage(self):
+ # Fetch all the info from the header files
+ c_objects = self.env.domaindata['c']['objects']
+ for filename in self.c_sourcefiles:
+ undoc = []
+ f = open(filename, 'r')
+ try:
+ for line in f:
+ for key, regex in self.c_regexes:
+ match = regex.match(line)
+ if match:
+ name = match.groups()[0]
+ if name not in c_objects:
+ for exp in self.c_ignorexps.get(key, ()):
+ if exp.match(name):
+ break
+ else:
+ undoc.append((key, name))
+ continue
+ finally:
+ f.close()
+ if undoc:
+ self.c_undoc[filename] = undoc
+
+ def write_c_coverage(self):
+ output_file = path.join(self.outdir, 'c.txt')
+ op = open(output_file, 'w')
+ try:
+ if self.config.coverage_write_headline:
+ write_header(op, 'Undocumented C API elements', '=')
+ op.write('\n')
+
+ for filename, undoc in self.c_undoc.iteritems():
+ write_header(op, filename)
+ for typ, name in undoc:
+ op.write(' * %-50s [%9s]\n' % (name, typ))
+ op.write('\n')
+ finally:
+ op.close()
+
+ def build_py_coverage(self):
+ objects = self.env.domaindata['py']['objects']
+ modules = self.env.domaindata['py']['modules']
+
+ skip_undoc = self.config.coverage_skip_undoc_in_source
+
+ for mod_name in modules:
+ ignore = False
+ for exp in self.mod_ignorexps:
+ if exp.match(mod_name):
+ ignore = True
+ break
+ if ignore:
+ continue
+
+ try:
+ mod = __import__(mod_name, fromlist=['foo'])
+ except ImportError, err:
+ self.warn('module %s could not be imported: %s' %
+ (mod_name, err))
+ self.py_undoc[mod_name] = {'error': err}
+ continue
+
+ funcs = []
+ classes = {}
+
+ for name, obj in inspect.getmembers(mod):
+ # diverse module attributes are ignored:
+ if name[0] == '_':
+ # begins in an underscore
+ continue
+ if not hasattr(obj, '__module__'):
+ # cannot be attributed to a module
+ continue
+ if obj.__module__ != mod_name:
+ # is not defined in this module
+ continue
+
+ full_name = '%s.%s' % (mod_name, name)
+
+ if inspect.isfunction(obj):
+ if full_name not in objects:
+ for exp in self.fun_ignorexps:
+ if exp.match(name):
+ break
+ else:
+ if skip_undoc and not obj.__doc__:
+ continue
+ funcs.append(name)
+ elif inspect.isclass(obj):
+ for exp in self.cls_ignorexps:
+ if exp.match(name):
+ break
+ else:
+ if full_name not in objects:
+ if skip_undoc and not obj.__doc__:
+ continue
+ # not documented at all
+ classes[name] = []
+ continue
+
+ attrs = []
+
+ for attr_name in dir(obj):
+ if attr_name not in obj.__dict__:
+ continue
+ attr = getattr(obj, attr_name)
+ if not (inspect.ismethod(attr) or
+ inspect.isfunction(attr)):
+ continue
+ if attr_name[0] == '_':
+ # starts with an underscore, ignore it
+ continue
+ if skip_undoc and not attr.__doc__:
+ # skip methods without docstring if wished
+ continue
+
+ full_attr_name = '%s.%s' % (full_name, attr_name)
+ if full_attr_name not in objects:
+ attrs.append(attr_name)
+
+ if attrs:
+ # some attributes are undocumented
+ classes[name] = attrs
+
+ self.py_undoc[mod_name] = {'funcs': funcs, 'classes': classes}
+
+ def write_py_coverage(self):
+ output_file = path.join(self.outdir, 'python.txt')
+ op = open(output_file, 'w')
+ failed = []
+ try:
+ if self.config.coverage_write_headline:
+ write_header(op, 'Undocumented Python objects', '=')
+ keys = self.py_undoc.keys()
+ keys.sort()
+ for name in keys:
+ undoc = self.py_undoc[name]
+ if 'error' in undoc:
+ failed.append((name, undoc['error']))
+ else:
+ if not undoc['classes'] and not undoc['funcs']:
+ continue
+
+ write_header(op, name)
+ if undoc['funcs']:
+ op.write('Functions:\n')
+ op.writelines(' * %s\n' % x for x in undoc['funcs'])
+ op.write('\n')
+ if undoc['classes']:
+ op.write('Classes:\n')
+ for name, methods in sorted(
+ undoc['classes'].iteritems()):
+ if not methods:
+ op.write(' * %s\n' % name)
+ else:
+ op.write(' * %s -- missing methods:\n\n' % name)
+ op.writelines(' - %s\n' % x for x in methods)
+ op.write('\n')
+
+ if failed:
+ write_header(op, 'Modules that failed to import')
+ op.writelines(' * %s -- %s\n' % x for x in failed)
+ finally:
+ op.close()
+
+ def finish(self):
+ # dump the coverage data to a pickle file too
+ picklepath = path.join(self.outdir, 'undoc.pickle')
+ dumpfile = open(picklepath, 'wb')
+ try:
+ pickle.dump((self.py_undoc, self.c_undoc), dumpfile)
+ finally:
+ dumpfile.close()
+
+
+def setup(app):
+ app.add_builder(CoverageBuilder)
+ app.add_config_value('coverage_ignore_modules', [], False)
+ app.add_config_value('coverage_ignore_functions', [], False)
+ app.add_config_value('coverage_ignore_classes', [], False)
+ app.add_config_value('coverage_c_path', [], False)
+ app.add_config_value('coverage_c_regexes', {}, False)
+ app.add_config_value('coverage_ignore_c_items', {}, False)
+ app.add_config_value('coverage_write_headline', True, False)
+ app.add_config_value('coverage_skip_undoc_in_source', False, False)
diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py
new file mode 100644
index 0000000..70beb9b
--- /dev/null
+++ b/sphinx/ext/doctest.py
@@ -0,0 +1,437 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.doctest
+ ~~~~~~~~~~~~~~~~~~
+
+ Mimic doctest by automatically executing code snippets and checking
+ their results.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import sys
+import time
+import codecs
+import StringIO
+from os import path
+# circumvent relative import
+doctest = __import__('doctest')
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+
+from sphinx.builders import Builder
+from sphinx.util import force_decode
+from sphinx.util.nodes import set_source_info
+from sphinx.util.compat import Directive
+from sphinx.util.console import bold
+from sphinx.util.pycompat import bytes
+
+blankline_re = re.compile(r'^\s*<BLANKLINE>', re.MULTILINE)
+doctestopt_re = re.compile(r'#\s*doctest:.+$', re.MULTILINE)
+
+# set up the necessary directives
+
+class TestDirective(Directive):
+ """
+ Base class for doctest-related directives.
+ """
+
+ has_content = True
+ required_arguments = 0
+ optional_arguments = 1
+ final_argument_whitespace = True
+
+ def run(self):
+ # use ordinary docutils nodes for test code: they get special attributes
+ # so that our builder recognizes them, and the other builders are happy.
+ code = '\n'.join(self.content)
+ test = None
+ if self.name == 'doctest':
+ if '<BLANKLINE>' in code:
+ # convert <BLANKLINE>s to ordinary blank lines for presentation
+ test = code
+ code = blankline_re.sub('', code)
+ if doctestopt_re.search(code):
+ if not test:
+ test = code
+ code = doctestopt_re.sub('', code)
+ nodetype = nodes.literal_block
+ if self.name in ('testsetup', 'testcleanup') or 'hide' in self.options:
+ nodetype = nodes.comment
+ if self.arguments:
+ groups = [x.strip() for x in self.arguments[0].split(',')]
+ else:
+ groups = ['default']
+ node = nodetype(code, code, testnodetype=self.name, groups=groups)
+ set_source_info(self, node)
+ if test is not None:
+ # only save if it differs from code
+ node['test'] = test
+ if self.name == 'testoutput':
+ # don't try to highlight output
+ node['language'] = 'none'
+ node['options'] = {}
+ if self.name in ('doctest', 'testoutput') and 'options' in self.options:
+ # parse doctest-like output comparison flags
+ option_strings = self.options['options'].replace(',', ' ').split()
+ for option in option_strings:
+ if (option[0] not in '+-' or option[1:] not in
+ doctest.OPTIONFLAGS_BY_NAME):
+ # XXX warn?
+ continue
+ flag = doctest.OPTIONFLAGS_BY_NAME[option[1:]]
+ node['options'][flag] = (option[0] == '+')
+ return [node]
+
+class TestsetupDirective(TestDirective):
+ option_spec = {}
+
+class TestcleanupDirective(TestDirective):
+ option_spec = {}
+
+class DoctestDirective(TestDirective):
+ option_spec = {
+ 'hide': directives.flag,
+ 'options': directives.unchanged,
+ }
+
+class TestcodeDirective(TestDirective):
+ option_spec = {
+ 'hide': directives.flag,
+ }
+
+class TestoutputDirective(TestDirective):
+ option_spec = {
+ 'hide': directives.flag,
+ 'options': directives.unchanged,
+ }
+
+
+parser = doctest.DocTestParser()
+
+# helper classes
+
+class TestGroup(object):
+ def __init__(self, name):
+ self.name = name
+ self.setup = []
+ self.tests = []
+ self.cleanup = []
+
+ def add_code(self, code, prepend=False):
+ if code.type == 'testsetup':
+ if prepend:
+ self.setup.insert(0, code)
+ else:
+ self.setup.append(code)
+ elif code.type == 'testcleanup':
+ self.cleanup.append(code)
+ elif code.type == 'doctest':
+ self.tests.append([code])
+ elif code.type == 'testcode':
+ self.tests.append([code, None])
+ elif code.type == 'testoutput':
+ if self.tests and len(self.tests[-1]) == 2:
+ self.tests[-1][1] = code
+ else:
+ raise RuntimeError('invalid TestCode type')
+
+ def __repr__(self):
+ return 'TestGroup(name=%r, setup=%r, cleanup=%r, tests=%r)' % (
+ self.name, self.setup, self.cleanup, self.tests)
+
+
+class TestCode(object):
+ def __init__(self, code, type, lineno, options=None):
+ self.code = code
+ self.type = type
+ self.lineno = lineno
+ self.options = options or {}
+
+ def __repr__(self):
+ return 'TestCode(%r, %r, %r, options=%r)' % (
+ self.code, self.type, self.lineno, self.options)
+
+
+class SphinxDocTestRunner(doctest.DocTestRunner):
+ def summarize(self, out, verbose=None):
+ string_io = StringIO.StringIO()
+ old_stdout = sys.stdout
+ sys.stdout = string_io
+ try:
+ res = doctest.DocTestRunner.summarize(self, verbose)
+ finally:
+ sys.stdout = old_stdout
+ out(string_io.getvalue())
+ return res
+
+ def _DocTestRunner__patched_linecache_getlines(self, filename,
+ module_globals=None):
+ # this is overridden from DocTestRunner adding the try-except below
+ m = self._DocTestRunner__LINECACHE_FILENAME_RE.match(filename)
+ if m and m.group('name') == self.test.name:
+ try:
+ example = self.test.examples[int(m.group('examplenum'))]
+ # because we compile multiple doctest blocks with the same name
+ # (viz. the group name) this might, for outer stack frames in a
+ # traceback, get the wrong test which might not have enough examples
+ except IndexError:
+ pass
+ else:
+ return example.source.splitlines(True)
+ return self.save_linecache_getlines(filename, module_globals)
+
+
+# the new builder -- use sphinx-build.py -b doctest to run
+
+class DocTestBuilder(Builder):
+ """
+ Runs test snippets in the documentation.
+ """
+ name = 'doctest'
+
+ def init(self):
+ # default options
+ self.opt = doctest.DONT_ACCEPT_TRUE_FOR_1 | doctest.ELLIPSIS | \
+ doctest.IGNORE_EXCEPTION_DETAIL
+
+ # HACK HACK HACK
+ # doctest compiles its snippets with type 'single'. That is nice
+ # for doctest examples but unusable for multi-statement code such
+ # as setup code -- to be able to use doctest error reporting with
+ # that code nevertheless, we monkey-patch the "compile" it uses.
+ doctest.compile = self.compile
+
+ sys.path[0:0] = self.config.doctest_path
+
+ self.type = 'single'
+
+ self.total_failures = 0
+ self.total_tries = 0
+ self.setup_failures = 0
+ self.setup_tries = 0
+ self.cleanup_failures = 0
+ self.cleanup_tries = 0
+
+ date = time.strftime('%Y-%m-%d %H:%M:%S')
+
+ self.outfile = codecs.open(path.join(self.outdir, 'output.txt'),
+ 'w', encoding='utf-8')
+ self.outfile.write('''\
+Results of doctest builder run on %s
+==================================%s
+''' % (date, '='*len(date)))
+
+ def _out(self, text):
+ self.info(text, nonl=True)
+ self.outfile.write(text)
+
+ def _warn_out(self, text):
+ self.info(text, nonl=True)
+ if self.app.quiet:
+ self.warn(text)
+ if isinstance(text, bytes):
+ text = force_decode(text, None)
+ self.outfile.write(text)
+
+ def get_target_uri(self, docname, typ=None):
+ return ''
+
+ def get_outdated_docs(self):
+ return self.env.found_docs
+
+ def finish(self):
+ # write executive summary
+ def s(v):
+ return v != 1 and 's' or ''
+ self._out('''
+Doctest summary
+===============
+%5d test%s
+%5d failure%s in tests
+%5d failure%s in setup code
+%5d failure%s in cleanup code
+''' % (self.total_tries, s(self.total_tries),
+ self.total_failures, s(self.total_failures),
+ self.setup_failures, s(self.setup_failures),
+ self.cleanup_failures, s(self.cleanup_failures)))
+ self.outfile.close()
+
+ if self.total_failures or self.setup_failures or self.cleanup_failures:
+ self.app.statuscode = 1
+
+ def write(self, build_docnames, updated_docnames, method='update'):
+ if build_docnames is None:
+ build_docnames = sorted(self.env.all_docs)
+
+ self.info(bold('running tests...'))
+ for docname in build_docnames:
+ # no need to resolve the doctree
+ doctree = self.env.get_doctree(docname)
+ self.test_doc(docname, doctree)
+
+ def test_doc(self, docname, doctree):
+ groups = {}
+ add_to_all_groups = []
+ self.setup_runner = SphinxDocTestRunner(verbose=False,
+ optionflags=self.opt)
+ self.test_runner = SphinxDocTestRunner(verbose=False,
+ optionflags=self.opt)
+ self.cleanup_runner = SphinxDocTestRunner(verbose=False,
+ optionflags=self.opt)
+
+ self.test_runner._fakeout = self.setup_runner._fakeout
+ self.cleanup_runner._fakeout = self.setup_runner._fakeout
+
+ if self.config.doctest_test_doctest_blocks:
+ def condition(node):
+ return (isinstance(node, (nodes.literal_block, nodes.comment))
+ and node.has_key('testnodetype')) or \
+ isinstance(node, nodes.doctest_block)
+ else:
+ def condition(node):
+ return isinstance(node, (nodes.literal_block, nodes.comment)) \
+ and node.has_key('testnodetype')
+ for node in doctree.traverse(condition):
+ source = node.has_key('test') and node['test'] or node.astext()
+ if not source:
+ self.warn('no code/output in %s block at %s:%s' %
+ (node.get('testnodetype', 'doctest'),
+ self.env.doc2path(docname), node.line))
+ code = TestCode(source, type=node.get('testnodetype', 'doctest'),
+ lineno=node.line, options=node.get('options'))
+ node_groups = node.get('groups', ['default'])
+ if '*' in node_groups:
+ add_to_all_groups.append(code)
+ continue
+ for groupname in node_groups:
+ if groupname not in groups:
+ groups[groupname] = TestGroup(groupname)
+ groups[groupname].add_code(code)
+ for code in add_to_all_groups:
+ for group in groups.itervalues():
+ group.add_code(code)
+ if self.config.doctest_global_setup:
+ code = TestCode(self.config.doctest_global_setup,
+ 'testsetup', lineno=0)
+ for group in groups.itervalues():
+ group.add_code(code, prepend=True)
+ if self.config.doctest_global_cleanup:
+ code = TestCode(self.config.doctest_global_cleanup,
+ 'testcleanup', lineno=0)
+ for group in groups.itervalues():
+ group.add_code(code)
+ if not groups:
+ return
+
+ self._out('\nDocument: %s\n----------%s\n' %
+ (docname, '-'*len(docname)))
+ for group in groups.itervalues():
+ self.test_group(group, self.env.doc2path(docname, base=None))
+ # Separately count results from setup code
+ res_f, res_t = self.setup_runner.summarize(self._out, verbose=False)
+ self.setup_failures += res_f
+ self.setup_tries += res_t
+ if self.test_runner.tries:
+ res_f, res_t = self.test_runner.summarize(self._out, verbose=True)
+ self.total_failures += res_f
+ self.total_tries += res_t
+ if self.cleanup_runner.tries:
+ res_f, res_t = self.cleanup_runner.summarize(self._out,
+ verbose=True)
+ self.cleanup_failures += res_f
+ self.cleanup_tries += res_t
+
+ def compile(self, code, name, type, flags, dont_inherit):
+ return compile(code, name, self.type, flags, dont_inherit)
+
+ def test_group(self, group, filename):
+ ns = {}
+
+ def run_setup_cleanup(runner, testcodes, what):
+ examples = []
+ for testcode in testcodes:
+ examples.append(doctest.Example(testcode.code, '',
+ lineno=testcode.lineno))
+ if not examples:
+ return True
+ # simulate a doctest with the code
+ sim_doctest = doctest.DocTest(examples, {},
+ '%s (%s code)' % (group.name, what),
+ filename, 0, None)
+ sim_doctest.globs = ns
+ old_f = runner.failures
+ self.type = 'exec' # the snippet may contain multiple statements
+ runner.run(sim_doctest, out=self._warn_out, clear_globs=False)
+ if runner.failures > old_f:
+ return False
+ return True
+
+ # run the setup code
+ if not run_setup_cleanup(self.setup_runner, group.setup, 'setup'):
+ # if setup failed, don't run the group
+ return
+
+ # run the tests
+ for code in group.tests:
+ if len(code) == 1:
+ # ordinary doctests (code/output interleaved)
+ try:
+ test = parser.get_doctest(code[0].code, {}, group.name,
+ filename, code[0].lineno)
+ except Exception:
+ self.warn('ignoring invalid doctest code: %r' %
+ code[0].code,
+ '%s:%s' % (filename, code[0].lineno))
+ continue
+ if not test.examples:
+ continue
+ for example in test.examples:
+ # apply directive's comparison options
+ new_opt = code[0].options.copy()
+ new_opt.update(example.options)
+ example.options = new_opt
+ self.type = 'single' # as for ordinary doctests
+ else:
+ # testcode and output separate
+ output = code[1] and code[1].code or ''
+ options = code[1] and code[1].options or {}
+ # disable <BLANKLINE> processing as it is not needed
+ options[doctest.DONT_ACCEPT_BLANKLINE] = True
+ # find out if we're testing an exception
+ m = parser._EXCEPTION_RE.match(output)
+ if m:
+ exc_msg = m.group('msg')
+ else:
+ exc_msg = None
+ example = doctest.Example(code[0].code, output,
+ exc_msg=exc_msg,
+ lineno=code[0].lineno,
+ options=options)
+ test = doctest.DocTest([example], {}, group.name,
+ filename, code[0].lineno, None)
+ self.type = 'exec' # multiple statements again
+ # DocTest.__init__ copies the globs namespace, which we don't want
+ test.globs = ns
+ # also don't clear the globs namespace after running the doctest
+ self.test_runner.run(test, out=self._warn_out, clear_globs=False)
+
+ # run the cleanup
+ run_setup_cleanup(self.cleanup_runner, group.cleanup, 'cleanup')
+
+
+def setup(app):
+ app.add_directive('testsetup', TestsetupDirective)
+ app.add_directive('testcleanup', TestcleanupDirective)
+ app.add_directive('doctest', DoctestDirective)
+ app.add_directive('testcode', TestcodeDirective)
+ app.add_directive('testoutput', TestoutputDirective)
+ app.add_builder(DocTestBuilder)
+ # this config value adds to sys.path
+ app.add_config_value('doctest_path', [], False)
+ app.add_config_value('doctest_test_doctest_blocks', 'default', False)
+ app.add_config_value('doctest_global_setup', '', False)
+ app.add_config_value('doctest_global_cleanup', '', False)
diff --git a/sphinx/ext/extlinks.py b/sphinx/ext/extlinks.py
new file mode 100644
index 0000000..18da573
--- /dev/null
+++ b/sphinx/ext/extlinks.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.extlinks
+ ~~~~~~~~~~~~~~~~~~~
+
+ Extension to save typing and prevent hard-coding of base URLs in the reST
+ files.
+
+ This adds a new config value called ``extlinks`` that is created like this::
+
+ extlinks = {'exmpl': ('http://example.com/%s.html', prefix), ...}
+
+ Now you can use e.g. :exmpl:`foo` in your documents. This will create a
+ link to ``http://example.com/foo.html``. The link caption depends on the
+ *prefix* value given:
+
+ - If it is ``None``, the caption will be the full URL.
+ - If it is a string (empty or not), the caption will be the prefix prepended
+ to the role content.
+
+ You can also give an explicit caption, e.g. :exmpl:`Foo <foo>`.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes, utils
+
+from sphinx.util.nodes import split_explicit_title
+
+
+def make_link_role(base_url, prefix):
+ def role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
+ text = utils.unescape(text)
+ has_explicit_title, title, part = split_explicit_title(text)
+ try:
+ full_url = base_url % part
+ except (TypeError, ValueError):
+ inliner.reporter.warning(
+ 'unable to expand %s extlink with base URL %r, please make '
+ 'sure the base contains \'%%s\' exactly once'
+ % (typ, base_url), line=lineno)
+ full_url = base_url + part
+ if not has_explicit_title:
+ if prefix is None:
+ title = full_url
+ else:
+ title = prefix + part
+ pnode = nodes.reference(title, title, internal=False, refuri=full_url)
+ return [pnode], []
+ return role
+
+def setup_link_roles(app):
+ for name, (base_url, prefix) in app.config.extlinks.iteritems():
+ app.add_role(name, make_link_role(base_url, prefix))
+
+def setup(app):
+ app.add_config_value('extlinks', {}, 'env')
+ app.connect('builder-inited', setup_link_roles)
diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py
new file mode 100644
index 0000000..028560b
--- /dev/null
+++ b/sphinx/ext/graphviz.py
@@ -0,0 +1,323 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.graphviz
+ ~~~~~~~~~~~~~~~~~~~
+
+ Allow graphviz-formatted graphs to be included in Sphinx-generated
+ documents inline.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import codecs
+import posixpath
+from os import path
+from subprocess import Popen, PIPE
+try:
+ from hashlib import sha1 as sha
+except ImportError:
+ from sha import sha
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+
+from sphinx.errors import SphinxError
+from sphinx.locale import _
+from sphinx.util.osutil import ensuredir, ENOENT, EPIPE, EINVAL
+from sphinx.util.compat import Directive
+
+
+mapname_re = re.compile(r'<map id="(.*?)"')
+
+
+class GraphvizError(SphinxError):
+ category = 'Graphviz error'
+
+
+class graphviz(nodes.General, nodes.Element):
+ pass
+
+
+class Graphviz(Directive):
+ """
+ Directive to insert arbitrary dot markup.
+ """
+ has_content = True
+ required_arguments = 0
+ optional_arguments = 1
+ final_argument_whitespace = False
+ option_spec = {
+ 'alt': directives.unchanged,
+ 'inline': directives.flag,
+ 'caption': directives.unchanged,
+ }
+
+ def run(self):
+ if self.arguments:
+ document = self.state.document
+ if self.content:
+ return [document.reporter.warning(
+ 'Graphviz directive cannot have both content and '
+ 'a filename argument', line=self.lineno)]
+ env = self.state.document.settings.env
+ rel_filename, filename = env.relfn2path(self.arguments[0])
+ env.note_dependency(rel_filename)
+ try:
+ fp = codecs.open(filename, 'r', 'utf-8')
+ try:
+ dotcode = fp.read()
+ finally:
+ fp.close()
+ except (IOError, OSError):
+ return [document.reporter.warning(
+ 'External Graphviz file %r not found or reading '
+ 'it failed' % filename, line=self.lineno)]
+ else:
+ dotcode = '\n'.join(self.content)
+ if not dotcode.strip():
+ return [self.state_machine.reporter.warning(
+ 'Ignoring "graphviz" directive without content.',
+ line=self.lineno)]
+ node = graphviz()
+ node['code'] = dotcode
+ node['options'] = []
+ if 'alt' in self.options:
+ node['alt'] = self.options['alt']
+ if 'caption' in self.options:
+ node['caption'] = self.options['caption']
+ node['inline'] = 'inline' in self.options
+ return [node]
+
+
+class GraphvizSimple(Directive):
+ """
+ Directive to insert arbitrary dot markup.
+ """
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {
+ 'alt': directives.unchanged,
+ 'inline': directives.flag,
+ 'caption': directives.unchanged,
+ }
+
+ def run(self):
+ node = graphviz()
+ node['code'] = '%s %s {\n%s\n}\n' % \
+ (self.name, self.arguments[0], '\n'.join(self.content))
+ node['options'] = []
+ if 'alt' in self.options:
+ node['alt'] = self.options['alt']
+ if 'caption' in self.options:
+ node['caption'] = self.options['caption']
+ node['inline'] = 'inline' in self.options
+ return [node]
+
+
+def render_dot(self, code, options, format, prefix='graphviz'):
+ """Render graphviz code into a PNG or PDF output file."""
+ hashkey = (code + str(options) + \
+ str(self.builder.config.graphviz_dot) + \
+ str(self.builder.config.graphviz_dot_args)
+ ).encode('utf-8')
+
+ fname = '%s-%s.%s' % (prefix, sha(hashkey).hexdigest(), format)
+ if hasattr(self.builder, 'imgpath'):
+ # HTML
+ relfn = posixpath.join(self.builder.imgpath, fname)
+ outfn = path.join(self.builder.outdir, '_images', fname)
+ else:
+ # LaTeX
+ relfn = fname
+ outfn = path.join(self.builder.outdir, fname)
+
+ if path.isfile(outfn):
+ return relfn, outfn
+
+ if hasattr(self.builder, '_graphviz_warned_dot') or \
+ hasattr(self.builder, '_graphviz_warned_ps2pdf'):
+ return None, None
+
+ ensuredir(path.dirname(outfn))
+
+ # graphviz expects UTF-8 by default
+ if isinstance(code, unicode):
+ code = code.encode('utf-8')
+
+ dot_args = [self.builder.config.graphviz_dot]
+ dot_args.extend(self.builder.config.graphviz_dot_args)
+ dot_args.extend(options)
+ dot_args.extend(['-T' + format, '-o' + outfn])
+ if format == 'png':
+ dot_args.extend(['-Tcmapx', '-o%s.map' % outfn])
+ try:
+ p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE)
+ except OSError, err:
+ if err.errno != ENOENT: # No such file or directory
+ raise
+ self.builder.warn('dot command %r cannot be run (needed for graphviz '
+ 'output), check the graphviz_dot setting' %
+ self.builder.config.graphviz_dot)
+ self.builder._graphviz_warned_dot = True
+ return None, None
+ try:
+ # Graphviz may close standard input when an error occurs,
+ # resulting in a broken pipe on communicate()
+ stdout, stderr = p.communicate(code)
+ except (OSError, IOError), err:
+ if err.errno not in (EPIPE, EINVAL):
+ raise
+ # in this case, read the standard output and standard error streams
+ # directly, to get the error message(s)
+ stdout, stderr = p.stdout.read(), p.stderr.read()
+ p.wait()
+ if p.returncode != 0:
+ raise GraphvizError('dot exited with error:\n[stderr]\n%s\n'
+ '[stdout]\n%s' % (stderr, stdout))
+ if not path.isfile(outfn):
+ raise GraphvizError('dot did not produce an output file:\n[stderr]\n%s\n'
+ '[stdout]\n%s' % (stderr, stdout))
+ return relfn, outfn
+
+
+def render_dot_html(self, node, code, options, prefix='graphviz',
+ imgcls=None, alt=None):
+ format = self.builder.config.graphviz_output_format
+ try:
+ if format not in ('png', 'svg'):
+ raise GraphvizError("graphviz_output_format must be one of 'png', "
+ "'svg', but is %r" % format)
+ fname, outfn = render_dot(self, code, options, format, prefix)
+ except GraphvizError, exc:
+ self.builder.warn('dot code %r: ' % code + str(exc))
+ raise nodes.SkipNode
+
+ inline = node.get('inline', False)
+ if inline:
+ wrapper = 'span'
+ else:
+ wrapper = 'p'
+
+ self.body.append(self.starttag(node, wrapper, CLASS='graphviz'))
+ if fname is None:
+ self.body.append(self.encode(code))
+ else:
+ if alt is None:
+ alt = node.get('alt', self.encode(code).strip())
+ imgcss = imgcls and 'class="%s"' % imgcls or ''
+ if format == 'svg':
+ svgtag = '<img src="%s" alt="%s" %s/>\n' % (fname, alt, imgcss)
+ self.body.append(svgtag)
+ else:
+ mapfile = open(outfn + '.map', 'rb')
+ try:
+ imgmap = mapfile.readlines()
+ finally:
+ mapfile.close()
+ if len(imgmap) == 2:
+ # nothing in image map (the lines are <map> and </map>)
+ self.body.append('<img src="%s" alt="%s" %s/>\n' %
+ (fname, alt, imgcss))
+ else:
+ # has a map: get the name of the map and connect the parts
+ mapname = mapname_re.match(imgmap[0].decode('utf-8')).group(1)
+ self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' %
+ (fname, alt, mapname, imgcss))
+ self.body.extend([item.decode('utf-8') for item in imgmap])
+ if node.get('caption') and not inline:
+ self.body.append('</p>\n<p class="caption">')
+ self.body.append(self.encode(node['caption']))
+
+ self.body.append('</%s>\n' % wrapper)
+ raise nodes.SkipNode
+
+
+def html_visit_graphviz(self, node):
+ render_dot_html(self, node, node['code'], node['options'])
+
+
+def render_dot_latex(self, node, code, options, prefix='graphviz'):
+ try:
+ fname, outfn = render_dot(self, code, options, 'pdf', prefix)
+ except GraphvizError, exc:
+ self.builder.warn('dot code %r: ' % code + str(exc))
+ raise nodes.SkipNode
+
+ inline = node.get('inline', False)
+ if inline:
+ para_separator = ''
+ else:
+ para_separator = '\n'
+
+ if fname is not None:
+ caption = node.get('caption')
+ # XXX add ids from previous target node
+ if caption and not inline:
+ self.body.append('\n\\begin{figure}[h!]')
+ self.body.append('\n\\begin{center}')
+ self.body.append('\n\\caption{%s}' % self.encode(caption))
+ self.body.append('\n\\includegraphics{%s}' % fname)
+ self.body.append('\n\\end{center}')
+ self.body.append('\n\\end{figure}\n')
+ else:
+ self.body.append('%s\\includegraphics{%s}%s' %
+ (para_separator, fname, para_separator))
+ raise nodes.SkipNode
+
+
+def latex_visit_graphviz(self, node):
+ render_dot_latex(self, node, node['code'], node['options'])
+
+
+def render_dot_texinfo(self, node, code, options, prefix='graphviz'):
+ try:
+ fname, outfn = render_dot(self, code, options, 'png', prefix)
+ except GraphvizError, exc:
+ self.builder.warn('dot code %r: ' % code + str(exc))
+ raise nodes.SkipNode
+ if fname is not None:
+ self.body.append('\n\n at float\n')
+ caption = node.get('caption')
+ if caption:
+ self.body.append('@caption{%s}\n' % self.escape_arg(caption))
+ self.body.append('@image{%s,,,[graphviz],png}\n'
+ '@end float\n\n' % fname[:-4])
+ raise nodes.SkipNode
+
+def texinfo_visit_graphviz(self, node):
+ render_dot_texinfo(self, node, node['code'], node['options'])
+
+
+def text_visit_graphviz(self, node):
+ if 'alt' in node.attributes:
+ self.add_text(_('[graph: %s]') % node['alt'])
+ else:
+ self.add_text(_('[graph]'))
+ raise nodes.SkipNode
+
+
+def man_visit_graphviz(self, node):
+ if 'alt' in node.attributes:
+ self.body.append(_('[graph: %s]') % node['alt'])
+ else:
+ self.body.append(_('[graph]'))
+ raise nodes.SkipNode
+
+
+def setup(app):
+ app.add_node(graphviz,
+ html=(html_visit_graphviz, None),
+ latex=(latex_visit_graphviz, None),
+ texinfo=(texinfo_visit_graphviz, None),
+ text=(text_visit_graphviz, None),
+ man=(man_visit_graphviz, None))
+ app.add_directive('graphviz', Graphviz)
+ app.add_directive('graph', GraphvizSimple)
+ app.add_directive('digraph', GraphvizSimple)
+ app.add_config_value('graphviz_dot', 'dot', 'html')
+ app.add_config_value('graphviz_dot_args', [], 'html')
+ app.add_config_value('graphviz_output_format', 'png', 'html')
diff --git a/sphinx/ext/ifconfig.py b/sphinx/ext/ifconfig.py
new file mode 100644
index 0000000..3362e56
--- /dev/null
+++ b/sphinx/ext/ifconfig.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.ifconfig
+ ~~~~~~~~~~~~~~~~~~~
+
+ Provides the ``ifconfig`` directive that allows to write documentation
+ that is included depending on configuration variables.
+
+ Usage::
+
+ .. ifconfig:: releaselevel in ('alpha', 'beta', 'rc')
+
+ This stuff is only included in the built docs for unstable versions.
+
+ The argument for ``ifconfig`` is a plain Python expression, evaluated in the
+ namespace of the project configuration (that is, all variables from
+ ``conf.py`` are available.)
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from sphinx.util.nodes import set_source_info
+from sphinx.util.compat import Directive
+
+
+class ifconfig(nodes.Element): pass
+
+
+class IfConfig(Directive):
+
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ node = ifconfig()
+ node.document = self.state.document
+ set_source_info(self, node)
+ node['expr'] = self.arguments[0]
+ self.state.nested_parse(self.content, self.content_offset,
+ node, match_titles=1)
+ return [node]
+
+
+def process_ifconfig_nodes(app, doctree, docname):
+ ns = app.config.__dict__.copy()
+ ns['builder'] = app.builder.name
+ for node in doctree.traverse(ifconfig):
+ try:
+ res = eval(node['expr'], ns)
+ except Exception, err:
+ # handle exceptions in a clean fashion
+ from traceback import format_exception_only
+ msg = ''.join(format_exception_only(err.__class__, err))
+ newnode = doctree.reporter.error('Exception occured in '
+ 'ifconfig expression: \n%s' %
+ msg, base_node=node)
+ node.replace_self(newnode)
+ else:
+ if not res:
+ node.replace_self([])
+ else:
+ node.replace_self(node.children)
+
+
+def setup(app):
+ app.add_node(ifconfig)
+ app.add_directive('ifconfig', IfConfig)
+ app.connect('doctree-resolved', process_ifconfig_nodes)
diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py
new file mode 100644
index 0000000..5b8eab3
--- /dev/null
+++ b/sphinx/ext/inheritance_diagram.py
@@ -0,0 +1,407 @@
+# -*- coding: utf-8 -*-
+r"""
+ sphinx.ext.inheritance_diagram
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Defines a docutils directive for inserting inheritance diagrams.
+
+ Provide the directive with one or more classes or modules (separated
+ by whitespace). For modules, all of the classes in that module will
+ be used.
+
+ Example::
+
+ Given the following classes:
+
+ class A: pass
+ class B(A): pass
+ class C(A): pass
+ class D(B, C): pass
+ class E(B): pass
+
+ .. inheritance-diagram: D E
+
+ Produces a graph like the following:
+
+ A
+ / \
+ B C
+ / \ /
+ E D
+
+ The graph is inserted as a PNG+image map into HTML and a PDF in
+ LaTeX.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import sys
+import inspect
+import __builtin__ as __builtin__ # as __builtin__ is for lib2to3 compatibility
+try:
+ from hashlib import md5
+except ImportError:
+ from md5 import md5
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+
+from sphinx.ext.graphviz import render_dot_html, render_dot_latex, \
+ render_dot_texinfo
+from sphinx.pycode import ModuleAnalyzer
+from sphinx.util import force_decode
+from sphinx.util.compat import Directive
+
+
+class_sig_re = re.compile(r'''^([\w.]*\.)? # module names
+ (\w+) \s* $ # class/final module name
+ ''', re.VERBOSE)
+
+
+class InheritanceException(Exception):
+ pass
+
+
+class InheritanceGraph(object):
+ """
+ Given a list of classes, determines the set of classes that they inherit
+ from all the way to the root "object", and then is able to generate a
+ graphviz dot graph from them.
+ """
+ def __init__(self, class_names, currmodule, show_builtins=False,
+ private_bases=False, parts=0):
+ """*class_names* is a list of child classes to show bases from.
+
+ If *show_builtins* is True, then Python builtins will be shown
+ in the graph.
+ """
+ self.class_names = class_names
+ classes = self._import_classes(class_names, currmodule)
+ self.class_info = self._class_info(classes, show_builtins,
+ private_bases, parts)
+ if not self.class_info:
+ raise InheritanceException('No classes found for '
+ 'inheritance diagram')
+
+ def _import_class_or_module(self, name, currmodule):
+ """Import a class using its fully-qualified *name*."""
+ try:
+ path, base = class_sig_re.match(name).groups()
+ except (AttributeError, ValueError):
+ raise InheritanceException('Invalid class or module %r specified '
+ 'for inheritance diagram' % name)
+
+ fullname = (path or '') + base
+ path = (path and path.rstrip('.') or '')
+
+ # two possibilities: either it is a module, then import it
+ try:
+ __import__(fullname)
+ todoc = sys.modules[fullname]
+ except ImportError:
+ # else it is a class, then import the module
+ if not path:
+ if currmodule:
+ # try the current module
+ path = currmodule
+ else:
+ raise InheritanceException(
+ 'Could not import class %r specified for '
+ 'inheritance diagram' % base)
+ try:
+ __import__(path)
+ todoc = getattr(sys.modules[path], base)
+ except (ImportError, AttributeError):
+ raise InheritanceException(
+ 'Could not import class or module %r specified for '
+ 'inheritance diagram' % (path + '.' + base))
+
+ # If a class, just return it
+ if inspect.isclass(todoc):
+ return [todoc]
+ elif inspect.ismodule(todoc):
+ classes = []
+ for cls in todoc.__dict__.values():
+ if inspect.isclass(cls) and cls.__module__ == todoc.__name__:
+ classes.append(cls)
+ return classes
+ raise InheritanceException('%r specified for inheritance diagram is '
+ 'not a class or module' % name)
+
+ def _import_classes(self, class_names, currmodule):
+ """Import a list of classes."""
+ classes = []
+ for name in class_names:
+ classes.extend(self._import_class_or_module(name, currmodule))
+ return classes
+
+ def _class_info(self, classes, show_builtins, private_bases, parts):
+ """Return name and bases for all classes that are ancestors of
+ *classes*.
+
+ *parts* gives the number of dotted name parts that is removed from the
+ displayed node names.
+ """
+ all_classes = {}
+ builtins = vars(__builtin__).values()
+
+ def recurse(cls):
+ if not show_builtins and cls in builtins:
+ return
+ if not private_bases and cls.__name__.startswith('_'):
+ return
+
+ nodename = self.class_name(cls, parts)
+ fullname = self.class_name(cls, 0)
+
+ # Use first line of docstring as tooltip, if available
+ tooltip = None
+ try:
+ if cls.__doc__:
+ enc = ModuleAnalyzer.for_module(cls.__module__).encoding
+ doc = cls.__doc__.strip().split("\n")[0]
+ if not isinstance(doc, unicode):
+ doc = force_decode(doc, enc)
+ if doc:
+ tooltip = '"%s"' % doc.replace('"', '\\"')
+ except Exception: # might raise AttributeError for strange classes
+ pass
+
+ baselist = []
+ all_classes[cls] = (nodename, fullname, baselist, tooltip)
+ for base in cls.__bases__:
+ if not show_builtins and base in builtins:
+ continue
+ if not private_bases and base.__name__.startswith('_'):
+ continue
+ baselist.append(self.class_name(base, parts))
+ if base not in all_classes:
+ recurse(base)
+
+ for cls in classes:
+ recurse(cls)
+
+ return all_classes.values()
+
+ def class_name(self, cls, parts=0):
+ """Given a class object, return a fully-qualified name.
+
+ This works for things I've tested in matplotlib so far, but may not be
+ completely general.
+ """
+ module = cls.__module__
+ if module == '__builtin__':
+ fullname = cls.__name__
+ else:
+ fullname = '%s.%s' % (module, cls.__name__)
+ if parts == 0:
+ return fullname
+ name_parts = fullname.split('.')
+ return '.'.join(name_parts[-parts:])
+
+ def get_all_class_names(self):
+ """Get all of the class names involved in the graph."""
+ return [fullname for (_, fullname, _, _) in self.class_info]
+
+ # These are the default attrs for graphviz
+ default_graph_attrs = {
+ 'rankdir': 'LR',
+ 'size': '"8.0, 12.0"',
+ }
+ default_node_attrs = {
+ 'shape': 'box',
+ 'fontsize': 10,
+ 'height': 0.25,
+ 'fontname': '"Vera Sans, DejaVu Sans, Liberation Sans, '
+ 'Arial, Helvetica, sans"',
+ 'style': '"setlinewidth(0.5)"',
+ }
+ default_edge_attrs = {
+ 'arrowsize': 0.5,
+ 'style': '"setlinewidth(0.5)"',
+ }
+
+ def _format_node_attrs(self, attrs):
+ return ','.join(['%s=%s' % x for x in attrs.items()])
+
+ def _format_graph_attrs(self, attrs):
+ return ''.join(['%s=%s;\n' % x for x in attrs.items()])
+
+ def generate_dot(self, name, urls={}, env=None,
+ graph_attrs={}, node_attrs={}, edge_attrs={}):
+ """Generate a graphviz dot graph from the classes that were passed in
+ to __init__.
+
+ *name* is the name of the graph.
+
+ *urls* is a dictionary mapping class names to HTTP URLs.
+
+ *graph_attrs*, *node_attrs*, *edge_attrs* are dictionaries containing
+ key/value pairs to pass on as graphviz properties.
+ """
+ g_attrs = self.default_graph_attrs.copy()
+ n_attrs = self.default_node_attrs.copy()
+ e_attrs = self.default_edge_attrs.copy()
+ g_attrs.update(graph_attrs)
+ n_attrs.update(node_attrs)
+ e_attrs.update(edge_attrs)
+ if env:
+ g_attrs.update(env.config.inheritance_graph_attrs)
+ n_attrs.update(env.config.inheritance_node_attrs)
+ e_attrs.update(env.config.inheritance_edge_attrs)
+
+ res = []
+ res.append('digraph %s {\n' % name)
+ res.append(self._format_graph_attrs(g_attrs))
+
+ for name, fullname, bases, tooltip in sorted(self.class_info):
+ # Write the node
+ this_node_attrs = n_attrs.copy()
+ if fullname in urls:
+ this_node_attrs['URL'] = '"%s"' % urls[fullname]
+ if tooltip:
+ this_node_attrs['tooltip'] = tooltip
+ res.append(' "%s" [%s];\n' %
+ (name, self._format_node_attrs(this_node_attrs)))
+
+ # Write the edges
+ for base_name in bases:
+ res.append(' "%s" -> "%s" [%s];\n' %
+ (base_name, name,
+ self._format_node_attrs(e_attrs)))
+ res.append('}\n')
+ return ''.join(res)
+
+
+class inheritance_diagram(nodes.General, nodes.Element):
+ """
+ A docutils node to use as a placeholder for the inheritance diagram.
+ """
+ pass
+
+
+class InheritanceDiagram(Directive):
+ """
+ Run when the inheritance_diagram directive is first encountered.
+ """
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {
+ 'parts': directives.nonnegative_int,
+ 'private-bases': directives.flag,
+ }
+
+ def run(self):
+ node = inheritance_diagram()
+ node.document = self.state.document
+ env = self.state.document.settings.env
+ class_names = self.arguments[0].split()
+ class_role = env.get_domain('py').role('class')
+ # Store the original content for use as a hash
+ node['parts'] = self.options.get('parts', 0)
+ node['content'] = ', '.join(class_names)
+
+ # Create a graph starting with the list of classes
+ try:
+ graph = InheritanceGraph(
+ class_names, env.temp_data.get('py:module'),
+ parts=node['parts'],
+ private_bases='private-bases' in self.options)
+ except InheritanceException, err:
+ return [node.document.reporter.warning(err.args[0],
+ line=self.lineno)]
+
+ # Create xref nodes for each target of the graph's image map and
+ # add them to the doc tree so that Sphinx can resolve the
+ # references to real URLs later. These nodes will eventually be
+ # removed from the doctree after we're done with them.
+ for name in graph.get_all_class_names():
+ refnodes, x = class_role(
+ 'class', ':class:`%s`' % name, name, 0, self.state)
+ node.extend(refnodes)
+ # Store the graph object so we can use it to generate the
+ # dot file later
+ node['graph'] = graph
+ return [node]
+
+
+def get_graph_hash(node):
+ encoded = (node['content'] + str(node['parts'])).encode('utf-8')
+ return md5(encoded).hexdigest()[-10:]
+
+
+def html_visit_inheritance_diagram(self, node):
+ """
+ Output the graph for HTML. This will insert a PNG with clickable
+ image map.
+ """
+ graph = node['graph']
+
+ graph_hash = get_graph_hash(node)
+ name = 'inheritance%s' % graph_hash
+
+ # Create a mapping from fully-qualified class names to URLs.
+ urls = {}
+ for child in node:
+ if child.get('refuri') is not None:
+ urls[child['reftitle']] = child.get('refuri')
+ elif child.get('refid') is not None:
+ urls[child['reftitle']] = '#' + child.get('refid')
+
+ dotcode = graph.generate_dot(name, urls, env=self.builder.env)
+ render_dot_html(self, node, dotcode, [], 'inheritance', 'inheritance',
+ alt='Inheritance diagram of ' + node['content'])
+ raise nodes.SkipNode
+
+
+def latex_visit_inheritance_diagram(self, node):
+ """
+ Output the graph for LaTeX. This will insert a PDF.
+ """
+ graph = node['graph']
+
+ graph_hash = get_graph_hash(node)
+ name = 'inheritance%s' % graph_hash
+
+ dotcode = graph.generate_dot(name, env=self.builder.env,
+ graph_attrs={'size': '"6.0,6.0"'})
+ render_dot_latex(self, node, dotcode, [], 'inheritance')
+ raise nodes.SkipNode
+
+
+def texinfo_visit_inheritance_diagram(self, node):
+ """
+ Output the graph for Texinfo. This will insert a PNG.
+ """
+ graph = node['graph']
+
+ graph_hash = get_graph_hash(node)
+ name = 'inheritance%s' % graph_hash
+
+ dotcode = graph.generate_dot(name, env=self.builder.env,
+ graph_attrs={'size': '"6.0,6.0"'})
+ render_dot_texinfo(self, node, dotcode, [], 'inheritance')
+ raise nodes.SkipNode
+
+
+def skip(self, node):
+ raise nodes.SkipNode
+
+
+def setup(app):
+ app.setup_extension('sphinx.ext.graphviz')
+ app.add_node(
+ inheritance_diagram,
+ latex=(latex_visit_inheritance_diagram, None),
+ html=(html_visit_inheritance_diagram, None),
+ text=(skip, None),
+ man=(skip, None),
+ texinfo=(texinfo_visit_inheritance_diagram, None))
+ app.add_directive('inheritance-diagram', InheritanceDiagram)
+ app.add_config_value('inheritance_graph_attrs', {}, False),
+ app.add_config_value('inheritance_node_attrs', {}, False),
+ app.add_config_value('inheritance_edge_attrs', {}, False),
diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py
new file mode 100644
index 0000000..c3adf56
--- /dev/null
+++ b/sphinx/ext/intersphinx.py
@@ -0,0 +1,271 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.intersphinx
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Insert links to objects documented in remote Sphinx documentation.
+
+ This works as follows:
+
+ * Each Sphinx HTML build creates a file named "objects.inv" that contains a
+ mapping from object names to URIs relative to the HTML set's root.
+
+ * Projects using the Intersphinx extension can specify links to such mapping
+ files in the `intersphinx_mapping` config value. The mapping will then be
+ used to resolve otherwise missing references to objects into links to the
+ other documentation.
+
+ * By default, the mapping file is assumed to be at the same location as the
+ rest of the documentation; however, the location of the mapping file can
+ also be specified individually, e.g. if the docs should be buildable
+ without Internet access.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import time
+import zlib
+import codecs
+import urllib2
+import posixpath
+from os import path
+import re
+
+from docutils import nodes
+from docutils.utils import relative_path
+
+from sphinx.locale import _
+from sphinx.builders.html import INVENTORY_FILENAME
+from sphinx.util.pycompat import b
+
+
+handlers = [urllib2.ProxyHandler(), urllib2.HTTPRedirectHandler(),
+ urllib2.HTTPHandler()]
+try:
+ handlers.append(urllib2.HTTPSHandler)
+except AttributeError:
+ pass
+
+urllib2.install_opener(urllib2.build_opener(*handlers))
+
+UTF8StreamReader = codecs.lookup('utf-8')[2]
+
+
+def read_inventory_v1(f, uri, join):
+ f = UTF8StreamReader(f)
+ invdata = {}
+ line = f.next()
+ projname = line.rstrip()[11:]
+ line = f.next()
+ version = line.rstrip()[11:]
+ for line in f:
+ name, type, location = line.rstrip().split(None, 2)
+ location = join(uri, location)
+ # version 1 did not add anchors to the location
+ if type == 'mod':
+ type = 'py:module'
+ location += '#module-' + name
+ else:
+ type = 'py:' + type
+ location += '#' + name
+ invdata.setdefault(type, {})[name] = (projname, version, location, '-')
+ return invdata
+
+
+def read_inventory_v2(f, uri, join, bufsize=16*1024):
+ invdata = {}
+ line = f.readline()
+ projname = line.rstrip()[11:].decode('utf-8')
+ line = f.readline()
+ version = line.rstrip()[11:].decode('utf-8')
+ line = f.readline().decode('utf-8')
+ if 'zlib' not in line:
+ raise ValueError
+
+ def read_chunks():
+ decompressor = zlib.decompressobj()
+ for chunk in iter(lambda: f.read(bufsize), b('')):
+ yield decompressor.decompress(chunk)
+ yield decompressor.flush()
+
+ def split_lines(iter):
+ buf = b('')
+ for chunk in iter:
+ buf += chunk
+ lineend = buf.find(b('\n'))
+ while lineend != -1:
+ yield buf[:lineend].decode('utf-8')
+ buf = buf[lineend+1:]
+ lineend = buf.find(b('\n'))
+ assert not buf
+
+ for line in split_lines(read_chunks()):
+ # be careful to handle names with embedded spaces correctly
+ m = re.match(r'(?x)(.+?)\s+(\S*:\S*)\s+(\S+)\s+(\S+)\s+(.*)',
+ line.rstrip())
+ if not m:
+ continue
+ name, type, prio, location, dispname = m.groups()
+ if type == 'py:module' and type in invdata and \
+ name in invdata[type]: # due to a bug in 1.1 and below,
+ # two inventory entries are created
+ # for Python modules, and the first
+ # one is correct
+ continue
+ if location.endswith(u'$'):
+ location = location[:-1] + name
+ location = join(uri, location)
+ invdata.setdefault(type, {})[name] = (projname, version,
+ location, dispname)
+ return invdata
+
+
+def fetch_inventory(app, uri, inv):
+ """Fetch, parse and return an intersphinx inventory file."""
+ # both *uri* (base URI of the links to generate) and *inv* (actual
+ # location of the inventory file) can be local or remote URIs
+ localuri = uri.find('://') == -1
+ join = localuri and path.join or posixpath.join
+ try:
+ if inv.find('://') != -1:
+ f = urllib2.urlopen(inv)
+ else:
+ f = open(path.join(app.srcdir, inv), 'rb')
+ except Exception, err:
+ app.warn('intersphinx inventory %r not fetchable due to '
+ '%s: %s' % (inv, err.__class__, err))
+ return
+ try:
+ line = f.readline().rstrip().decode('utf-8')
+ try:
+ if line == '# Sphinx inventory version 1':
+ invdata = read_inventory_v1(f, uri, join)
+ elif line == '# Sphinx inventory version 2':
+ invdata = read_inventory_v2(f, uri, join)
+ else:
+ raise ValueError
+ f.close()
+ except ValueError:
+ f.close()
+ raise ValueError('unknown or unsupported inventory version')
+ except Exception, err:
+ app.warn('intersphinx inventory %r not readable due to '
+ '%s: %s' % (inv, err.__class__.__name__, err))
+ else:
+ return invdata
+
+
+def load_mappings(app):
+ """Load all intersphinx mappings into the environment."""
+ now = int(time.time())
+ cache_time = now - app.config.intersphinx_cache_limit * 86400
+ env = app.builder.env
+ if not hasattr(env, 'intersphinx_cache'):
+ env.intersphinx_cache = {}
+ env.intersphinx_inventory = {}
+ env.intersphinx_named_inventory = {}
+ cache = env.intersphinx_cache
+ update = False
+ for key, value in app.config.intersphinx_mapping.iteritems():
+ if isinstance(value, tuple):
+ # new format
+ name, (uri, inv) = key, value
+ if not name.isalnum():
+ app.warn('intersphinx identifier %r is not alphanumeric' % name)
+ else:
+ # old format, no name
+ name, uri, inv = None, key, value
+ # we can safely assume that the uri<->inv mapping is not changed
+ # during partial rebuilds since a changed intersphinx_mapping
+ # setting will cause a full environment reread
+ if not inv:
+ inv = posixpath.join(uri, INVENTORY_FILENAME)
+ # decide whether the inventory must be read: always read local
+ # files; remote ones only if the cache time is expired
+ if '://' not in inv or uri not in cache \
+ or cache[uri][1] < cache_time:
+ app.info('loading intersphinx inventory from %s...' % inv)
+ invdata = fetch_inventory(app, uri, inv)
+ if invdata:
+ cache[uri] = (name, now, invdata)
+ else:
+ cache.pop(uri, None)
+ update = True
+ if update:
+ env.intersphinx_inventory = {}
+ env.intersphinx_named_inventory = {}
+ # Duplicate values in different inventories will shadow each
+ # other; which one will override which can vary between builds
+ # since they are specified using an unordered dict. To make
+ # it more consistent, we sort the named inventories and then
+ # add the unnamed inventories last. This means that the
+ # unnamed inventories will shadow the named ones but the named
+ # ones can still be accessed when the name is specified.
+ cached_vals = list(cache.itervalues())
+ named_vals = sorted(v for v in cached_vals if v[0])
+ unnamed_vals = [v for v in cached_vals if not v[0]]
+ for name, _, invdata in named_vals + unnamed_vals:
+ if name:
+ env.intersphinx_named_inventory[name] = invdata
+ for type, objects in invdata.iteritems():
+ env.intersphinx_inventory.setdefault(
+ type, {}).update(objects)
+
+
+def missing_reference(app, env, node, contnode):
+ """Attempt to resolve a missing reference via intersphinx references."""
+ domain = node.get('refdomain')
+ if not domain:
+ # only objects in domains are in the inventory
+ return
+ target = node['reftarget']
+ objtypes = env.domains[domain].objtypes_for_role(node['reftype'])
+ if not objtypes:
+ return
+ objtypes = ['%s:%s' % (domain, objtype) for objtype in objtypes]
+ to_try = [(env.intersphinx_inventory, target)]
+ in_set = None
+ if ':' in target:
+ # first part may be the foreign doc set name
+ setname, newtarget = target.split(':', 1)
+ if setname in env.intersphinx_named_inventory:
+ in_set = setname
+ to_try.append((env.intersphinx_named_inventory[setname], newtarget))
+ for inventory, target in to_try:
+ for objtype in objtypes:
+ if objtype not in inventory or target not in inventory[objtype]:
+ continue
+ proj, version, uri, dispname = inventory[objtype][target]
+ if '://' not in uri and node.get('refdoc'):
+ # get correct path in case of subdirectories
+ uri = path.join(relative_path(node['refdoc'], env.srcdir), uri)
+ newnode = nodes.reference('', '', internal=False, refuri=uri,
+ reftitle=_('(in %s v%s)') % (proj, version))
+ if node.get('refexplicit'):
+ # use whatever title was given
+ newnode.append(contnode)
+ elif dispname == '-' or \
+ (domain == 'std' and node['reftype'] == 'keyword'):
+ # use whatever title was given, but strip prefix
+ title = contnode.astext()
+ if in_set and title.startswith(in_set+':'):
+ newnode.append(contnode.__class__(title[len(in_set)+1:],
+ title[len(in_set)+1:]))
+ else:
+ newnode.append(contnode)
+ else:
+ # else use the given display name (used for :ref:)
+ newnode.append(contnode.__class__(dispname, dispname))
+ return newnode
+ # at least get rid of the ':' in the target if no explicit title given
+ if in_set is not None and not node.get('refexplicit', True):
+ if len(contnode) and isinstance(contnode[0], nodes.Text):
+ contnode[0] = nodes.Text(newtarget, contnode[0].rawsource)
+
+
+def setup(app):
+ app.add_config_value('intersphinx_mapping', {}, True)
+ app.add_config_value('intersphinx_cache_limit', 5, False)
+ app.connect('missing-reference', missing_reference)
+ app.connect('builder-inited', load_mappings)
diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py
new file mode 100644
index 0000000..8907576
--- /dev/null
+++ b/sphinx/ext/jsmath.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.jsmath
+ ~~~~~~~~~~~~~~~~~
+
+ Set up everything for use of JSMath to display math in HTML
+ via JavaScript.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from sphinx.application import ExtensionError
+from sphinx.ext.mathbase import setup_math as mathbase_setup
+
+
+def html_visit_math(self, node):
+ self.body.append(self.starttag(node, 'span', '', CLASS='math'))
+ self.body.append(self.encode(node['latex']) + '</span>')
+ raise nodes.SkipNode
+
+def html_visit_displaymath(self, node):
+ if node['nowrap']:
+ self.body.append(self.starttag(node, 'div', CLASS='math'))
+ self.body.append(node['latex'])
+ self.body.append('</div>')
+ raise nodes.SkipNode
+ for i, part in enumerate(node['latex'].split('\n\n')):
+ part = self.encode(part)
+ if i == 0:
+ # necessary to e.g. set the id property correctly
+ if node['number']:
+ self.body.append('<span class="eqno">(%s)</span>' %
+ node['number'])
+ self.body.append(self.starttag(node, 'div', CLASS='math'))
+ else:
+ # but only once!
+ self.body.append('<div class="math">')
+ if '&' in part or '\\\\' in part:
+ self.body.append('\\begin{split}' + part + '\\end{split}')
+ else:
+ self.body.append(part)
+ self.body.append('</div>\n')
+ raise nodes.SkipNode
+
+def builder_inited(app):
+ if not app.config.jsmath_path:
+ raise ExtensionError('jsmath_path config value must be set for the '
+ 'jsmath extension to work')
+ app.add_javascript(app.config.jsmath_path)
+
+
+def setup(app):
+ mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
+ app.add_config_value('jsmath_path', '', False)
+ app.connect('builder-inited', builder_inited)
diff --git a/sphinx/ext/linkcode.py b/sphinx/ext/linkcode.py
new file mode 100644
index 0000000..77bd9f2
--- /dev/null
+++ b/sphinx/ext/linkcode.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.linkcode
+ ~~~~~~~~~~~~~~~~~~~
+
+ Add external links to module code in Python object descriptions.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.locale import _
+from sphinx.errors import SphinxError
+
+class LinkcodeError(SphinxError):
+ category = "linkcode error"
+
+def doctree_read(app, doctree):
+ env = app.builder.env
+
+ resolve_target = getattr(env.config, 'linkcode_resolve', None)
+ if not callable(env.config.linkcode_resolve):
+ raise LinkcodeError(
+ "Function `linkcode_resolve` is not given in conf.py")
+
+ domain_keys = dict(
+ py=['module', 'fullname'],
+ c=['names'],
+ cpp=['names'],
+ js=['object', 'fullname'],
+ )
+
+ for objnode in doctree.traverse(addnodes.desc):
+ domain = objnode.get('domain')
+ uris = set()
+ for signode in objnode:
+ if not isinstance(signode, addnodes.desc_signature):
+ continue
+
+ # Convert signode to a specified format
+ info = {}
+ for key in domain_keys.get(domain, []):
+ value = signode.get(key)
+ if not value:
+ value = ''
+ info[key] = value
+ if not info:
+ continue
+
+ # Call user code to resolve the link
+ uri = resolve_target(domain, info)
+ if not uri:
+ # no source
+ continue
+
+ if uri in uris or not uri:
+ # only one link per name, please
+ continue
+ uris.add(uri)
+
+ onlynode = addnodes.only(expr='html')
+ onlynode += nodes.reference('', '', internal=False, refuri=uri)
+ onlynode[0] += nodes.inline('', _('[source]'),
+ classes=['viewcode-link'])
+ signode += onlynode
+
+def setup(app):
+ app.connect('doctree-read', doctree_read)
+ app.add_config_value('linkcode_resolve', None, '')
diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py
new file mode 100644
index 0000000..6aaffca
--- /dev/null
+++ b/sphinx/ext/mathbase.py
@@ -0,0 +1,200 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.mathbase
+ ~~~~~~~~~~~~~~~~~~~
+
+ Set up math support in source files and LaTeX/text output.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes, utils
+from docutils.parsers.rst import directives
+
+from sphinx.util.nodes import set_source_info
+from sphinx.util.compat import Directive
+
+
+class math(nodes.Inline, nodes.TextElement):
+ pass
+
+class displaymath(nodes.Part, nodes.Element):
+ pass
+
+class eqref(nodes.Inline, nodes.TextElement):
+ pass
+
+
+def wrap_displaymath(math, label):
+ parts = math.split('\n\n')
+ ret = []
+ for i, part in enumerate(parts):
+ if not part.strip():
+ continue
+ if label is not None and i == 0:
+ ret.append('\\begin{split}%s\\end{split}' % part +
+ (label and '\\label{'+label+'}' or ''))
+ else:
+ ret.append('\\begin{split}%s\\end{split}\\notag' % part)
+ if not ret:
+ return ''
+ return '\\begin{gather}\n' + '\\\\'.join(ret) + '\n\\end{gather}'
+
+
+def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
+ latex = utils.unescape(text, restore_backslashes=True)
+ return [math(latex=latex)], []
+
+def eq_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
+ text = utils.unescape(text)
+ node = eqref('(?)', '(?)', target=text)
+ node['docname'] = inliner.document.settings.env.docname
+ return [node], []
+
+
+class MathDirective(Directive):
+
+ has_content = True
+ required_arguments = 0
+ optional_arguments = 1
+ final_argument_whitespace = True
+ option_spec = {
+ 'label': directives.unchanged,
+ 'name': directives.unchanged,
+ 'nowrap': directives.flag,
+ }
+
+ def run(self):
+ latex = '\n'.join(self.content)
+ if self.arguments and self.arguments[0]:
+ latex = self.arguments[0] + '\n\n' + latex
+ node = displaymath()
+ node['latex'] = latex
+ node['label'] = self.options.get('name', None)
+ if node['label'] is None:
+ node['label'] = self.options.get('label', None)
+ node['nowrap'] = 'nowrap' in self.options
+ node['docname'] = self.state.document.settings.env.docname
+ ret = [node]
+ set_source_info(self, node)
+ if hasattr(self, 'src'):
+ node.source = self.src
+ if node['label']:
+ tnode = nodes.target('', '', ids=['equation-' + node['label']])
+ self.state.document.note_explicit_target(tnode)
+ ret.insert(0, tnode)
+ return ret
+
+
+def latex_visit_math(self, node):
+ self.body.append('\\(' + node['latex'] + '\\)')
+ raise nodes.SkipNode
+
+def latex_visit_displaymath(self, node):
+ if node['nowrap']:
+ self.body.append(node['latex'])
+ else:
+ label = node['label'] and node['docname'] + '-' + node['label'] or None
+ self.body.append(wrap_displaymath(node['latex'], label))
+ raise nodes.SkipNode
+
+def latex_visit_eqref(self, node):
+ self.body.append('\\eqref{%s-%s}' % (node['docname'], node['target']))
+ raise nodes.SkipNode
+
+
+def text_visit_math(self, node):
+ self.add_text(node['latex'])
+ raise nodes.SkipNode
+
+def text_visit_displaymath(self, node):
+ self.new_state()
+ self.add_text(node['latex'])
+ self.end_state()
+ raise nodes.SkipNode
+
+def text_visit_eqref(self, node):
+ self.add_text(node['target'])
+ raise nodes.SkipNode
+
+
+def man_visit_math(self, node):
+ self.body.append(node['latex'])
+ raise nodes.SkipNode
+
+def man_visit_displaymath(self, node):
+ self.visit_centered(node)
+def man_depart_displaymath(self, node):
+ self.depart_centered(node)
+
+def man_visit_eqref(self, node):
+ self.body.append(node['target'])
+ raise nodes.SkipNode
+
+
+def texinfo_visit_math(self, node):
+ self.body.append('@math{' + self.escape_arg(node['latex']) + '}')
+ raise nodes.SkipNode
+
+def texinfo_visit_displaymath(self, node):
+ if node.get('label'):
+ self.add_anchor(node['label'], node)
+ self.body.append('\n\n at example\n%s\n at end example\n\n' %
+ self.escape_arg(node['latex']))
+def texinfo_depart_displaymath(self, node):
+ pass
+
+def texinfo_visit_eqref(self, node):
+ self.add_xref(node['docname'] + ':' + node['target'],
+ node['target'], node)
+ raise nodes.SkipNode
+
+
+def html_visit_eqref(self, node):
+ self.body.append('<a href="#equation-%s">' % node['target'])
+
+def html_depart_eqref(self, node):
+ self.body.append('</a>')
+
+
+def number_equations(app, doctree, docname):
+ num = 0
+ numbers = {}
+ for node in doctree.traverse(displaymath):
+ if node['label'] is not None:
+ num += 1
+ node['number'] = num
+ numbers[node['label']] = num
+ else:
+ node['number'] = None
+ for node in doctree.traverse(eqref):
+ if node['target'] not in numbers:
+ continue
+ num = '(%d)' % numbers[node['target']]
+ node[0] = nodes.Text(num, num)
+
+
+def setup_math(app, htmlinlinevisitors, htmldisplayvisitors):
+ app.add_node(math,
+ latex=(latex_visit_math, None),
+ text=(text_visit_math, None),
+ man=(man_visit_math, None),
+ texinfo=(texinfo_visit_math, None),
+ html=htmlinlinevisitors)
+ app.add_node(displaymath,
+ latex=(latex_visit_displaymath, None),
+ text=(text_visit_displaymath, None),
+ man=(man_visit_displaymath, man_depart_displaymath),
+ texinfo=(texinfo_visit_displaymath, texinfo_depart_displaymath),
+ html=htmldisplayvisitors)
+ app.add_node(eqref,
+ latex=(latex_visit_eqref, None),
+ text=(text_visit_eqref, None),
+ man=(man_visit_eqref, None),
+ texinfo=(texinfo_visit_eqref, None),
+ html=(html_visit_eqref, html_depart_eqref))
+ app.add_role('math', math_role)
+ app.add_role('eq', eq_role)
+ app.add_directive('math', MathDirective)
+ app.connect('doctree-resolved', number_equations)
diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py
new file mode 100644
index 0000000..ee27866
--- /dev/null
+++ b/sphinx/ext/mathjax.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.mathjax
+ ~~~~~~~~~~~~~~~~~~
+
+ Allow `MathJax <http://mathjax.org/>`_ to be used to display math in
+ Sphinx's HTML writer -- requires the MathJax JavaScript library on your
+ webserver/computer.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from sphinx.application import ExtensionError
+from sphinx.ext.mathbase import setup_math as mathbase_setup
+
+
+def html_visit_math(self, node):
+ self.body.append(self.starttag(node, 'span', '', CLASS='math'))
+ self.body.append(self.builder.config.mathjax_inline[0] +
+ self.encode(node['latex']) +
+ self.builder.config.mathjax_inline[1] + '</span>')
+ raise nodes.SkipNode
+
+def html_visit_displaymath(self, node):
+ self.body.append(self.starttag(node, 'div', CLASS='math'))
+ if node['nowrap']:
+ self.body.append(self.builder.config.mathjax_display[0] +
+ node['latex'] +
+ self.builder.config.mathjax_display[1])
+ self.body.append('</div>')
+ raise nodes.SkipNode
+
+ parts = [prt for prt in node['latex'].split('\n\n') if prt.strip()]
+ for i, part in enumerate(parts):
+ part = self.encode(part)
+ if i == 0:
+ # necessary to e.g. set the id property correctly
+ if node['number']:
+ self.body.append('<span class="eqno">(%s)</span>' %
+ node['number'])
+ if '&' in part or '\\\\' in part:
+ self.body.append(self.builder.config.mathjax_display[0] +
+ '\\begin{split}' + part + '\\end{split}' +
+ self.builder.config.mathjax_display[1])
+ else:
+ self.body.append(self.builder.config.mathjax_display[0] + part +
+ self.builder.config.mathjax_display[1])
+ self.body.append('</div>\n')
+ raise nodes.SkipNode
+
+def builder_inited(app):
+ if not app.config.mathjax_path:
+ raise ExtensionError('mathjax_path config value must be set for the '
+ 'mathjax extension to work')
+ app.add_javascript(app.config.mathjax_path)
+
+
+def setup(app):
+ mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
+ app.add_config_value('mathjax_path',
+ 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?'
+ 'config=TeX-AMS-MML_HTMLorMML', False)
+ app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html')
+ app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html')
+ app.connect('builder-inited', builder_inited)
diff --git a/sphinx/ext/oldcmarkup.py b/sphinx/ext/oldcmarkup.py
new file mode 100644
index 0000000..aa10246
--- /dev/null
+++ b/sphinx/ext/oldcmarkup.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.oldcmarkup
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ Extension for compatibility with old C markup (directives and roles).
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils.parsers.rst import directives
+
+from sphinx.util.compat import Directive
+
+_warned_oldcmarkup = False
+WARNING_MSG = 'using old C markup; please migrate to new-style markup ' \
+ '(e.g. c:function instead of cfunction), see ' \
+ 'http://sphinx-doc.org/domains.html'
+
+
+class OldCDirective(Directive):
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+ option_spec = {
+ 'noindex': directives.flag,
+ 'module': directives.unchanged,
+ }
+
+ def run(self):
+ env = self.state.document.settings.env
+ if not env.app._oldcmarkup_warned:
+ self.state_machine.reporter.warning(WARNING_MSG, line=self.lineno)
+ env.app._oldcmarkup_warned = True
+ newname = 'c:' + self.name[1:]
+ newdir = env.lookup_domain_element('directive', newname)[0]
+ return newdir(newname, self.arguments, self.options,
+ self.content, self.lineno, self.content_offset,
+ self.block_text, self.state, self.state_machine).run()
+
+
+def old_crole(typ, rawtext, text, lineno, inliner, options={}, content=[]):
+ env = inliner.document.settings.env
+ if not typ:
+ typ = env.config.default_role
+ if not env.app._oldcmarkup_warned:
+ inliner.reporter.warning(WARNING_MSG, line=lineno)
+ env.app._oldcmarkup_warned = True
+ newtyp = 'c:' + typ[1:]
+ newrole = env.lookup_domain_element('role', newtyp)[0]
+ return newrole(newtyp, rawtext, text, lineno, inliner, options, content)
+
+
+def setup(app):
+ app._oldcmarkup_warned = False
+ app.add_directive('cfunction', OldCDirective)
+ app.add_directive('cmember', OldCDirective)
+ app.add_directive('cmacro', OldCDirective)
+ app.add_directive('ctype', OldCDirective)
+ app.add_directive('cvar', OldCDirective)
+ app.add_role('cdata', old_crole)
+ app.add_role('cfunc', old_crole)
+ app.add_role('cmacro', old_crole)
+ app.add_role('ctype', old_crole)
+ app.add_role('cmember', old_crole)
diff --git a/sphinx/ext/pngmath.py b/sphinx/ext/pngmath.py
new file mode 100644
index 0000000..b654630
--- /dev/null
+++ b/sphinx/ext/pngmath.py
@@ -0,0 +1,249 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.pngmath
+ ~~~~~~~~~~~~~~~~~~
+
+ Render math in HTML via dvipng.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import codecs
+import shutil
+import tempfile
+import posixpath
+from os import path, getcwd, chdir
+from subprocess import Popen, PIPE
+try:
+ from hashlib import sha1 as sha
+except ImportError:
+ from sha import sha
+
+from docutils import nodes
+
+from sphinx.errors import SphinxError
+from sphinx.util.png import read_png_depth, write_png_depth
+from sphinx.util.osutil import ensuredir, ENOENT
+from sphinx.util.pycompat import b, sys_encoding
+from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
+
+class MathExtError(SphinxError):
+ category = 'Math extension error'
+
+ def __init__(self, msg, stderr=None, stdout=None):
+ if stderr:
+ msg += '\n[stderr]\n' + stderr.decode(sys_encoding, 'replace')
+ if stdout:
+ msg += '\n[stdout]\n' + stdout.decode(sys_encoding, 'replace')
+ SphinxError.__init__(self, msg)
+
+
+DOC_HEAD = r'''
+\documentclass[12pt]{article}
+\usepackage[utf8x]{inputenc}
+\usepackage{amsmath}
+\usepackage{amsthm}
+\usepackage{amssymb}
+\usepackage{amsfonts}
+\usepackage{bm}
+\pagestyle{empty}
+'''
+
+DOC_BODY = r'''
+\begin{document}
+%s
+\end{document}
+'''
+
+DOC_BODY_PREVIEW = r'''
+\usepackage[active]{preview}
+\begin{document}
+\begin{preview}
+%s
+\end{preview}
+\end{document}
+'''
+
+depth_re = re.compile(b(r'\[\d+ depth=(-?\d+)\]'))
+
+def render_math(self, math):
+ """Render the LaTeX math expression *math* using latex and dvipng.
+
+ Return the filename relative to the built document and the "depth",
+ that is, the distance of image bottom and baseline in pixels, if the
+ option to use preview_latex is switched on.
+
+ Error handling may seem strange, but follows a pattern: if LaTeX or
+ dvipng aren't available, only a warning is generated (since that enables
+ people on machines without these programs to at least build the rest
+ of the docs successfully). If the programs are there, however, they
+ may not fail since that indicates a problem in the math source.
+ """
+ use_preview = self.builder.config.pngmath_use_preview
+ latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble
+ latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math
+
+ shasum = "%s.png" % sha(latex.encode('utf-8')).hexdigest()
+ relfn = posixpath.join(self.builder.imgpath, 'math', shasum)
+ outfn = path.join(self.builder.outdir, '_images', 'math', shasum)
+ if path.isfile(outfn):
+ depth = read_png_depth(outfn)
+ return relfn, depth
+
+ # if latex or dvipng has failed once, don't bother to try again
+ if hasattr(self.builder, '_mathpng_warned_latex') or \
+ hasattr(self.builder, '_mathpng_warned_dvipng'):
+ return None, None
+
+ # use only one tempdir per build -- the use of a directory is cleaner
+ # than using temporary files, since we can clean up everything at once
+ # just removing the whole directory (see cleanup_tempdir)
+ if not hasattr(self.builder, '_mathpng_tempdir'):
+ tempdir = self.builder._mathpng_tempdir = tempfile.mkdtemp()
+ else:
+ tempdir = self.builder._mathpng_tempdir
+
+ tf = codecs.open(path.join(tempdir, 'math.tex'), 'w', 'utf-8')
+ tf.write(latex)
+ tf.close()
+
+ # build latex command; old versions of latex don't have the
+ # --output-directory option, so we have to manually chdir to the
+ # temp dir to run it.
+ ltx_args = [self.builder.config.pngmath_latex, '--interaction=nonstopmode']
+ # add custom args from the config file
+ ltx_args.extend(self.builder.config.pngmath_latex_args)
+ ltx_args.append('math.tex')
+
+ curdir = getcwd()
+ chdir(tempdir)
+
+ try:
+ try:
+ p = Popen(ltx_args, stdout=PIPE, stderr=PIPE)
+ except OSError, err:
+ if err.errno != ENOENT: # No such file or directory
+ raise
+ self.builder.warn('LaTeX command %r cannot be run (needed for math '
+ 'display), check the pngmath_latex setting' %
+ self.builder.config.pngmath_latex)
+ self.builder._mathpng_warned_latex = True
+ return None, None
+ finally:
+ chdir(curdir)
+
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ raise MathExtError('latex exited with error', stderr, stdout)
+
+ ensuredir(path.dirname(outfn))
+ # use some standard dvipng arguments
+ dvipng_args = [self.builder.config.pngmath_dvipng]
+ dvipng_args += ['-o', outfn, '-T', 'tight', '-z9']
+ # add custom ones from config value
+ dvipng_args.extend(self.builder.config.pngmath_dvipng_args)
+ if use_preview:
+ dvipng_args.append('--depth')
+ # last, the input file name
+ dvipng_args.append(path.join(tempdir, 'math.dvi'))
+ try:
+ p = Popen(dvipng_args, stdout=PIPE, stderr=PIPE)
+ except OSError, err:
+ if err.errno != ENOENT: # No such file or directory
+ raise
+ self.builder.warn('dvipng command %r cannot be run (needed for math '
+ 'display), check the pngmath_dvipng setting' %
+ self.builder.config.pngmath_dvipng)
+ self.builder._mathpng_warned_dvipng = True
+ return None, None
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ raise MathExtError('dvipng exited with error', stderr, stdout)
+ depth = None
+ if use_preview:
+ for line in stdout.splitlines():
+ m = depth_re.match(line)
+ if m:
+ depth = int(m.group(1))
+ write_png_depth(outfn, depth)
+ break
+
+ return relfn, depth
+
+def cleanup_tempdir(app, exc):
+ if exc:
+ return
+ if not hasattr(app.builder, '_mathpng_tempdir'):
+ return
+ try:
+ shutil.rmtree(app.builder._mathpng_tempdir)
+ except Exception:
+ pass
+
+def get_tooltip(self, node):
+ if self.builder.config.pngmath_add_tooltips:
+ return ' alt="%s"' % self.encode(node['latex']).strip()
+ return ''
+
+def html_visit_math(self, node):
+ try:
+ fname, depth = render_math(self, '$'+node['latex']+'$')
+ except MathExtError, exc:
+ msg = unicode(exc)
+ sm = nodes.system_message(msg, type='WARNING', level=2,
+ backrefs=[], source=node['latex'])
+ sm.walkabout(self)
+ self.builder.warn('display latex %r: ' % node['latex'] + msg)
+ raise nodes.SkipNode
+ if fname is None:
+ # something failed -- use text-only as a bad substitute
+ self.body.append('<span class="math">%s</span>' %
+ self.encode(node['latex']).strip())
+ else:
+ c = ('<img class="math" src="%s"' % fname) + get_tooltip(self, node)
+ if depth is not None:
+ c += ' style="vertical-align: %dpx"' % (-depth)
+ self.body.append(c + '/>')
+ raise nodes.SkipNode
+
+def html_visit_displaymath(self, node):
+ if node['nowrap']:
+ latex = node['latex']
+ else:
+ latex = wrap_displaymath(node['latex'], None)
+ try:
+ fname, depth = render_math(self, latex)
+ except MathExtError, exc:
+ sm = nodes.system_message(str(exc), type='WARNING', level=2,
+ backrefs=[], source=node['latex'])
+ sm.walkabout(self)
+ self.builder.warn('inline latex %r: ' % node['latex'] + str(exc))
+ raise nodes.SkipNode
+ self.body.append(self.starttag(node, 'div', CLASS='math'))
+ self.body.append('<p>')
+ if node['number']:
+ self.body.append('<span class="eqno">(%s)</span>' % node['number'])
+ if fname is None:
+ # something failed -- use text-only as a bad substitute
+ self.body.append('<span class="math">%s</span></p>\n</div>' %
+ self.encode(node['latex']).strip())
+ else:
+ self.body.append(('<img src="%s"' % fname) + get_tooltip(self, node)
+ + '/></p>\n</div>')
+ raise nodes.SkipNode
+
+
+def setup(app):
+ mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
+ app.add_config_value('pngmath_dvipng', 'dvipng', 'html')
+ app.add_config_value('pngmath_latex', 'latex', 'html')
+ app.add_config_value('pngmath_use_preview', False, 'html')
+ app.add_config_value('pngmath_dvipng_args',
+ ['-gamma', '1.5', '-D', '110', '-bg', 'Transparent'],
+ 'html')
+ app.add_config_value('pngmath_latex_args', [], 'html')
+ app.add_config_value('pngmath_latex_preamble', '', 'html')
+ app.add_config_value('pngmath_add_tooltips', True, 'html')
+ app.connect('build-finished', cleanup_tempdir)
diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py
new file mode 100644
index 0000000..9f521fb
--- /dev/null
+++ b/sphinx/ext/todo.py
@@ -0,0 +1,174 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.todo
+ ~~~~~~~~~~~~~~~
+
+ Allow todos to be inserted into your documentation. Inclusion of todos can
+ be switched of by a configuration variable. The todolist directive collects
+ all todos of your project and lists them along with a backlink to the
+ original location.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from sphinx.locale import _
+from sphinx.environment import NoUri
+from sphinx.util.nodes import set_source_info
+from sphinx.util.compat import Directive, make_admonition
+
+class todo_node(nodes.Admonition, nodes.Element): pass
+class todolist(nodes.General, nodes.Element): pass
+
+
+class Todo(Directive):
+ """
+ A todo entry, displayed (if configured) in the form of an admonition.
+ """
+
+ has_content = True
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ targetid = 'index-%s' % env.new_serialno('index')
+ targetnode = nodes.target('', '', ids=[targetid])
+
+ ad = make_admonition(todo_node, self.name, [_('Todo')], self.options,
+ self.content, self.lineno, self.content_offset,
+ self.block_text, self.state, self.state_machine)
+ set_source_info(self, ad[0])
+ return [targetnode] + ad
+
+
+def process_todos(app, doctree):
+ # collect all todos in the environment
+ # this is not done in the directive itself because it some transformations
+ # must have already been run, e.g. substitutions
+ env = app.builder.env
+ if not hasattr(env, 'todo_all_todos'):
+ env.todo_all_todos = []
+ for node in doctree.traverse(todo_node):
+ try:
+ targetnode = node.parent[node.parent.index(node) - 1]
+ if not isinstance(targetnode, nodes.target):
+ raise IndexError
+ except IndexError:
+ targetnode = None
+ newnode = node.deepcopy()
+ del newnode['ids']
+ env.todo_all_todos.append({
+ 'docname': env.docname,
+ 'source': node.source or env.doc2path(env.docname),
+ 'lineno': node.line,
+ 'todo': newnode,
+ 'target': targetnode,
+ })
+
+
+class TodoList(Directive):
+ """
+ A list of all todo entries.
+ """
+
+ has_content = False
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {}
+
+ def run(self):
+ # Simply insert an empty todolist node which will be replaced later
+ # when process_todo_nodes is called
+ return [todolist('')]
+
+
+def process_todo_nodes(app, doctree, fromdocname):
+ if not app.config['todo_include_todos']:
+ for node in doctree.traverse(todo_node):
+ node.parent.remove(node)
+
+ # Replace all todolist nodes with a list of the collected todos.
+ # Augment each todo with a backlink to the original location.
+ env = app.builder.env
+
+ if not hasattr(env, 'todo_all_todos'):
+ env.todo_all_todos = []
+
+ for node in doctree.traverse(todolist):
+ if not app.config['todo_include_todos']:
+ node.replace_self([])
+ continue
+
+ content = []
+
+ for todo_info in env.todo_all_todos:
+ para = nodes.paragraph(classes=['todo-source'])
+ description = _('(The <<original entry>> is located in '
+ ' %s, line %d.)') % \
+ (todo_info['source'], todo_info['lineno'])
+ desc1 = description[:description.find('<<')]
+ desc2 = description[description.find('>>')+2:]
+ para += nodes.Text(desc1, desc1)
+
+ # Create a reference
+ newnode = nodes.reference('', '', internal=True)
+ innernode = nodes.emphasis(_('original entry'), _('original entry'))
+ try:
+ newnode['refuri'] = app.builder.get_relative_uri(
+ fromdocname, todo_info['docname'])
+ newnode['refuri'] += '#' + todo_info['target']['refid']
+ except NoUri:
+ # ignore if no URI can be determined, e.g. for LaTeX output
+ pass
+ newnode.append(innernode)
+ para += newnode
+ para += nodes.Text(desc2, desc2)
+
+ # (Recursively) resolve references in the todo content
+ todo_entry = todo_info['todo']
+ env.resolve_references(todo_entry, todo_info['docname'],
+ app.builder)
+
+ # Insert into the todolist
+ content.append(todo_entry)
+ content.append(para)
+
+ node.replace_self(content)
+
+
+def purge_todos(app, env, docname):
+ if not hasattr(env, 'todo_all_todos'):
+ return
+ env.todo_all_todos = [todo for todo in env.todo_all_todos
+ if todo['docname'] != docname]
+
+
+def visit_todo_node(self, node):
+ self.visit_admonition(node)
+
+def depart_todo_node(self, node):
+ self.depart_admonition(node)
+
+def setup(app):
+ app.add_config_value('todo_include_todos', False, 'html')
+
+ app.add_node(todolist)
+ app.add_node(todo_node,
+ html=(visit_todo_node, depart_todo_node),
+ latex=(visit_todo_node, depart_todo_node),
+ text=(visit_todo_node, depart_todo_node),
+ man=(visit_todo_node, depart_todo_node),
+ texinfo=(visit_todo_node, depart_todo_node))
+
+ app.add_directive('todo', Todo)
+ app.add_directive('todolist', TodoList)
+ app.connect('doctree-read', process_todos)
+ app.connect('doctree-resolved', process_todo_nodes)
+ app.connect('env-purge-doc', purge_todos)
+
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
new file mode 100644
index 0000000..74a0046
--- /dev/null
+++ b/sphinx/ext/viewcode.py
@@ -0,0 +1,177 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.viewcode
+ ~~~~~~~~~~~~~~~~~~~
+
+ Add links to module code in Python object descriptions.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.locale import _
+from sphinx.pycode import ModuleAnalyzer
+from sphinx.util.nodes import make_refnode
+
+
+def doctree_read(app, doctree):
+ env = app.builder.env
+ if not hasattr(env, '_viewcode_modules'):
+ env._viewcode_modules = {}
+
+ def has_tag(modname, fullname, docname):
+ entry = env._viewcode_modules.get(modname, None)
+ try:
+ analyzer = ModuleAnalyzer.for_module(modname)
+ except Exception:
+ env._viewcode_modules[modname] = False
+ return
+ if not isinstance(analyzer.code, unicode):
+ code = analyzer.code.decode(analyzer.encoding)
+ else:
+ code = analyzer.code
+ if entry is None or entry[0] != code:
+ analyzer.find_tags()
+ entry = code, analyzer.tags, {}
+ env._viewcode_modules[modname] = entry
+ elif entry is False:
+ return
+ code, tags, used = entry
+ if fullname in tags:
+ used[fullname] = docname
+ return True
+
+ for objnode in doctree.traverse(addnodes.desc):
+ if objnode.get('domain') != 'py':
+ continue
+ names = set()
+ for signode in objnode:
+ if not isinstance(signode, addnodes.desc_signature):
+ continue
+ modname = signode.get('module')
+ if not modname:
+ continue
+ fullname = signode.get('fullname')
+ if not has_tag(modname, fullname, env.docname):
+ continue
+ if fullname in names:
+ # only one link per name, please
+ continue
+ names.add(fullname)
+ pagename = '_modules/' + modname.replace('.', '/')
+ onlynode = addnodes.only(expr='html')
+ onlynode += addnodes.pending_xref(
+ '', reftype='viewcode', refdomain='std', refexplicit=False,
+ reftarget=pagename, refid=fullname,
+ refdoc=env.docname)
+ onlynode[0] += nodes.inline('', _('[source]'),
+ classes=['viewcode-link'])
+ signode += onlynode
+
+
+def missing_reference(app, env, node, contnode):
+ # resolve our "viewcode" reference nodes -- they need special treatment
+ if node['reftype'] == 'viewcode':
+ return make_refnode(app.builder, node['refdoc'], node['reftarget'],
+ node['refid'], contnode)
+
+
+def collect_pages(app):
+ env = app.builder.env
+ if not hasattr(env, '_viewcode_modules'):
+ return
+ highlighter = app.builder.highlighter
+ urito = app.builder.get_relative_uri
+
+ modnames = set(env._viewcode_modules)
+
+ app.builder.info(' (%d module code pages)' %
+ len(env._viewcode_modules), nonl=1)
+
+ for modname, entry in env._viewcode_modules.iteritems():
+ if not entry:
+ continue
+ code, tags, used = entry
+ # construct a page name for the highlighted source
+ pagename = '_modules/' + modname.replace('.', '/')
+ # highlight the source using the builder's highlighter
+ highlighted = highlighter.highlight_block(code, 'python', linenos=False)
+ # split the code into lines
+ lines = highlighted.splitlines()
+ # split off wrap markup from the first line of the actual code
+ before, after = lines[0].split('<pre>')
+ lines[0:1] = [before + '<pre>', after]
+ # nothing to do for the last line; it always starts with </pre> anyway
+ # now that we have code lines (starting at index 1), insert anchors for
+ # the collected tags (HACK: this only works if the tag boundaries are
+ # properly nested!)
+ maxindex = len(lines) - 1
+ for name, docname in used.iteritems():
+ type, start, end = tags[name]
+ backlink = urito(pagename, docname) + '#' + modname + '.' + name
+ lines[start] = (
+ '<div class="viewcode-block" id="%s"><a class="viewcode-back" '
+ 'href="%s">%s</a>' % (name, backlink, _('[docs]'))
+ + lines[start])
+ lines[min(end - 1, maxindex)] += '</div>'
+ # try to find parents (for submodules)
+ parents = []
+ parent = modname
+ while '.' in parent:
+ parent = parent.rsplit('.', 1)[0]
+ if parent in modnames:
+ parents.append({
+ 'link': urito(pagename, '_modules/' +
+ parent.replace('.', '/')),
+ 'title': parent})
+ parents.append({'link': urito(pagename, '_modules/index'),
+ 'title': _('Module code')})
+ parents.reverse()
+ # putting it all together
+ context = {
+ 'parents': parents,
+ 'title': modname,
+ 'body': _('<h1>Source code for %s</h1>') % modname + \
+ '\n'.join(lines)
+ }
+ yield (pagename, context, 'page.html')
+
+ if not modnames:
+ return
+
+ app.builder.info(' _modules/index', nonl=True)
+ html = ['\n']
+ # the stack logic is needed for using nested lists for submodules
+ stack = ['']
+ for modname in sorted(modnames):
+ if modname.startswith(stack[-1]):
+ stack.append(modname + '.')
+ html.append('<ul>')
+ else:
+ stack.pop()
+ while not modname.startswith(stack[-1]):
+ stack.pop()
+ html.append('</ul>')
+ stack.append(modname + '.')
+ html.append('<li><a href="%s">%s</a></li>\n' % (
+ urito('_modules/index', '_modules/' + modname.replace('.', '/')),
+ modname))
+ html.append('</ul>' * (len(stack) - 1))
+ context = {
+ 'title': _('Overview: module code'),
+ 'body': _('<h1>All modules for which code is available</h1>') + \
+ ''.join(html),
+ }
+
+ yield ('_modules/index', context, 'page.html')
+
+
+def setup(app):
+ app.connect('doctree-read', doctree_read)
+ app.connect('html-collect-pages', collect_pages)
+ app.connect('missing-reference', missing_reference)
+ #app.add_config_value('viewcode_include_modules', [], 'env')
+ #app.add_config_value('viewcode_exclude_modules', [], 'env')
diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py
new file mode 100644
index 0000000..600a7cf
--- /dev/null
+++ b/sphinx/highlighting.py
@@ -0,0 +1,240 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.highlighting
+ ~~~~~~~~~~~~~~~~~~~
+
+ Highlight code blocks using Pygments.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import re
+import textwrap
+
+try:
+ import parser
+except ImportError:
+ # parser is not available on Jython
+ parser = None
+
+from sphinx.util.pycompat import htmlescape
+from sphinx.util.texescape import tex_hl_escape_map_new
+from sphinx.ext import doctest
+
+try:
+ import pygments
+ from pygments import highlight
+ from pygments.lexers import PythonLexer, PythonConsoleLexer, CLexer, \
+ TextLexer, RstLexer
+ from pygments.lexers import get_lexer_by_name, guess_lexer
+ from pygments.formatters import HtmlFormatter, LatexFormatter
+ from pygments.filters import ErrorToken
+ from pygments.styles import get_style_by_name
+ from pygments.util import ClassNotFound
+ from sphinx.pygments_styles import SphinxStyle, NoneStyle
+except ImportError:
+ pygments = None
+ lexers = None
+ HtmlFormatter = LatexFormatter = None
+else:
+
+ lexers = dict(
+ none = TextLexer(),
+ python = PythonLexer(),
+ pycon = PythonConsoleLexer(),
+ pycon3 = PythonConsoleLexer(python3=True),
+ rest = RstLexer(),
+ c = CLexer(),
+ )
+ for _lexer in lexers.values():
+ _lexer.add_filter('raiseonerror')
+
+
+escape_hl_chars = {ord(u'\\'): u'\\PYGZbs{}',
+ ord(u'{'): u'\\PYGZob{}',
+ ord(u'}'): u'\\PYGZcb{}'}
+
+# used if Pygments is not available
+_LATEX_STYLES = r'''
+\newcommand\PYGZbs{\char`\\}
+\newcommand\PYGZob{\char`\{}
+\newcommand\PYGZcb{\char`\}}
+'''
+
+# used if Pygments is available
+# use textcomp quote to get a true single quote
+_LATEX_ADD_STYLES = r'''
+\renewcommand\PYGZsq{\textquotesingle}
+'''
+
+parsing_exceptions = (SyntaxError, UnicodeEncodeError)
+if sys.version_info < (2, 5):
+ # Python <= 2.4 raises MemoryError when parsing an
+ # invalid encoding cookie
+ parsing_exceptions += MemoryError,
+
+
+class PygmentsBridge(object):
+ # Set these attributes if you want to have different Pygments formatters
+ # than the default ones.
+ html_formatter = HtmlFormatter
+ latex_formatter = LatexFormatter
+
+ def __init__(self, dest='html', stylename='sphinx',
+ trim_doctest_flags=False):
+ self.dest = dest
+ if not pygments:
+ return
+ if stylename is None or stylename == 'sphinx':
+ style = SphinxStyle
+ elif stylename == 'none':
+ style = NoneStyle
+ elif '.' in stylename:
+ module, stylename = stylename.rsplit('.', 1)
+ style = getattr(__import__(module, None, None, ['__name__']),
+ stylename)
+ else:
+ style = get_style_by_name(stylename)
+ self.trim_doctest_flags = trim_doctest_flags
+ self.formatter_args = {'style' : style}
+ if dest == 'html':
+ self.formatter = self.html_formatter
+ else:
+ self.formatter = self.latex_formatter
+ self.formatter_args['commandprefix'] = 'PYG'
+
+ def get_formatter(self, **kwargs):
+ kwargs.update(self.formatter_args)
+ return self.formatter(**kwargs)
+
+ def unhighlighted(self, source):
+ if self.dest == 'html':
+ return '<pre>' + htmlescape(source) + '</pre>\n'
+ else:
+ # first, escape highlighting characters like Pygments does
+ source = source.translate(escape_hl_chars)
+ # then, escape all characters nonrepresentable in LaTeX
+ source = source.translate(tex_hl_escape_map_new)
+ return '\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n' + \
+ source + '\\end{Verbatim}\n'
+
+ def try_parse(self, src):
+ # Make sure it ends in a newline
+ src += '\n'
+
+ # Ignore consistent indentation.
+ if src.lstrip('\n').startswith(' '):
+ src = textwrap.dedent(src)
+
+ # Replace "..." by a mark which is also a valid python expression
+ # (Note, the highlighter gets the original source, this is only done
+ # to allow "..." in code and still highlight it as Python code.)
+ mark = "__highlighting__ellipsis__"
+ src = src.replace("...", mark)
+
+ # lines beginning with "..." are probably placeholders for suite
+ src = re.sub(r"(?m)^(\s*)" + mark + "(.)", r"\1"+ mark + r"# \2", src)
+
+ # if we're using 2.5, use the with statement
+ if sys.version_info >= (2, 5):
+ src = 'from __future__ import with_statement\n' + src
+
+ if sys.version_info < (3, 0) and isinstance(src, unicode):
+ # Non-ASCII chars will only occur in string literals
+ # and comments. If we wanted to give them to the parser
+ # correctly, we'd have to find out the correct source
+ # encoding. Since it may not even be given in a snippet,
+ # just replace all non-ASCII characters.
+ src = src.encode('ascii', 'replace')
+
+ if (3, 0) <= sys.version_info < (3, 2):
+ # Python 3.1 can't process '\r' as linesep.
+ # `parser.suite("print('hello')\r\n")` cause error.
+ if '\r\n' in src:
+ src = src.replace('\r\n', '\n')
+
+ if parser is None:
+ return True
+
+ try:
+ parser.suite(src)
+ except parsing_exceptions:
+ return False
+ else:
+ return True
+
+ def highlight_block(self, source, lang, warn=None, force=False, **kwargs):
+ if not isinstance(source, unicode):
+ source = source.decode()
+ if not pygments:
+ return self.unhighlighted(source)
+
+ # find out which lexer to use
+ if lang in ('py', 'python'):
+ if source.startswith('>>>'):
+ # interactive session
+ lexer = lexers['pycon']
+ elif not force:
+ # maybe Python -- try parsing it
+ if self.try_parse(source):
+ lexer = lexers['python']
+ else:
+ lexer = lexers['none']
+ else:
+ lexer = lexers['python']
+ elif lang in ('python3', 'py3') and source.startswith('>>>'):
+ # for py3, recognize interactive sessions, but do not try parsing...
+ lexer = lexers['pycon3']
+ elif lang == 'guess':
+ try:
+ lexer = guess_lexer(source)
+ except Exception:
+ lexer = lexers['none']
+ else:
+ if lang in lexers:
+ lexer = lexers[lang]
+ else:
+ try:
+ lexer = lexers[lang] = get_lexer_by_name(lang)
+ except ClassNotFound:
+ if warn:
+ warn('Pygments lexer name %r is not known' % lang)
+ lexer = lexers['none']
+ else:
+ raise
+ else:
+ lexer.add_filter('raiseonerror')
+
+ # trim doctest options if wanted
+ if isinstance(lexer, PythonConsoleLexer) and self.trim_doctest_flags:
+ source = doctest.blankline_re.sub('', source)
+ source = doctest.doctestopt_re.sub('', source)
+
+ # highlight via Pygments
+ formatter = self.get_formatter(**kwargs)
+ try:
+ hlsource = highlight(source, lexer, formatter)
+ except ErrorToken:
+ # this is most probably not the selected language,
+ # so let it pass unhighlighted
+ hlsource = highlight(source, lexers['none'], formatter)
+ if self.dest == 'html':
+ return hlsource
+ else:
+ if not isinstance(hlsource, unicode): # Py2 / Pygments < 1.6
+ hlsource = hlsource.decode()
+ return hlsource.translate(tex_hl_escape_map_new)
+
+ def get_stylesheet(self):
+ if not pygments:
+ if self.dest == 'latex':
+ return _LATEX_STYLES
+ # no HTML styles needed
+ return ''
+ formatter = self.get_formatter()
+ if self.dest == 'html':
+ return formatter.get_style_defs('.highlight')
+ else:
+ return formatter.get_style_defs() + _LATEX_ADD_STYLES
diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py
new file mode 100644
index 0000000..f4a5a81
--- /dev/null
+++ b/sphinx/jinja2glue.py
@@ -0,0 +1,153 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.jinja2glue
+ ~~~~~~~~~~~~~~~~~
+
+ Glue code for the jinja2 templating engine.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from os import path
+from pprint import pformat
+
+from jinja2 import FileSystemLoader, BaseLoader, TemplateNotFound, \
+ contextfunction
+from jinja2.utils import open_if_exists
+from jinja2.sandbox import SandboxedEnvironment
+
+from sphinx.application import TemplateBridge
+from sphinx.util.osutil import mtimes_of_files
+
+
+def _tobool(val):
+ if isinstance(val, basestring):
+ return val.lower() in ('true', '1', 'yes', 'on')
+ return bool(val)
+
+def _toint(val):
+ try:
+ return int(val)
+ except ValueError:
+ return 0
+
+def accesskey(context, key):
+ """Helper to output each access key only once."""
+ if '_accesskeys' not in context:
+ context.vars['_accesskeys'] = {}
+ if key and key not in context.vars['_accesskeys']:
+ context.vars['_accesskeys'][key] = 1
+ return 'accesskey="%s"' % key
+ return ''
+
+class idgen(object):
+ def __init__(self):
+ self.id = 0
+ def current(self):
+ return self.id
+ def __next__(self):
+ self.id += 1
+ return self.id
+ next = __next__ # Python 2/Jinja compatibility
+
+
+class SphinxFileSystemLoader(FileSystemLoader):
+ """
+ FileSystemLoader subclass that is not so strict about '..' entries in
+ template names.
+ """
+
+ def get_source(self, environment, template):
+ for searchpath in self.searchpath:
+ filename = path.join(searchpath, template)
+ f = open_if_exists(filename)
+ if f is None:
+ continue
+ try:
+ contents = f.read().decode(self.encoding)
+ finally:
+ f.close()
+
+ mtime = path.getmtime(filename)
+ def uptodate():
+ try:
+ return path.getmtime(filename) == mtime
+ except OSError:
+ return False
+ return contents, filename, uptodate
+ raise TemplateNotFound(template)
+
+
+
+class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
+ """
+ Interfaces the rendering environment of jinja2 for use in Sphinx.
+ """
+
+ # TemplateBridge interface
+
+ def init(self, builder, theme=None, dirs=None):
+ # create a chain of paths to search
+ if theme:
+ # the theme's own dir and its bases' dirs
+ pathchain = theme.get_dirchain()
+ # then the theme parent paths
+ loaderchain = pathchain + theme.themepath
+ elif dirs:
+ pathchain = list(dirs)
+ loaderchain = list(dirs)
+ else:
+ pathchain = []
+ loaderchain = []
+
+ # prepend explicit template paths
+ self.templatepathlen = len(builder.config.templates_path)
+ if builder.config.templates_path:
+ cfg_templates_path = [path.join(builder.confdir, tp)
+ for tp in builder.config.templates_path]
+ pathchain[0:0] = cfg_templates_path
+ loaderchain[0:0] = cfg_templates_path
+
+ # store it for use in newest_template_mtime
+ self.pathchain = pathchain
+
+ # make the paths into loaders
+ self.loaders = map(SphinxFileSystemLoader, loaderchain)
+
+ use_i18n = builder.app.translator is not None
+ extensions = use_i18n and ['jinja2.ext.i18n'] or []
+ self.environment = SandboxedEnvironment(loader=self,
+ extensions=extensions)
+ self.environment.filters['tobool'] = _tobool
+ self.environment.filters['toint'] = _toint
+ self.environment.globals['debug'] = contextfunction(pformat)
+ self.environment.globals['accesskey'] = contextfunction(accesskey)
+ self.environment.globals['idgen'] = idgen
+ if use_i18n:
+ self.environment.install_gettext_translations(
+ builder.app.translator)
+
+ def render(self, template, context):
+ return self.environment.get_template(template).render(context)
+
+ def render_string(self, source, context):
+ return self.environment.from_string(source).render(context)
+
+ def newest_template_mtime(self):
+ return max(mtimes_of_files(self.pathchain, '.html'))
+
+ # Loader interface
+
+ def get_source(self, environment, template):
+ loaders = self.loaders
+ # exclamation mark starts search from theme
+ if template.startswith('!'):
+ loaders = loaders[self.templatepathlen:]
+ template = template[1:]
+ for loader in loaders:
+ try:
+ return loader.get_source(environment, template)
+ except TemplateNotFound:
+ pass
+ raise TemplateNotFound(template)
diff --git a/sphinx/locale/.tx/config b/sphinx/locale/.tx/config
new file mode 100644
index 0000000..06c5142
--- /dev/null
+++ b/sphinx/locale/.tx/config
@@ -0,0 +1,8 @@
+[main]
+host = https://www.transifex.com
+
+[sphinx-1.sphinx-pot]
+file_filter = <lang>/LC_MESSAGES/sphinx.po
+source_file = sphinx.pot
+source_lang = en
+
diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py
new file mode 100644
index 0000000..b76aab1
--- /dev/null
+++ b/sphinx/locale/__init__.py
@@ -0,0 +1,225 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.locale
+ ~~~~~~~~~~~~~
+
+ Locale utilities.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import gettext
+import UserString
+
+
+class _TranslationProxy(UserString.UserString, object):
+ """
+ Class for proxy strings from gettext translations. This is a helper for the
+ lazy_* functions from this module.
+
+ The proxy implementation attempts to be as complete as possible, so that
+ the lazy objects should mostly work as expected, for example for sorting.
+
+ This inherits from UserString because some docutils versions use UserString
+ for their Text nodes, which then checks its argument for being either a
+ basestring or UserString, otherwise calls str() -- not unicode() -- on it.
+ This also inherits from object to make the __new__ method work.
+ """
+ __slots__ = ('_func', '_args')
+
+ def __new__(cls, func, *args):
+ if not args:
+ # not called with "function" and "arguments", but a plain string
+ return unicode(func)
+ return object.__new__(cls)
+
+ def __getnewargs__(self):
+ return (self._func,) + self._args
+
+ def __init__(self, func, *args):
+ self._func = func
+ self._args = args
+
+ data = property(lambda x: x._func(*x._args))
+
+ # replace function from UserString; it instantiates a self.__class__
+ # for the encoding result
+
+ def encode(self, encoding=None, errors=None):
+ if encoding:
+ if errors:
+ return self.data.encode(encoding, errors)
+ else:
+ return self.data.encode(encoding)
+ else:
+ return self.data.encode()
+
+ def __contains__(self, key):
+ return key in self.data
+
+ def __nonzero__(self):
+ return bool(self.data)
+
+ def __dir__(self):
+ return dir(unicode)
+
+ def __iter__(self):
+ return iter(self.data)
+
+ def __len__(self):
+ return len(self.data)
+
+ def __str__(self):
+ return str(self.data)
+
+ def __unicode__(self):
+ return unicode(self.data)
+
+ def __add__(self, other):
+ return self.data + other
+
+ def __radd__(self, other):
+ return other + self.data
+
+ def __mod__(self, other):
+ return self.data % other
+
+ def __rmod__(self, other):
+ return other % self.data
+
+ def __mul__(self, other):
+ return self.data * other
+
+ def __rmul__(self, other):
+ return other * self.data
+
+ def __lt__(self, other):
+ return self.data < other
+
+ def __le__(self, other):
+ return self.data <= other
+
+ def __eq__(self, other):
+ return self.data == other
+
+ def __ne__(self, other):
+ return self.data != other
+
+ def __gt__(self, other):
+ return self.data > other
+
+ def __ge__(self, other):
+ return self.data >= other
+
+ def __getattr__(self, name):
+ if name == '__members__':
+ return self.__dir__()
+ return getattr(self.data, name)
+
+ def __getstate__(self):
+ return self._func, self._args
+
+ def __setstate__(self, tup):
+ self._func, self._args = tup
+
+ def __getitem__(self, key):
+ return self.data[key]
+
+ def __copy__(self):
+ return self
+
+ def __repr__(self):
+ try:
+ return 'i' + repr(unicode(self.data))
+ except:
+ return '<%s broken>' % self.__class__.__name__
+
+def mygettext(string):
+ """Used instead of _ when creating TranslationProxies, because _ is
+ not bound yet at that time.
+ """
+ return _(string)
+
+def lazy_gettext(string):
+ """A lazy version of `gettext`."""
+ #if isinstance(string, _TranslationProxy):
+ # return string
+ return _TranslationProxy(mygettext, string)
+
+l_ = lazy_gettext
+
+
+admonitionlabels = {
+ 'attention': l_('Attention'),
+ 'caution': l_('Caution'),
+ 'danger': l_('Danger'),
+ 'error': l_('Error'),
+ 'hint': l_('Hint'),
+ 'important': l_('Important'),
+ 'note': l_('Note'),
+ 'seealso': l_('See also'),
+ 'tip': l_('Tip'),
+ 'warning': l_('Warning'),
+}
+
+versionlabels = {
+ 'versionadded': l_('New in version %s'),
+ 'versionchanged': l_('Changed in version %s'),
+ 'deprecated': l_('Deprecated since version %s'),
+}
+
+# XXX Python specific
+pairindextypes = {
+ 'module': l_('module'),
+ 'keyword': l_('keyword'),
+ 'operator': l_('operator'),
+ 'object': l_('object'),
+ 'exception': l_('exception'),
+ 'statement': l_('statement'),
+ 'builtin': l_('built-in function'),
+}
+
+translators = {}
+
+if sys.version_info >= (3, 0):
+ def _(message):
+ return translators['sphinx'].gettext(message)
+else:
+ def _(message):
+ return translators['sphinx'].ugettext(message)
+
+
+def init(locale_dirs, language, catalog='sphinx'):
+ """Look for message catalogs in `locale_dirs` and *ensure* that there is at
+ least a NullTranslations catalog set in `translators`. If called multiple
+ times or if several ``.mo`` files are found, their contents are merged
+ together (thus making ``init`` reentrable).
+ """
+ global translators
+ translator = translators.get(catalog)
+ # ignore previously failed attempts to find message catalogs
+ if isinstance(translator, gettext.NullTranslations):
+ translator = None
+ # the None entry is the system's default locale path
+ has_translation = True
+ for dir_ in locale_dirs:
+ try:
+ trans = gettext.translation(catalog, localedir=dir_,
+ languages=[language])
+ if translator is None:
+ translator = trans
+ else:
+ translator._catalog.update(trans._catalog)
+ except Exception:
+ # Language couldn't be found in the specified path
+ pass
+ # guarantee translators[catalog] exists
+ if translator is None:
+ translator = gettext.NullTranslations()
+ has_translation = False
+ translators[catalog] = translator
+ if hasattr(translator, 'ugettext'):
+ translator.gettext = translator.ugettext
+ return translator, has_translation
diff --git a/sphinx/locale/bn/LC_MESSAGES/sphinx.js b/sphinx/locale/bn/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..e0f7654
--- /dev/null
+++ b/sphinx/locale/bn/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "bn", "plural_expr": "(n != 1)", "messages": {"Next topic": "\u09aa\u09b0\u09ac\u09b0\u09cd\u09a4\u09c0 \u099f\u09aa\u09bf\u0995", "Index": "\u0987\u09a8\u09a1\u09c7\u0995\u09cd\u09b8", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "\u0995\u09aa\u09bf\u09b0\u09be\u0987\u099f", "C API changes": "C API \u09aa\u09b0\u09bf\u09ac\u09b0\u09cd\u09a4\u09a8", "quick access to all modules": [...]
\ No newline at end of file
diff --git a/sphinx/locale/bn/LC_MESSAGES/sphinx.mo b/sphinx/locale/bn/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..e68cbb7
Binary files /dev/null and b/sphinx/locale/bn/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/bn/LC_MESSAGES/sphinx.po b/sphinx/locale/bn/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..5192caf
--- /dev/null
+++ b/sphinx/locale/bn/LC_MESSAGES/sphinx.po
@@ -0,0 +1,840 @@
+# Bengali translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2009
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Bengali "
+"(http://www.transifex.com/projects/p/sphinx-1/language/bn/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "পাইথন উন্নয়ন পরামর্শ; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%B %d, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "বিল্টইন সমূহ"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "মডিউল লেভেল"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%b %d, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "সাধারণ ইনডেক্স"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "ইনডেক্স"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "পরবর্তী"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "পূর্ববর্তী"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr "(-"
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "অনুচ্ছেদ লেখক:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "মডিউল লেখক:"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "লেখক:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "প্যারামিটার"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "রিটার্নস"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "রিটার্ন টাইপ"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C ফাংশন)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C মেম্বার)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C ম্যাক্রো)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C টাইপ)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C ভ্যারিয়েবল)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "ফাংশন"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr ""
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr ""
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr ""
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr ""
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ ক্লাসে)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ টাইপ)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ মেম্বার)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ ফাংশন)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "ক্লাস"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (বিল্ট-ইন ফাংশন)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s মেথড)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (ক্লাসে)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s এ্যট্রিবিউট)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "ডাটা"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "এ্যট্রিবিউট"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "রেইজেস"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (%s মডিউলে)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (বিল্ট-ইন ভ্যারিয়েবল)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (%s মডিউলে)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (বিল্ট-ইন ক্লাস)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (%s ক্লাসে)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s (%s.%s মেথড)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s (%s.%s স্ট্যাটিক মেথড)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s স্ট্যাটিক মেথড)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s ক্লাস মেথড)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s ক্লাস মেথড)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s এ্যট্রিবিউট)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (মডিউল)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "মডিউল সমূহ"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "ডেপ্রিকেটেড"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "এক্সেপশন"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "মেথড"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "ক্লাস মেথড"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "স্ট্যাটিক মেথড"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "মডিউল"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "এনভায়রনমেন্ট ভ্যারিয়েবল; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sকমান্ড লাইন অপশন; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "শব্দকোষ"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "ব্যকরণ টোকেন"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "এনভায়রনমেন্ট ভ্যারিয়েবল"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "প্রোগ্রাম অপশন"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "ইনডেক্স"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "মডিউল ইনডেক্স"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "অনুসন্ধান পাতা"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr "বেস: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ":class:`%s` এর উপনাম"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "অসমাপ্ত কাজ"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "দৃষ্টি আকর্ষণ"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "সতর্কীকরণ"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "বিপজ্জনক"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "ভুল (এরর)"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "আভাস"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "গুরুত্বপূর্ণ"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "নোট"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "আরও দেখুন"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "পরামর্শ"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "সতর্কতা"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "%s ভার্সনে নতুন"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "%s ভার্সনে পরিবর্তিত"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "%s ভার্সন থেকে ডেপ্রিকেটেড"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "কিওয়ার্ড"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "অপারেটর"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "অবজেক্ট"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "স্ট্যাটমেন্ট"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "বিল্ট-ইন ফাংশন"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "সূচীপত্র"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "অনুসন্ধান"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "যান"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "অনুসন্ধানের জন্য টার্ম, মডিউল, ক্লাস অথবা ফাংশনের নাম দিন।"
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "সোর্স দেখুন"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "ভুমিকা"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "ইনডেক্স ও টেবিল সমূহ:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "পূর্ণাঙ্গ সূচীপত্র"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "সকল অনুচ্ছেদ সমূহের তালিকা"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "এই সহায়িকাতে অনুসন্ধা করুন"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "গ্লোবাল মডিউল ইনডেক্স"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "সকল মডিউলে দ্রুত প্রবেশ"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "সকল ফাংশন, ক্লাস, টার্ম"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "ইনডেক্স – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "এক পাতায় সম্পূর্ণ ইনডেক্স"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "বর্ণানুসারে ইনডেক্স পাতা"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "খুব বড় হতে পারে"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "নেভিগেশন"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "%(docstitle)s এর মধ্যে খুঁজুন"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "এই ডকুমেন্ট সম্পর্কে"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "কপিরাইট"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">কপিরাইট</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© কপিরাইট %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "%(last_updated)s সর্বশেষ পরিবর্তন করা হয়েছে।"
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"<a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s দিয়ে "
+"তৈরী।"
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "%(docstitle)s-এ খুঁজুন"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "পূর্ববর্তী টপিক"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "পূর্ববর্তী অধ্যায়"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "পরবর্তী টপিক"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "পরবর্তী অধ্যায়"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"অনুসন্ধান করার জন্য অনুগ্রহপূর্বক জাভাস্ক্রিপ্ট \n"
+" সক্রিয় করুন।"
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"এখান থেকে এই নথিগুলোতে আপনি অনুসন্ধান করতে পারবেন। \n"
+" আপনার কাঙ্ক্ষিত শব্দসমূহ নিচের বাক্সে লিখুন এবং \"অনুসন্ধান\" বাটনে "
+"ক্লিক করুন।\n"
+" উল্লেখ্য, সকল শব্দসমূহের উপস্থিতি নিয়ে অনুসন্ধান করা হবে। যেসব পাতায় "
+"সকল\n"
+" শব্দ নেই সেগুলো বাদ দেয়া হবে।"
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "খুঁজুন"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "অনুসন্ধানের ফলাফল"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "দ্রুত অনুসন্ধান"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "এই পাতা"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "%(version)s — %(docstitle)s-এ পরিবর্তন সমূহ"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "স্বয়ংক্রিয়ভাবে তৈরী %(version)s-এ পরিবর্তন সমূহের তালিকা।"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "লাইব্রেরির পরিবর্তন"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API পরিবর্তন"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "অন্যান্য পরিবর্তন"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "এই শিরোনামের পার্মালিঙ্ক"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "এই সংজ্ঞার পার্মালিঙ্ক"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "অনুসন্ধানের ম্যাচগুলো লুকান"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "রিলিজ"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "পাদটীকা"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "পূর্ববর্তী পাতা হতে চলমান"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "পরবর্তী পাতাতে চলমান"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[ছবি]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/ca/LC_MESSAGES/sphinx.js b/sphinx/locale/ca/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..8a204db
--- /dev/null
+++ b/sphinx/locale/ca/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "ca", "plural_expr": "(n != 1)", "messages": {"Next topic": "Tema seg\u00fcent", "Index": "\u00cdndex", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Copyright", "C API changes": "Canvis a la API de C", "quick access to all modules": "acc\u00e9s r\u00e0pid a tots els m\u00f2duls", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global Module Index": "\u00cdn [...]
\ No newline at end of file
diff --git a/sphinx/locale/ca/LC_MESSAGES/sphinx.mo b/sphinx/locale/ca/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..8db40c6
Binary files /dev/null and b/sphinx/locale/ca/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/ca/LC_MESSAGES/sphinx.po b/sphinx/locale/ca/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..9e0bab7
--- /dev/null
+++ b/sphinx/locale/ca/LC_MESSAGES/sphinx.po
@@ -0,0 +1,838 @@
+# Catalan translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2009
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Catalan "
+"(http://www.transifex.com/projects/p/sphinx-1/language/ca/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s documentació"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "vegeu %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "vegeu també %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d de %B de %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Mòduls Interns"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Nivell de mòdul"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Índex General"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "índex"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "següent"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "anterior"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (a "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autor de la secció:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autor del mòdul: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Paràmetres"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Retorna"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Tipus de retorn"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (funció de C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (membre de C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro de C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (tipus de C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (variable de C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funció"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "membre"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "macro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tipus"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variable"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (class de C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (tipus de C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (membre de C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (funció de C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "class"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (funció interna)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (mètode %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (class)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (atribut %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atribut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Llença"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (al mòdul %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (variable interna)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (al mòdul %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (classe interna)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (class a %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (mètode %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (mètode estàtic %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (mètode estàtic %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (atribut %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (mòdul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "mòduls"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Obsolet"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "excepció"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "mètode estàtic"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "mòdul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (obsolet)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "variable d'entorn; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "opció de línia de comandes %s; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "variable d'entorn"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Índex"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Índex de Mòduls"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Pàgina de Cerca"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Bases: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "àlies de :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Pendent"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(La <<entrada original>> està a %s, línia %d i.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Atenció"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Compte"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Perill"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Error"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Suggerència"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Important"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Nota"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Vegeu també"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Truc"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Avís"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Novetat de la versió %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Canviat a la versió %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Obsolet desde la versió %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "paraula clau"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operador"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objecte"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "sentència"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "funció interna"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Taula de Contingut"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Cerca"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Ves a"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Entra paraules de cerca o el nom d'un mòdul, classe o funció."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Mostra Codi Font"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Resum"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Índexs i taules:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Taula de Contingut Completa"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "llista totes les seccions i subseccions"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "cerca aquesta documentació"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Índex Global de Mòduls"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "accés ràpid a tots els mòduls"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "totes les funcions, classes, termes"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Índes – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Índex complet en una pàgina"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Pàgines d'índex per lletra"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "pot ser gegant"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navegació"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Cerca dins de %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Quant a aquests documents"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\\\"%(path)s\\\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Última actualització el %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Creat amb <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Cercar a %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Tema anterior"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "capítol anterior"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Tema següent"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "capítol següent"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Activa JavaScript per utilitzar la funcionalitat\n"
+"de cerca."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Des d'aquí pots fer cerques en aquests documents. Entra les \n"
+"paraules de la teva cerca i clica el botó \"cerca\". Tingues en compte\n"
+"que la cerca inclourà totes les paraules que posis. Les pàgines que no\n"
+"tenen totes les paraules no sortiràn."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "cerca"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Resultats de la Cerca"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Cerca ràpida"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Aquesta Pàgina"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Canvis a la Versió %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Llista de canvis de la versió %(version)s generada automàticament"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Canvis a la llibreria"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Canvis a la API de C"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Altres canvis"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Link permanent a aquest títol"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Link permanent a aquesta definició"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Oculta Resultats de Cerca"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Versió"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "ve de la pàgina anterior"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Continua a la pàgina següent"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[imatge]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/cs/LC_MESSAGES/sphinx.js b/sphinx/locale/cs/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..0f069df
--- /dev/null
+++ b/sphinx/locale/cs/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "cs", "plural_expr": "(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2", "messages": {"Next topic": "Dal\u0161\u00ed t\u00e9ma", "Index": "Rejst\u0159\u00edk", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "V\u00edtejte! Toto je", "Copyright": "Ve\u0161ker\u00e1 pr\u00e1va vyhrazena", "C API changes": "Zm\u011bny API", "quick access to all modules": "rychl\u00fd p\u0159\u00edstup ke v\u0161em modul\u016fm", "&c [...]
\ No newline at end of file
diff --git a/sphinx/locale/cs/LC_MESSAGES/sphinx.mo b/sphinx/locale/cs/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..2d1382d
Binary files /dev/null and b/sphinx/locale/cs/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/cs/LC_MESSAGES/sphinx.po b/sphinx/locale/cs/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..99aa3d8
--- /dev/null
+++ b/sphinx/locale/cs/LC_MESSAGES/sphinx.po
@@ -0,0 +1,838 @@
+# Czech translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2008
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-12-26 13:32+0000\n"
+"Last-Translator: pm13 <petr.marhoun at gmail.com>\n"
+"Language-Team: Czech "
+"(http://www.transifex.com/projects/p/sphinx-1/language/cs/)\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "Dokumentace pro %s %s"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "viz %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "viz také %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Symboly"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d.%m.%Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Vestavěné funkce"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Úroveň modulu"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d.%m.%Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Obecný rejstřík"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "rejstřík"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "další"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "předchozí"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (v "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autor sekce: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autor modulu: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Autor kódu:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametry"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Vrací"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Typ navrácené hodnoty"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C funkce)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C člen)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C makro)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C typ)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C proměnná)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funkce"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "člen"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "typ"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "proměnná"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Vyvolá"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ třída)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ typ)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ člen)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ funkce)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "třída"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (vestavěná funkce)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (metoda %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (třída)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (globální proměnná nebo konstanta)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (atribut %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumenty"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "data"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atribut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Proměnné"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Vyvolá"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (v modulu %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (vestavěná proměnná)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (v modulu %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (vestavěná třída)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (třída v %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (metoda %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (statická metoda %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (statická metoda %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (třídní metoda %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (třídní metoda %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (atribut %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Rejstřík modulů Pythonu"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduly"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Zastaralé"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "výjimka"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metoda"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "třídní metoda"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statická metoda"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (zastaralé)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktiva)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (role)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktiva"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "role"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "proměnná prostředí; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%svolba příkazového řádku; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "termín v glosáři"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "token gramatiky"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "referenční návěstí"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "proměnná prostředí"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "volba programu"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Rejstřík"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Rejstřík modulů"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Vyhledávací stránka"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Nadtřídy: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias třídy :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[graf: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[graf]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(v %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[zdroj]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Todo"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<original entry>> se nachází v %s, řádka %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "původní záznam"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[dokumentace]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Kód modulu"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Zdrojový kód pro %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Přehled: kód modulu"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Všechny moduly s dostupným kódem</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Výstraha"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Upozornění"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Nebezpečí"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Chyba"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Rada"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Důležité"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Poznámka"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Viz také"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tip"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Varování"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Nové ve verzi %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Změněno ve verzi %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Zastaralé od verze %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "klíčové slovo"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operátor"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "příkaz"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "vestavěná funkce"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Obsah"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Vyhledávání"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "OK"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Zadejte hledané termíny nebo jméno modulu, třídy či funkce."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Ukázat zdroj"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Přehled"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Vítejte! Toto je"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "dokumentace pro"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "naposledy aktualizováno"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Rejstříky a tabulky:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Celkový obsah"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "seznam všech sekcí a podsekcí"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "prohledat tuto dokumentaci"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Celkový rejstřík modulů"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "rychlý přístup ke všem modulům"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "všechny funkce, třídy, termíny"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Rejstřík – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Celý rejstřík na jedné stránce"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Rejstřík podle písmene"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "může být obrovský"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigace"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Prohledat %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "O těchto dokumentech"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Veškerá práva vyhrazena"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Aktualizováno dne %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Vytvořeno pomocí <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Prohledat %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Přechozí téma"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "předchozí kapitola"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Další téma"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "další kapitola"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Pro podporu vyhledávání aktivujte JavaScript."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Toto je vyhledávací stránka. Zadejte klíčová slova a klikněte na "
+"\"hledat\". \n"
+"Vyhledávání automaticky hledá všechna slova, nebudou tedy nalezeny "
+"stránky obsahující jen některé z nich."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "hledat"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Výsledky vyhledávání"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"Vyhledávání nenalezlo žádný odpovídající dokument. Ujistěte se, že jste "
+"všechna slova zapsal/a správně a že jste vybral/a dostatek kategorií."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Rychlé vyhledávání"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Tato stránka"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Změny ve verzi %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automaticky generovaný seznam změn ve verzi %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Změny v knihovnách"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Změny API"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Ostatní změny"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Trvalý odkaz na tento nadpis"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Trvalý odkaz na tuto definici"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Skrýt výsledky vyhledávání"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Probíhá vyhledání"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Vyhledávání se připravuje..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Vyhledávání dokončeno, stránky odpovídající hledanému výrazu: %s."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", v "
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Rozbalit boční lištu"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Sbalit boční lištu"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Obsah"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Vydání"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Poznámky pod čarou"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "pokračujte na předchozí stránce"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Pokračujte na další stránce"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[obrázek: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[obrázek]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Navrácená hodnota: Vždy NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Navrácená hodnota: Nová reference."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Navrácená hodnota: Vypůjčená reference."
+
diff --git a/sphinx/locale/da/LC_MESSAGES/sphinx.js b/sphinx/locale/da/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..83c5ffc
--- /dev/null
+++ b/sphinx/locale/da/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "da", "plural_expr": "(n != 1)", "messages": {"Next topic": "N\u00e6ste emne", "Index": "Indeks", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Ophavsret", "C API changes": "\u00c6ndringer i C-API", "quick access to all modules": "hurtig adgang til alle moduler", "© Copyright %(copyright)s.": "© Ophavsret %(copyright)s.", "Global Module Index": "Globalt modulindeks", "Yo [...]
\ No newline at end of file
diff --git a/sphinx/locale/da/LC_MESSAGES/sphinx.mo b/sphinx/locale/da/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..bb081b9
Binary files /dev/null and b/sphinx/locale/da/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/da/LC_MESSAGES/sphinx.po b/sphinx/locale/da/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..e773216
--- /dev/null
+++ b/sphinx/locale/da/LC_MESSAGES/sphinx.po
@@ -0,0 +1,838 @@
+# Danish translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# askhl <asklarsen at gmail.com>, 2010-2011
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Danish "
+"(http://www.transifex.com/projects/p/sphinx-1/language/da/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "se %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "se også %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d. %B, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Indbyggede"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Modulniveau"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d. %b, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Generelt indeks"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "indeks"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "næste"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "forrige"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (i "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Afsnitsforfatter: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Modulforfatter: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Kodeforfatter: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Forfatter: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametre"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Returnerer"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Returtype"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C-funktion)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C-medlem)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C-makro)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C-type)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C-variabel)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funktion"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "medlem"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "type"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variabel"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Kaster"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++-klasse)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++-type)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++-medlem)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++-funktion)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "klasse"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (indbygget funktion)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (metode i %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (klasse)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (global variabel eller konstant)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (attribut i %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Parametre"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "data"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "attribut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variable"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Rejser"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (i modulet %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (indbygget variabel)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (i modulet %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (indbygget klasse)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (klasse i %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (metode i %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (statisk metode i %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (statisk metode i %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (klassemetode i %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (klassemetode i %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (attribut i %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python-modulindeks"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduler"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Forældet"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "undtagelse"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metode"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "klassemetode"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statisk metode"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (forældet)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktiv)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (rolle)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktiv"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "rolle"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "miljøvariabel; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%skommandolinjetilvalg; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "begreb i ordliste"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "grammatisk element"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "referenceetiket"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "miljøvariabel"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "programtilvalg"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Indeks"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Modulindeks"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Søgeside"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Baser: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias for :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[kilde]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Todo"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(Det <<oprindelige punkt>> befinder sig i %s, linje %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "oprindeligt punkt"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[dok]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Modulkode"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Kildekode for %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Oversigt: modulkode"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Alle moduler, der er kode tilgængelig for</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Vær opmærksom"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Forsigtig"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Fare"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Fejl"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Fif"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Vigtigt"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Bemærk"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Se også"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tip"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Advarsel"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Ny i version %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Ændret i version %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Forældet siden version %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "nøgleord"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "erklæring"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "indbygget funktion"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Indholdsfortegnelse"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Søg"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Søg"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Indtast søgeord eller navnet på et modul, en klasse eller en funktion."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Vis kilde"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Oversigt"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indeks og tabeller:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Fuldstændig indholdsfortegnelse"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "viser alle afsnit og underafsnit"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "søg i denne dokumentation"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Globalt modulindeks"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "hurtig adgang til alle moduler"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "alle funktioner, klasser, begreber"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Indeks – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Fuldt indeks på én side"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Indeksér sider efter bogstav"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "kan være enormt"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigation"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Søg i %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Om disse dokumenter"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Ophavsret"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Ophavsret</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Ophavsret %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Sidst opdateret %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Bygget med <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Søg i %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Forrige emne"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "forrige kapitel"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Næste emne"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "næste kapitel"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Aktivér venligst JavaScript for at aktivere\n"
+" søgefunktionalitet."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Her fra kan du søge i disse dokumenter. Indtast dine søgeord\n"
+" i boksen nedenfor og klik på \"søg\". Bemærk at søgefunktionen\n"
+" automatisk vil søge på alle ordene. Sider, der indeholder\n"
+" færre ord, vil ikke indgå i resultaterne."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "søg"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Søgeresultater"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Hurtig søgning"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Denne side"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Ændringer i version %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatisk oprettet liste af ændringer i version %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Biblioteksændringer"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Ændringer i C-API"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Andre ændringer"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Permalink til denne overskrift"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Permalink til denne definition"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Skjul søgeresultater"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Udfold sidebjælke"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Sammenfold sidebjælke"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Indhold"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Udgave"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Fodnoter"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "fortsat fra forrige side"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Fortsættes på næste side"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[billede]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/de/LC_MESSAGES/sphinx.js b/sphinx/locale/de/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..06a6340
--- /dev/null
+++ b/sphinx/locale/de/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "de", "plural_expr": "(n != 1)", "messages": {"Next topic": "N\u00e4chstes Thema", "Index": "Stichwortverzeichnis", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Willkommen! Dies ist", "Copyright": "Copyright", "C API changes": "C API-\u00c4nderungen", "quick access to all modules": "Schneller Zugriff auf alle Module", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global M [...]
\ No newline at end of file
diff --git a/sphinx/locale/de/LC_MESSAGES/sphinx.mo b/sphinx/locale/de/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..b91f71d
Binary files /dev/null and b/sphinx/locale/de/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/de/LC_MESSAGES/sphinx.po b/sphinx/locale/de/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..ec32d15
--- /dev/null
+++ b/sphinx/locale/de/LC_MESSAGES/sphinx.po
@@ -0,0 +1,841 @@
+# German translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Georg Brandl <g.brandl at gmx.net>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: German "
+"(http://www.transifex.com/projects/p/sphinx-1/language/de/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s Dokumentation"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "siehe %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "siehe auch %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Sonderzeichen"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d.%m.%Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Builtins"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Modulebene"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d.%m.%Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Stichwortverzeichnis"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "Index"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "weiter"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "zurück"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (in "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autor des Abschnitts: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autor des Moduls: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Autor des Quellcode: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s-%s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parameter"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Rückgabe"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Rückgabetyp"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C-Funktion)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C-Member)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C-Makro)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C-Typ)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C-Variable)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "Funktion"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "Member"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "Makro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "Typ"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "Variable"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Wirft"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++-Klasse)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++-Typ)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++-Member)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++-Funktion)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "Klasse"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (Standard-Funktion)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (Methode von %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (Klasse)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (globale Variable oder Konstante)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (Attribut von %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Parameter"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "Daten"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "Attribut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variablen"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Verursacht"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (im Modul %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (Standard-Variable)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (in Modul %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (Standard-Klasse)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (Klasse in %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (Methode von %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (statische Methode von %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (statische Methode von %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (Klassenmethode von %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (Klassenmethode von %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (Attribut von %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (Modul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python-Modulindex"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "Module"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Veraltet"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "Exception"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "Methode"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "Klassenmethode"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statische Methode"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "Module"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (veraltet)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (Direktive)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (Rolle)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "Direktive"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "Rolle"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "Umgebungsvariable; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sKommandozeilenoption; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "Glossareintrag"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "Grammatik-Token"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "Referenz-Label"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "Umgebungsvariable"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "Programmoption"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Stichwortverzeichnis"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Modulindex"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Suche"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Basisklassen: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "Alias von :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[Graph: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[Graph]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(in %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[Quelle]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Zu tun"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(Der <<ursprüngliche Eintrag>> steht in %s, Zeile %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "ursprüngliche Eintrag"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[Doku]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Modul-Quellcode"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Quellcode für %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Überblick: Modul-Quellcode"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Alle Module, für die Quellcode verfügbar ist</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Achtung"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Vorsicht"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Gefahr"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Fehler"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Hinweis"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Wichtig"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Bemerkung"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Siehe auch"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tipp"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Warnung"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Neu in Version %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Geändert in Version %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Veraltet ab Version %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "Schlüsselwort"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "Operator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "Objekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "Anweisung"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "Standard-Funktion"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Inhalt"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Suche"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Los"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr ""
+"Geben Sie Suchbegriffe oder einen Modul-, Klassen- oder Funktionsnamen "
+"ein."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Quelltext anzeigen"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Übersicht"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Willkommen! Dies ist"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "die Dokumentation für"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "zuletzt aktualisiert"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indizes und Tabellen:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Vollständiges Inhaltsverzeichnis"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "Liste aller Kapitel und Unterkapitel"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "Durchsuche diese Dokumentation"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Globaler Modulindex"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "Schneller Zugriff auf alle Module"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "Alle Funktionen, Klassen, Begriffe"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Stichwortverzeichnis – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Gesamtes Stichwortverzeichnis auf einer Seite"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Stichwortverzeichnis nach Anfangsbuchstabe"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "kann groß sein"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigation"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Suche in %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Über diese Dokumentation"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Zuletzt aktualisiert am %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Mit <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s "
+"erstellt."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Suche in %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Vorheriges Thema"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "vorheriges Kapitel"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Nächstes Thema"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "nächstes Kapitel"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Bitte aktivieren Sie JavaScript, wenn Sie die Suchfunktion nutzen wollen."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Von hier aus können Sie die Dokumentation durchsuchen. Geben Sie Ihre "
+"Suchbegriffe in das untenstehende Feld ein und klicken Sie auf "
+"\"Suchen\". Bitte beachten Sie, dass die Suchfunktion automatisch nach "
+"all diesen Worten suchen wird. Seiten, die nicht alle Worte enthalten, "
+"werden nicht in der Ergebnisliste erscheinen."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "suchen"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Suchergebnisse"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"Ihre Suche ergab keine Treffer. Bitte stellen Sie sicher, dass alle "
+"Wörter richtig geschrieben sind und genügend Kategorien ausgewählt sind."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Schnellsuche"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Diese Seite"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Änderungen in Version %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatisch generierte Liste der Änderungen in Version %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Bibliotheks-Änderungen"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API-Änderungen"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Andere Änderungen"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Permalink zu dieser Überschrift"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Permalink zu dieser Definition"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Suchergebnisse ausblenden"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Suchen"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Suche wird vorbereitet..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Die Suche ist fertig, es wurde(n) %s Seite(n) mit Treffern gefunden."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", in "
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Sidebar ausklappen"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Sidebar einklappen"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Inhalt"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Release"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Fußnoten"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "Fortsetzung der vorherigen Seite"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Fortsetzung auf der nächsten Seite"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[Bild: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[Bild]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Rückgabewert: Immer NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Rückgabewert: Neue Referenz."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Rückgabewert: Geliehene Referenz."
+
diff --git a/sphinx/locale/es/LC_MESSAGES/sphinx.js b/sphinx/locale/es/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..cd09807
--- /dev/null
+++ b/sphinx/locale/es/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "es", "plural_expr": "(n != 1)", "messages": {"Next topic": "Pr\u00f3ximo tema", "Index": "\u00cdndice", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "\u00a1Bienvenido! Este es", "Copyright": "Copyright", "C API changes": "Cambios en la API C", "quick access to all modules": "acceso r\u00e1pido a todos los m\u00f3dulos", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global [...]
\ No newline at end of file
diff --git a/sphinx/locale/es/LC_MESSAGES/sphinx.mo b/sphinx/locale/es/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..0fc1e88
Binary files /dev/null and b/sphinx/locale/es/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/es/LC_MESSAGES/sphinx.po b/sphinx/locale/es/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..8db5388
--- /dev/null
+++ b/sphinx/locale/es/LC_MESSAGES/sphinx.po
@@ -0,0 +1,846 @@
+# Spanish translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Guillem Borrell <guillem at torroja.dmt.upm.es>, 2011
+# Leonardo J. Caballero G. <leonardocaballero at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Leonardo J. Caballero G. <leonardocaballero at gmail.com>\n"
+"Language-Team: Spanish "
+"(http://www.transifex.com/projects/p/sphinx-1/language/es/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "documentación de %s - %s"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "ver %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "ver también %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Símbolos"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d de %B de %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Funciones incorporadas"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Nivel de módulo"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d de %B de %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Índice General"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "índice"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "siguiente"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "anterior"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (en "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autor de la sección: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autor del módulo: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Código del autor: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parámetros"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Devuelve"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Tipo del valor devuelto"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (función C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (miembro C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (tipo C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (variable C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "función"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "miembro"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "macro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tipo"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variable"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Lanzamientos"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (clase C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (tipo C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (miembro C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (función C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "clase"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (función incorporada)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (método de %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (clase)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (variable global o constante)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (atributo de %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumentos"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "dato"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atributo"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variables"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Muestra"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (en el módulo %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (variable incorporada)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (en el módulo %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (clase incorporada)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (clase en %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (método de %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (método estático de %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (método estático de %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (método de clase de %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (método de clase de %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (atributo de %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (módulo)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Índice de Módulos Python"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "módulos"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Obsoleto"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "excepción"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "método"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "método de la clase"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "método estático"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "módulo"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (obsoleto)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (directiva)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (rol)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "directiva"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "rol"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "variables de entorno; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sopción en línea de comandos; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "termino de glosario"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "gramática simbólica"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "etiqueta de referencia"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "variables de entorno"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "opción de programa"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Índice"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Índice de Módulos"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Página de Búsqueda"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Clases base: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias de :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[gráfica: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[gráfica]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(en %s versión %s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[fuente]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Por hacer"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(El <<entrada original>> se encuentra en %s, en la línea %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "entrada original"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[documentos]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Código de módulo"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Código fuente para %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Resumen: código de modulo"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Todos los módulos para los cuales disponen código</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Atención"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Prudencia"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Peligro"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Error"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Consejo"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Importante"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Nota"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Ver también"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Truco"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Advertencia"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Nuevo en la versión %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Distinto en la versión %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Obsoleto desde la versión %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "palabra clave"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operador"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objeto"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "sentencia"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "función incorporada"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Tabla de Contenidos"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Búsqueda"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Ir a"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr ""
+"Introduzca los términos de búsqueda o un nombre de módulo, clase o "
+"función."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Mostrar el código"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Resumen"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "¡Bienvenido! Este es"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "la documentación para"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "actualizado por última vez el"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Índices y tablas:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Índice de contenidos completo"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "muestra todas las secciones y subsecciones"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "buscar en esta documentación"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Índice Global de Módulos"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "acceso rápido a todos los módulos"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "todas las funciones, clases, términos"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Índice – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Índice completo en una página"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Índice alfabético de páginas"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "puede ser muy grande"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navegación"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Buscar en %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Sobre este documento"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\\\"%(path)s\\\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Actualizado por última vez en %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Creado con <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Buscar en %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Tema anterior"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "capítulo anterior"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Próximo tema"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "próximo capítulo"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Por favor, active JavaScript para habilitar la funcionalidad\n"
+" de búsqueda."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Este es el diálogo de búsqueda. Introduce los términos en el\n"
+" diálogo siguiente y pulsa \"buscar\". Note que el asistente buscará \n"
+" automáticamente todas las palabras. Las páginas que contengan \n"
+" menos palabras no aparecerán en la lista de resultados."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "buscar"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Resultados de la búsqueda"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"Su búsqueda no coincide con ningún documentos. Por favor, asegúrese de "
+"que todas las palabras estén correctamente escritas y que usted allá "
+"seleccionado las suficientes categorías."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Búsqueda rápida"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Esta página"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Cambios en la versión %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Lista de cambios generada automáticamente en la versión %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Cambios en la biblioteca"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Cambios en la API C"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Otros cambios"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Enlazar permanentemente con este título"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Enlazar permanentemente con esta definición"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Ocultar coincidencias de la búsqueda"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Buscando"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Preparando búsqueda..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+"Búsqueda finalizada, encontró %s página(s) acorde con la consulta de "
+"búsqueda."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", en "
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Expandir barra lateral"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Contraer barra lateral"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Contenidos"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Publicación"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Notas a pie de página"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "proviene de la página anterior"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Continúa en la página siguiente"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[imagen: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[imagen]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Valor de retorno: Siempre NULO."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Valor de retorno: Nueva referencia."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Valor de retorno: Referencia prestada."
+
diff --git a/sphinx/locale/et/LC_MESSAGES/sphinx.js b/sphinx/locale/et/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..e45950b
--- /dev/null
+++ b/sphinx/locale/et/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "et", "plural_expr": "(n != 1)", "messages": {"Next topic": "J\u00e4rgmine teema", "Index": "Indeks", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Tervitused! See on", "Copyright": "Autori\u00f5igused", "C API changes": "C API muutused", "quick access to all modules": "kiire ligip\u00e4\u00e4s k\u00f5igile moodulitele", "© Copyright %(copyright)s.": "© Autori\u00f5igused %(copyright)s." [...]
\ No newline at end of file
diff --git a/sphinx/locale/et/LC_MESSAGES/sphinx.mo b/sphinx/locale/et/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..3f1c6fc
Binary files /dev/null and b/sphinx/locale/et/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/et/LC_MESSAGES/sphinx.po b/sphinx/locale/et/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..57349ae
--- /dev/null
+++ b/sphinx/locale/et/LC_MESSAGES/sphinx.po
@@ -0,0 +1,837 @@
+# Estonian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Aivar Annamaa <aivar.annamaa at gmail.com>, 2011
+# Ivar Smolin <okul at linux ee>, 2012
+# Ivar Smolin <okul at linux.ee>, 2013-2014
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2014-04-30 06:58+0000\n"
+"Last-Translator: Ivar Smolin <okul at linux.ee>\n"
+"Language-Team: Estonian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/et/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s dokumentatsioon"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "vaata %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "vaata ka %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Pythoni täiustusettepanekud, PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d. %B %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Sisseehitatud"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Mooduli tase"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d. %b %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Üldindeks"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "indeks"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "järgmine"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "eelmine"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (pealkirjas "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Sektsiooni autor:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Mooduli autor:"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Koodi autor:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parameetrid"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Tagastab"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Tagastustüüp"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C funktsioon)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C liige)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C makro)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C tüüp)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C muutuja)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funktsioon"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "liige"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tüüp"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "muutuja"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ klass)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ tüüp)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ liige)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ funktsioon)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "klass"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (sisseehitatud funktsioon)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s meetod)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (klass)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (globaalmuutuja või konstant)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s atribuut)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumendid"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "andmed"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atribuut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Muutujad"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr ""
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (moodulis %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (sisseehitatud muutuja)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (moodulis %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (sisseehitatud klass)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (klass moodulis %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s meetod)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s staatiline meetod)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s staatiline meetod)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (klassi %s.%s meetod)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (klassi %s meetod)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s atribuut)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (moodul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Pythoni moodulite indeks"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moodulid"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Iganenud"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "erind"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "meetod"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "klassi meetod"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "staatiline meetod"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "moodul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (iganenud)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktiiv)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (roll)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktiiv"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "roll"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "keskkonnamuutuja; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%s käsurea valik; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "sõnastiku termin"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "grammatika märk"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "viite pealkiri"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "keskkonnamuutuja"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "programmi valik"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Indeks"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Mooduli indeks"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Otsinguleht"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Pärineb: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "klassi :class:`%s` sünonüüm"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[lähtekood]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Teha"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<Algne kirje>> asub failis %s real %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "algne kirje"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[dokumentatsioon]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Mooduli kood"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>%s lähtekood</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Ülevaade: mooduli kood"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Kõik lähtekoodiga moodulid</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Tähelepanu"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Ettevaatust"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Oht"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Viga"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Vihje"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Tähtis"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Märkus"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Vaata ka"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Nõuanne"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Hoiatus"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Uus versioonis %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Muudetud versioonis %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Iganenud alates versioonist %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "võtmesõna"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operaator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "lause"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "sisseehitatud funktsioon"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Sisukord"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Otsing"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Otsi"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Sisesta otsingusõna või mooduli/klassi/funktsiooni nimi."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Näita lähtekoodi"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Ülevaade"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Tervitused! See on"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "viimati uuendatud"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indeksid ja tabelid"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Täielik sisukord"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "toob välja kõik sektsioonid ja alamsektsioonid"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "otsi sellest dokumentatsioonist"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Globaalne moodulite indeks"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "kiire ligipääs kõigile moodulitele"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "kõik funktsioonid, klassid ja terminid"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Indeks – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Täisindeks ühel lehel"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Indeksi leheküljed algustähe kaupa"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "võib olla väga suur"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigatsioon"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Otsi %(docstitle)s piires"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Info selle dokumentatsiooni kohta"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Autoriõigused"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Autoriõigused</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Autoriõigused %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Viimati uuendatud %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Loodud <a href=\"http://sphinx-doc.org/\">Sphinxiga</a> (versioon: "
+"%(sphinx_version)s)."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Otsi %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Eelmine teema"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "eelmine jaotis"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Järgmine teema"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "järgmine jaotis"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Otsingu võimaldamiseks tuleb aktiveerida JavaScript."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Siin saad otsida käesolevast dokumentatsioonist. Sisesta otsisõnad "
+"allolevasse lahtrisse ning klõpsa \"Otsi\". Tulemuseks antakse "
+"leheküljed, mis sisaldavad kõiki otsisõnasid."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "otsi"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Otsingutulemused"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Kiirotsing"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Käesolev leht"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Muutused versioonis %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automaatselt genereeritud nimekiri versiooni %(version)s muutustest"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Teegi muutused"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API muutused"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Ülejäänud muutused"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Püsiviit sellele pealkirjale"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Püsiviit sellele definitsioonile"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Varja otsingutulemused"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Otsimine"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Otsingu ettevalmistamine..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Otsingu tulemusena leiti %s leht(e)."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Näita külgriba"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Varja külgriba"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Sisukord"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Redaktsioon"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Joonealused märkused"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "jätk eelmisele leheküljele"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Jätkub järgmisel lehel"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[pilt: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[pilt]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Tagastatav väärtus: alati NULL"
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/eu/LC_MESSAGES/sphinx.js b/sphinx/locale/eu/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..e4bfd8b
--- /dev/null
+++ b/sphinx/locale/eu/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "eu", "plural_expr": "(n != 1)", "messages": {"Next topic": "Hurrengo gaia", "Index": "Indizea", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Copyright", "C API changes": "C API aldaketak", "quick access to all modules": "modulu guztietara atzipen azkarra", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global Module Index": "Modulu indize globala", "Your [...]
\ No newline at end of file
diff --git a/sphinx/locale/eu/LC_MESSAGES/sphinx.mo b/sphinx/locale/eu/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..5aaa342
Binary files /dev/null and b/sphinx/locale/eu/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/eu/LC_MESSAGES/sphinx.po b/sphinx/locale/eu/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..7f22e55
--- /dev/null
+++ b/sphinx/locale/eu/LC_MESSAGES/sphinx.po
@@ -0,0 +1,836 @@
+# Basque translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Ales Zabala Alava <shagi at gisa-elkartea.org>, 2011
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Basque "
+"(http://www.transifex.com/projects/p/sphinx-1/language/eu/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s dokumentazioa"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "%s ikusi"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "ikusi %s baita ere"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Hobekuntza Proposamena; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%Y %B %d"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr ""
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Modulu maila"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%Y %b %d"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Indize orokorra"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "indizea"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "hurrengoa"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "aurrekoa"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (hemen: "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Atalaren egilea: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Moduluaren egilea: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Kodearen egilea: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Egilea:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametroak"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Itzultzen du"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Itzulketa mota"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C funtzioa)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C partaidea)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C makroa)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C mota)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C aldagaia)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funtzioa"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "partaidea"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makroa"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "mota"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "aldagaia"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Jaurtitzen du"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ klasea)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ mota)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ partaidea)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ funtzioa)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "klasea"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metodoa)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (klasea)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (aldagai globala edo konstantea)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s atributua)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumentuak"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "datuak"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atributua"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Aldagaiak"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Goratzen du"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (%s moduluan)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr ""
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (%s moduluan)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr ""
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (klasea %s-(e)n)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metodoa)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s metodo estatikoa)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s metodo estatikoa)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s klaseko metodoa)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s klaseko metodoa)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s atributua)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modulua)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python moduluen indizea"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduluak"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Zaharkitua"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "salbuespena"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metodoa"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "klaseko metodoa"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "metodo estatikoa"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modulua"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (zaharkitua)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (rola)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "rola"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "inguruneko aldagaia; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%skomando lerroko aukera; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "glosarioko terminoa"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "gramatikako token-a"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "erreferentzia etiketa"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "inguruneko aldagaia"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "programako aukera"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Indizea"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Moduluen indizea"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Bilaketa orria"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[iturburua]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Egitekoa"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "jatorrizko sarrera"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[dokumentazioa]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Moduluko kodea"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>%s(r)en iturburu kodea</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Gainbegirada: moduluko kodea"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Kodea eskuragarri duten modulu guztiak</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Adi"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Kontuz"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Arriskua"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Errorea"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Argibidea"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Garrantzitsua"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Nota"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Ikusi baita ere"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Iradokizuna"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Kontuz"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Berria %s bertsioan"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "%s bertsioan aldatuta"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "%s bertsiotik aurrera zaharkituta"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "gako-hitza"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "eragiketa"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objetua"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "sententzia"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Eduki taula"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Bilatu"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Joan"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Sartu bilaketa terminoa edo modulu, klase edo funtzioaren izena."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Iturburua ikusi"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Gainbegirada"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indizeak eta taulak:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Eduki taula osoa"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "atal eta azpiatal guztiak zerrendatu"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "dokumentazio honetan bilatu"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Modulu indize globala"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "modulu guztietara atzipen azkarra"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "funtzio, klase, termino guztiak"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Indizea – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Indize guztia orri batean"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Indize orriak hizkika"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "handia izan daiteke"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Nabigazioa"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Bilatu %(docstitle)s(e)n"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Dokumentu hauen inguruan"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Azken aldaketa: %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"<a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s erabiliz"
+" sortutakoa."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "%(docstitle)s bilatu"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Aurreko gaia"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "aurreko kapitulua"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Hurrengo gaia"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "hurrengo kapitulua"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Mesedez, gaitu JavaScript-a bilaketa erabili ahal izateko."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Honekin dokumentu hauetan bilatu dezakezu. Sartu zure bilaketa hitzak\n"
+"ondoko kutxan eta \"bilatu\" sakatu. Kontutan eduki bilaketa funtzioak\n"
+"hitz guztiak bilatuko dituela. Hitz gutxiago dituzten orriak ez dira \n"
+"emaitzen zerrendan agertuko."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "bilatu"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Bilaketa emaitzak"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Bilaketa azkarra"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Orri hau"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "%(version)s bertsioko aldaketak — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatikoki sortutako %(version)s bertsioaren aldaketen zerrenda"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Liburutegi aldaketak"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API aldaketak"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Beste aldaketak"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Goiburu honetarako esteka iraunkorra"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Definizio honetarako esteka iraunkorra"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Bilaketa bat-etortzeak ezkutatu"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Alboko barra luzatu"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Alboko barra tolestu"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Edukiak"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Argitalpena"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Oin-oharrak"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "aurreko orritik jarraitzen du"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Hurrengo orrian jarraitzen du"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[irudia]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/fa/LC_MESSAGES/sphinx.js b/sphinx/locale/fa/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..c732a96
--- /dev/null
+++ b/sphinx/locale/fa/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "fa", "plural_expr": "0", "messages": {"Next topic": "\u0645\u0648\u0636\u0648\u0639 \u0628\u0639\u062f\u06cc", "Index": "\u0641\u0647\u0631\u0633\u062a", "%(filename)s — %(docstitle)s": "", "Welcome! This is": "", "Copyright": "\u06a9\u067e\u06cc \u0631\u0627\u06cc\u062a", "C API changes": "C API \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a", "quick access to all modules": "\u062f\u0633\u062a\u0631\u0633\u06cc \u0633\u0631\u06cc\u0639 \u0628 [...]
\ No newline at end of file
diff --git a/sphinx/locale/fa/LC_MESSAGES/sphinx.mo b/sphinx/locale/fa/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..993243c
Binary files /dev/null and b/sphinx/locale/fa/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/fa/LC_MESSAGES/sphinx.po b/sphinx/locale/fa/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..ca1a303
--- /dev/null
+++ b/sphinx/locale/fa/LC_MESSAGES/sphinx.po
@@ -0,0 +1,831 @@
+# Persian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Persian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/fa/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr ""
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "درونی سازی"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "در سطح ماژول"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr ""
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "فهرست کلی"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "فهرست"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "بعدی"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "قبلی"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr ""
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr ":نویسنده این بخش"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "نویسنده این ماژول:"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr ":نویسنده"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "پارامترها"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr ""
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "نوع برگشتی"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C تابع)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C عضو)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C ماکرو)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C نوع)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C متغیر)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr ""
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr ""
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr ""
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr ""
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr ""
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr ""
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (توابع درونی)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s متد)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s مشخصه)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr ""
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "برانگیختن"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (در ماژول %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (متغیر درونی)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (در ماژول %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (کلاس درونی)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (کلاس در %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s متد)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s متد استاتیک)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s متد استاتیک)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s مشخصه)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (ماژول)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "ماژول ها"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "منسوخ شده"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "استثناء"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr ""
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "ماژول"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "%s متغیرهای عمومی؛"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sگزینه خط فرمان; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr ""
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "فهرست"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "فهرست ماژول ها"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "صفحه جستجو"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "در دست انجام"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "دقت"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "ملاحظه"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "خطر"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "خطا"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "تذکر"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "مهم"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "توجه"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "همچنین ملاحظه نمائید"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "نکته"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "هشدار"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "جدید در نسخه %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "تغییر داده شده در نسخه %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "منسوخ شده از نسخه %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "کلمه کلیدی"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "عملگر"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "شیء"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "گذاره"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "توابع درونی"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "فهرست عناوین"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "جستجو"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "برو"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "نمایش سورس"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "بررسی اجمالی"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "ایندکس ها و جداول:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "فهرست کامل مطالب"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "فهرست تمامی بخش ها و زیر مجموعه ها"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "جستجو در این اسناد"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "فهرست کلی ماژول ها"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "دسترسی سریع به تمامی متدها"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "تمامی توابع ، کلاس ها ، اصطلاحات"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "فهرست – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "فهرست کامل در یک صفحه"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "فهرست صفحات بر اساس حروف"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "ناوبری"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "جستجو در %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "درباره این مستندات"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "کپی رایت"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr ". %(last_updated)s آخرین بروز رسانی در"
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+". <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s ایجاد "
+"شده با"
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "جستجو %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "موضوع قبلی"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "فصل قبلی"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "موضوع بعدی"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "فصل بعدی"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "جستجو"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "نتایج جستجو"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "جستجو سریع"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "صفحه فعلی"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "تغییرات در نسخه %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "لیست تولید شده خودکار از تغییرات در نسخه %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "تغییرات کتابخانه ایی"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API تغییرات"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "دگر تغییرات"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "لینک ثابت به این سر مقاله"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "لینک ثابت به این تعریف"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "عدم نمایش نتایج یافت شده"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "انتشار"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr ""
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr ""
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr ""
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/fi/LC_MESSAGES/sphinx.js b/sphinx/locale/fi/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..c85994d
--- /dev/null
+++ b/sphinx/locale/fi/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "fi", "plural_expr": "(n != 1)", "messages": {"Next topic": ">>", "Index": "Sis\u00e4llysluettelo", "%(filename)s — %(docstitle)s": "", "Welcome! This is": "", "Copyright": "", "C API changes": "", "quick access to all modules": "", "© Copyright %(copyright)s.": "", "Global Module Index": "Yleinen moduulien sis\u00e4llysluettelo", "Your search did not match any documents. Please make sure that all words are spelled correctly and that yo [...]
\ No newline at end of file
diff --git a/sphinx/locale/fi/LC_MESSAGES/sphinx.mo b/sphinx/locale/fi/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..4e210c3
Binary files /dev/null and b/sphinx/locale/fi/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/fi/LC_MESSAGES/sphinx.po b/sphinx/locale/fi/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..f721262
--- /dev/null
+++ b/sphinx/locale/fi/LC_MESSAGES/sphinx.po
@@ -0,0 +1,830 @@
+# Finnish translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2009
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Finnish "
+"(http://www.transifex.com/projects/p/sphinx-1/language/fi/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d.%m.%Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr ""
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Moduulitaso"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d.%m.%Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Yleinen sisällysluettelo"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "hakemisto"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr ">"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "<"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr ""
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Luvun kirjoittaja: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Moduulin kirjoittaja: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Tekijä: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr ""
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr ""
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr ""
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr ""
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr ""
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr ""
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr ""
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr ""
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr ""
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr ""
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr ""
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr ""
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr ""
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr ""
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr ""
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr ""
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr ""
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr ""
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr ""
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr ""
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (moduuli)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduulit"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Poistettu"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr ""
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr ""
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "moduuli"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (poistettu)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr ""
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr ""
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr ""
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Sisällysluettelo"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Moduuli sisällysluettelo"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Etsi sivu"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Tehtävä vielä"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Huom"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Varoitus"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Vaara"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Virhe"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Vihje"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Tärkeä"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Muista"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Katso myös"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Vihje"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Varoitus"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Uusi versiossa %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Muutettu versiossa %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Poistettu versiosta %s alkaen"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr ""
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr ""
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr ""
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr ""
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Sisällysluettelo"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Etsi"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Siirry"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Anna etsittävä termi tai moduuli, luokka tai funktio"
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Näytä lähdekoodina"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Yhteenveto"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Yleinen moduulien sisällysluettelo"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Hakemisto yhtenä luettelona"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Hakemisto aakkostus sivuttain"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "voi olla iso"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navikointi"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Tietoja tästä documentistä"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "<<"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "<<"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr ">>"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr ">>"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Javascript pitää olla sallittu, jotta etsintä toimii."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr "Anna hakusanat kokonaan, osasanoilla ei haeta."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "etsi"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Etsinnän tulos"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Pikahaku"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Tämä sivu"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Muutos versiosta %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automaattisesti luotu muutoshistoria alkaen versiosta %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Piilota löydetyt"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr ""
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr ""
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr ""
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr ""
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/fr/LC_MESSAGES/sphinx.js b/sphinx/locale/fr/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..bb67cbe
--- /dev/null
+++ b/sphinx/locale/fr/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "fr", "plural_expr": "(n > 1)", "messages": {"Next topic": "Sujet suivant", "Index": "Index", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Bienvenue ! ceci est", "Copyright": "Copyright", "C API changes": "Modifications de l'API C", "quick access to all modules": "acc\u00e8s rapide \u00e0 l'ensemble des modules", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global Module [...]
\ No newline at end of file
diff --git a/sphinx/locale/fr/LC_MESSAGES/sphinx.mo b/sphinx/locale/fr/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..06618fa
Binary files /dev/null and b/sphinx/locale/fr/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/fr/LC_MESSAGES/sphinx.po b/sphinx/locale/fr/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..e20cb70
--- /dev/null
+++ b/sphinx/locale/fr/LC_MESSAGES/sphinx.po
@@ -0,0 +1,849 @@
+# French translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Christophe kryskool <christophe.chauvet at gmail.com>, 2013
+# Larlet davidbgk <larlet at gmail.com>, 2008
+# fgallaire <fgallaire at gmail.com>, 2010
+# Georg Brandl <g.brandl at gmx.net>, 2014
+# Jean-Daniel Browne <jeandaniel.browne at gmail.com>, 2010
+# Lilian Besson <naereen at crans.org>, 2013-2014
+# Sebastien Douche <sdouche at gmail.com>, 2008
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2014-02-11 22:24+0000\n"
+"Last-Translator: Lilian Besson <naereen at crans.org>\n"
+"Language-Team: French "
+"(http://www.transifex.com/projects/p/sphinx-1/language/fr/)\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "documentation %s %s"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "voir %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "voir aussi %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Symboles"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Fonctions de base"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Module"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Index général"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "index"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "suivant"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "précédent"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr "(dans"
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Auteur de la section : "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Auteur du module : "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Auteur du code :"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Auteur : "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Paramètres"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Retourne"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Type retourné"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (fonction C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (membre C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (type C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (variable C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "fonction"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "membre"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "macro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "type"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variable"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Déclenche"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (classe C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (type C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (membre C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (fonction C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "classe"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (fonction de base)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (méthode %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (classe)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (variable globale ou constante)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (attribut %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Arguments"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "données"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "attribut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variables"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Lève"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (dans le module %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (variable de base)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (dans le module %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (classe de base)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (classe dans %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (méthode %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (méthode statique %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (méthode statique %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (méthode de classe %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (méthode de classe %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (attribut %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (module)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Index des modules Python"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "modules"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Obsolète"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "exception"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "méthode"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "méthode de classe"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "méthode statique"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "module"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (obsolète)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (directive)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (role)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "directive"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "role"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "variable d'environnement; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%s option de ligne de commande; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "terme du glossaire"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "élément de grammaire"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "étiquette de référence"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "variable d'environnement"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "option du programme"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Index"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Index du module"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Page de recherche"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr "Bases: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias de :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[graph: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[graph]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(disponible dans %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[source]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "À faire"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(L'<<entrée orginale>> se trouve dans %s, à la ligne %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "entrée originale"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[docs]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Code du module"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Code source de %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Vue d'ensemble : code du module"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Modules pour lesquels le code est disponible</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Attention"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Prudence"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Danger"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Erreur"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Indice"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Important"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Note"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Voir aussi"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Astuce"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Avertissement"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Introduit dans la version %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Modifié dans la version %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Obsolète depuis la version %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "mot-clé"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "opérateur"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objet"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "état"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "fonction de base"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Table des Matières"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Recherche"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Go"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Saisissez un mot clef ou un nom de module, classe ou fonction."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Montrer la source"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Résumé"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Bienvenue ! ceci est"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "la documentation pour"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "dernière modification"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indices et Tables :"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Table des matières complète"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "lister l'ensemble des sections et sous-sections"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "rechercher dans cette documentation"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Index général des modules"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "accès rapide à l'ensemble des modules"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "toutes les fonctions, classes, termes"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Index – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Index complet sur une seule page"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Indexer les pages par lettre"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "peut être énorme"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigation"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Recherchez dans %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "À propos de ces documents"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Mis à jour le %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Créé avec <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Rechercher %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Sujet précédent"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "Chapitre précédent"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Sujet suivant"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "Chapitre suivant"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Veuillez activer le JavaScript pour que la recherche fonctionne."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Vous pouvez effectuer une recherche au sein des documents. Saisissez les "
+"termes\n"
+"de votre recherche dans le champs ci-dessous et cliquez sur "
+"\"rechercher\". Notez que la fonctionnalité de recherche\n"
+"va automatiquement chercher parmi l'ensemble les mots. Les pages\n"
+"contenant moins de mots n'apparaîtront pas dans la liste des résultats."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "rechercher"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Résultats de la recherche"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"Votre recherche ne correspond à aucun document. Veuillez vérifier que les"
+" mots sont correctement orthographiés et que vous avez sélectionné assez "
+"de catégories."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Recherche rapide"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Cette page"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Modifications dans la version %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Liste auto-générée des modifications due à la version %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Modifications de la bibliothèque"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Modifications de l'API C"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Autres modifications"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Lien permanent vers ce titre"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Permalien vers cette définition"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Cacher les résultats de la recherche"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Recherche en cours"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Préparation à la recherche..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+"La recherche est finie, %s page(s) trouvée(s) qui corresponde(nt) à la "
+"recherche."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", dans"
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Agrandir la barre latérale"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Réduire la barre latérale"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Contenu"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Version"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Notes de bas de page"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "Suite de la page précédente"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Suite sur la page suivante"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[image: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[image]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Valeur de retour : toujours NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Valeur de retour : nouvelle référence"
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Valeur de retour : référence empruntée"
+
diff --git a/sphinx/locale/he/LC_MESSAGES/sphinx.js b/sphinx/locale/he/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..0d47c04
--- /dev/null
+++ b/sphinx/locale/he/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "he", "plural_expr": "(n != 1)", "messages": {"Next topic": "\u05e0\u05d5\u05e9\u05d0 \u05d4\u05d1\u05d0", "Index": "\u05d0\u05d9\u05e0\u05d3\u05e7\u05e1", "%(filename)s — %(docstitle)s": "", "Welcome! This is": "", "Copyright": "\u05d6\u05db\u05d5\u05d9\u05d5\u05ea \u05e9\u05de\u05d5\u05e8\u05d5\u05ea", "C API changes": "", "quick access to all modules": "\u05d2\u05d9\u05e9\u05d4 \u05de\u05d4\u05d9\u05e8\u05d4 \u05dc\u05db\u05dc \u05d4\u05d [...]
\ No newline at end of file
diff --git a/sphinx/locale/he/LC_MESSAGES/sphinx.mo b/sphinx/locale/he/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..937b148
Binary files /dev/null and b/sphinx/locale/he/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/he/LC_MESSAGES/sphinx.po b/sphinx/locale/he/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..69a0629
--- /dev/null
+++ b/sphinx/locale/he/LC_MESSAGES/sphinx.po
@@ -0,0 +1,832 @@
+# Hebrew translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2011
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Hebrew "
+"(http://www.transifex.com/projects/p/sphinx-1/language/he/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "תיעוד %s %s"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "ראה %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "ראה גם %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr ""
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr ""
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr ""
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "רמת המודול"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr ""
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr ""
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "אינדקס"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "הבא"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "הקודם"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr "(בתוך"
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "מחבר הקטע:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "מחבר המודול:"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "מחבר הקוד:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "מחבר:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "פרמטרים"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr ""
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr ""
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr ""
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr ""
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr ""
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr ""
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr ""
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "פונקציה"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr ""
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "מאקרו"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr ""
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "משתנה"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (מחלקת C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (פונקציית C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "מחלקה"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr ""
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "משתנים"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr ""
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr ""
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr ""
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr ""
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr ""
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr ""
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr ""
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr ""
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr ""
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr ""
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "מודול"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "משתנה סביבה; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sאופציית שורת הפקודה ; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "משתנה סביבה"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "אינדקס"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "מודול אינדקס"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "דף חיפוש"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[מקור]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "לעשות"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(ה <<הרשומה המקורית>> ממוקמת ב %s, שורה %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "הטקסט המקורי"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[תיעוד]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>הראה קוד מקור ל %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>כל המודולים שיש להם קוד זמין</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "תשומת לב"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "זהירות"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "סכנה"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "שגיאה"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "רמז"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "חשוב"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "הערה"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "ראה גם"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "טיפ"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "אזהרה"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "חדש בגרסה %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "השתנה בגרסה %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr " לא מומלץ לשימוש מגרסה %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "מילת מפתח"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr ""
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr ""
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr ""
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "תוכן עניינים"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "חיפוש"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "לך"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "הכנס מושגים לחיפוש או שם מודול, מחלקה או פונקציה."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "הצג מקור"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "סקירה כללית"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "תוכן עניינים מלא"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "חפש בתיעוד זה"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "אינדקס מודולים גלובלי"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "גישה מהירה לכל המודולים"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "כל הפונקציות, המחלקות, המושגים"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "אינדקס מלא בעמוד אחד"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "עמודי אינדקס לפי אותיות"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "עשוי להיות עצום"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "ניווט"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "חפש בתוך %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "על מסמכים אלו"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "זכויות שמורות"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">זכויות שמורות</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© זכויות שמורות %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "עודכן לאחרונה ב %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "חפש %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "נושא קודם"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "פרק קודם"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "נושא הבא"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "פרק הבא"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"אנא הפעל ג'אואסקריפט ע\"מ לאפשר את\n"
+" החיפוש."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "חיפוש"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "תוצאות החיפוש"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "חיפוש מהיר"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "עמוד זה"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "שינויים בגרסה %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "יצר אוטומטית רשימה של שינויים בגרסה %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "שינויים אחרים"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "קישור קבוע לכותרת זו"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "קישור קבוע להגדרה זו"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "הסתר תוצאות חיפוש"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "הרחב סרגל צד"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "כווץ סרגל צד"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "תוכן"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "מהדורה"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "הערות שוליים"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "המשך מעמוד קודם"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "המשך בעמוד הבא"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[תמונה]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/hr/LC_MESSAGES/sphinx.js b/sphinx/locale/hr/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..3d3cdd1
--- /dev/null
+++ b/sphinx/locale/hr/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "hr", "plural_expr": "n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2", "messages": {"Next topic": "Slijede\u0107a tema", "Index": "Abecedni popis", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Sva prava zadr\u017eana", "C API changes": "C API changes", "quick access to all modules": "brz dostup do svih modulov", "© Copyright %(copyright)s.": [...]
\ No newline at end of file
diff --git a/sphinx/locale/hr/LC_MESSAGES/sphinx.mo b/sphinx/locale/hr/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..1b86bec
Binary files /dev/null and b/sphinx/locale/hr/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/hr/LC_MESSAGES/sphinx.po b/sphinx/locale/hr/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..5d973e4
--- /dev/null
+++ b/sphinx/locale/hr/LC_MESSAGES/sphinx.po
@@ -0,0 +1,838 @@
+# Croatian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Croatian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/hr/)\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Ugrađeni dijelovi"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Nivo modula"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Opceniti abecedni indeks"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "abecedni indeks"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "naprijed"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "nazad"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (u "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autor sekcije: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autor modula: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametri"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Vraća"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Vraća tip"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C funkcija)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C član)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C makro)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C tip)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C varijabla)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funkcija"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "član"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr ""
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tip"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr ""
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ razred)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ tip)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ član)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ funkcija)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "razred"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (ugrađene funkcije)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metoda)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (razred)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s atribut)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atribut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Podiže"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (u modulu %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (ugrađene variable)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (u modulu %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (ugrađen razred)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (razred u %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metoda)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s statična metoda)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s statična metoda)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s atribut)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "Moduli"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Zastarjelo"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "izuzetak"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statična metoda"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (zastarjelo)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "varijabla okruženja; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%scommand line parameter; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "varijabla okruženja"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Abecedni popis"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Popis modula"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Tražilica"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Osnove: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "nadimak za :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Todo"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Pozor"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Pažnja"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Opasnost"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Greška"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Savjet"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Važno"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Napomena"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Pogledaj i"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Savjet"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Upozorenje"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Novo u verziji %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Promijenjeno u verziji %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Zastarijelo od verzije %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "ključna riječ"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "izjava"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "ugrađen funkcije"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Pregled sadržaja"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Traži"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Naprijed"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Unesi ime modula, razreda ili funkcije."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Prikaži izvorni kod"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Pregled"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Kazala i tabele:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Potpuna tabela sadržaja"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "prikaži sve sekcije i podsekcije"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "traži po dokumentaciji"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Općeniti popis modula"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "brz dostup do svih modulov"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "sve funkcije, razredi, izrazi"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Index – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Potpun indeks na jednoj strani"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Indeksiraj stranice po slovu"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "može biti veliko"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigacija"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Traži između %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "O ovim dokumentima"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Sva prava zadržana"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Sva prava zadržana</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Sva prava zadržana %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Zadnji put ažurirano %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Izrađeno sa <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Traži %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Prijašnja tema"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "Prijašnje poglavje"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Slijedeća tema"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "slijedeće poglavje"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Molimo omogućite JavaScript\n"
+" za djelovanje tražilice."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "traži"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Rezultati pretrage"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Brzo pretraživanje"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Trenutna stranica"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Changes in Version %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatically generated list of changes in version %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Library changes"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API changes"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Ostale promjene"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Link na taj naslov"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Link na tu definiciju"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Sakrij rezultate pretrage"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Distribucija"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "nastavak sa prethodne stranice"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "nastavak na slijedećoj stranici"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[slika]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/hu/LC_MESSAGES/sphinx.js b/sphinx/locale/hu/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..bf9c3f6
--- /dev/null
+++ b/sphinx/locale/hu/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "hu", "plural_expr": "(n != 1)", "messages": {"Next topic": "K\u00f6vetkez\u0151 t\u00e9mak\u00f6r", "Index": "T\u00e1rgymutat\u00f3", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Minden jog fenntartva", "C API changes": "C API v\u00e1ltoz\u00e1sok", "quick access to all modules": "gyors hozz\u00e1f\u00e9r\u00e9s az \u00f6sszes modulhoz", "© Copyright %(copyright)s.": "© [...]
\ No newline at end of file
diff --git a/sphinx/locale/hu/LC_MESSAGES/sphinx.mo b/sphinx/locale/hu/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..a004ee6
Binary files /dev/null and b/sphinx/locale/hu/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/hu/LC_MESSAGES/sphinx.po b/sphinx/locale/hu/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..8316686
--- /dev/null
+++ b/sphinx/locale/hu/LC_MESSAGES/sphinx.po
@@ -0,0 +1,840 @@
+# Hungarian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2011
+# szunyog <szunyog at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: szunyog <szunyog at gmail.com>\n"
+"Language-Team: Hungarian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/hu/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s dokumentáció"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "lásd %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "lásd még %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Szimbólumok"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Fejlesztési Javaslatok; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%Y. %m. %d."
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Beépített"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Modul szint"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%b %d, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Általános tárgymutató"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "nyitóoldal"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "következő"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "előző"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " ("
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Fejezet szerző: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Modul szerző: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Kód szerző: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Szerző: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Paraméterek"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Visszatérési érték"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Visszatérés típusa"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C függvény)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C tagváltozó)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C makró)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C típus)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C változó)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "függvény"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "tag"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makró"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "típus"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "változó"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ osztály)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ típus)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ tagváltozó)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ függvény)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "osztály"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (beépített függvény)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metódus)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (osztály)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (globális változó vagy konstans)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s attribútum)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumentum"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "adat"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "attribútum"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Változók"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr ""
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (%s modulban)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (beépített változó)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (%s modulban)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (beépített osztály)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (osztály %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metódus)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s statikus metódus)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s statikus metódus)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s osztály metódus)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s osztály metódus)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s attribútum)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python Modul Mutató"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "modulok"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Elavult"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "kivétel"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metódus"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "osztály szintű metódus"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statikus metódus"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (elavult)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktíva)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (szerepkör)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktíva"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "szerepkör"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "környezeti változó; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sparancssor opció; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "szójegyzék"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "nyelvtani jel"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "referencia cimke"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "környezeti változó"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "program opció"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Tárgymutató"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Modulok"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Keresés"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Alapul: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "álneve :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[graph: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[graph]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(%s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[source]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Tennivaló"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(Az <<eredeti bejegyzés>> megtalálható a(z) %s, %d sor.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "eredeti bejegyzés"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[docs]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Modul forráskód"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>%s forráskódja</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Áttekintés: modul forráskód"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Az összes modul, melynek forrása elérhető</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Figyelem"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Figyelem"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Veszély"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Hiba"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Tipp"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Fontos"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Megjegyzés"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Lásd még"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Javaslat"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Figyelem"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Új a(z) %s verzióban"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "A %s verzióban változott"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Elavult a(z) %s verzió óta"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "kulcsszó"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operátor"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objektum"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr ""
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "beépített függvény"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Tartalomjegyzék"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Keresés"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Ok"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Adjon meg egy keresendő kifejezést, modul, osztály vagy funkció nevet."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Forrás megtekintése"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Áttekintés"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "utoljára frissítve"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Tárgymutató és táblázatok"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Teljes tartalomjegyzék"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "kilistázza az összes fejezetet és alfejezetet"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "keresés ebben a dokumentációban"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Teljes modul tárgymutató"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "gyors hozzáférés az összes modulhoz"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "összes funkció, osztály és kifejezés"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Tárgymutató – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Teljes tárgymutató egy oldalon"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Oldalak ABC sorrendben"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "nagy lehet"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigáció"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Keresés köztük: %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Névjegy ezekről a dokumentumokról"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Minden jog fenntartva"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Minden jog fenntartva</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Minden jog fenntartva %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Utolsó frissítés %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"<a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s "
+"használatával készült."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Keresés %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Előző témakör"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "előző fejezet"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Következő témakör"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "következő fejezet"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Kérem engedélyezze a JavaScriptet a kereső funkció\n"
+" használatához."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Erről az oldalról indíthatja kereséseit. Írja be a kulcsszavakat\n"
+" az alábbi szövegdobozba, majd kattintson a \"keresés\" gombra.\n"
+" Ügyeljen arra, hogy a keresés megadott kulcsszavak mindegyikét\n"
+" figyelembe veszi, így azok az oldalak, melyek nem tartalmazzák az\n"
+" összes kifejezést, nem jelennek meg a találati listában."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "keresés"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Keresési Eredmények"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Gyorskeresés"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Ez az Oldal"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Változások a(z) %(version)s változatban — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatikusan generált változáslista a(z) %(version)s változathoz"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Könyvtár változások"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API változások"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Egyéb változások"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Hivatkozás erre a fejezetcímre"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Hivatkozás erre a definícióra"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Keresési Találatok Elrejtése"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Keresés folyamatban"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Felkészülés a keresésre..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "A keresés befejeződött, %s oldal egyezik a keresési felételeknek."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Oldalsáv kinyitása"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Oldalsáv összezárása"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Tartalom"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Kiadás"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Lábjegyzetek"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "folytatás az előző oldalról"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "A következő oldalon folytatódik"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[image: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[image]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Visszatérési érték: Mindig NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Visszatérési érték: Új referencia érték."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/id/LC_MESSAGES/sphinx.js b/sphinx/locale/id/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..5175201
--- /dev/null
+++ b/sphinx/locale/id/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "id", "plural_expr": "0", "messages": {"Next topic": "Topik berikutnya", "Index": "Indeks", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Selamat Datang! Ini adalah", "Copyright": "Copyright", "C API changes": "Perubahan API C", "quick access to all modules": "akses cepat semua modul", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global Module Index": "Index Modul Global" [...]
\ No newline at end of file
diff --git a/sphinx/locale/id/LC_MESSAGES/sphinx.mo b/sphinx/locale/id/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..a03a553
Binary files /dev/null and b/sphinx/locale/id/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/id/LC_MESSAGES/sphinx.po b/sphinx/locale/id/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..1be44f0
--- /dev/null
+++ b/sphinx/locale/id/LC_MESSAGES/sphinx.po
@@ -0,0 +1,842 @@
+# Indonesian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2009
+# Sakti Dwi Cahyono <54krpl at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Sakti Dwi Cahyono <54krpl at gmail.com>\n"
+"Language-Team: Indonesian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/id/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "dokumentasi %s %s"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "lihat %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "lihat juga %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Simbol"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Modul Internal"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Level Modul"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Indeks Umum"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "index"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "berikut"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "sebelum"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (dalam "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Penyusun bagian:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Penyusun modul: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Penulis kode:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Penyusun: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parameter"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Kembali"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Return type"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (fungsi C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (anggota C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (tipe C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (variabel C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "fungsi"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "anggota"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "macro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tipe"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variabel"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Throws"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (class C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (tipe C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (anggota C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (fungsi C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "class"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (fungsi built-in)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (method %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (class)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (variabel global atau konstan)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (atribut %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumen"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "data"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atribut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variabel"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Raises"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (di modul %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (variabel built-in)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (di modul %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (class built-in)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (class di %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (method %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (method static %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (method static %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (method class %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (method class %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (atribut %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (module)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Indeks Modul Python"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "modul"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Akan ditinggalkan"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "eksepsi"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "method"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "method class"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "method static"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (obsolet)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktif)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (role)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktif"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "role"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "variabel environment; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sopsi command line; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "daftar istilah"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "token grammar"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "label referensi"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "variabel environment"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "opsi program"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Indeks"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Indeks Modul"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Pencarian Halaman"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Bases: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias dari :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[graph: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[graph]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(di %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[sumber]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Todo"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<original entry>> terletak pada %s, baris ke %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "entri asli"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[docs]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Kode modul"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Kode sumber untuk %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Tinjauan: kode modul"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Semua modul dimana kode tersedia</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Pehatian"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Hati-hati"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Bahaya"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Kesalahan"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Hint"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Penting"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Catatan"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "lihat juga"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tip"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Peringatan"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Baru pada versi %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Berubah pada versi %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Ditinggalkan sejak versi %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "keyword"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "object"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "statement"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "fungsi built-in"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Daftar Isi"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Pencarian"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Go"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Masukkan term pencarian atau nama modul, class atau fungsi."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Lihat Sumber"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Tinjauan"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Selamat Datang! Ini adalah"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "dokumentasi untuk"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "terakhir diperbarui"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Index dan tabel:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Daftar Isi Lengkap"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "daftar semua seksi dan subseksi"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "pencarian pada dokumentasi ini"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Index Modul Global"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "akses cepat semua modul"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "semua fungsi, class, term"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Index – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Index penuh dalam satu halaman"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Index halaman berdasarkan huruf"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "dapat menjadi besar"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigasi"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Pencarian dalam %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Tentang dokumen ini"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Terakhir diperbarui pada %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Dibuat menggunakan <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Pencarian %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Topik sebelum"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "bab sebelum"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Topik berikutnya"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "bab berikutnya"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Tolong aktifkan JavaScript untuk melakukan pencarian.\n"
+" "
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Dari sini dapat dilakukan pencarian pada dokumentasi. Masukkan\n"
+" kata yang dicari pada kotak dibawah dan klik \"search\". Catatan "
+"untuk fungsi pencarian\n"
+" akan secara otomatis mencari semua kata. Halaman\n"
+" yang berisi kata yang sedikat tidak dimunculkan pada daftar hasil."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "pencarian"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Hasil Pencarian"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"Tidak ada dokumen yang cocok dengan pencarian anda. Pastikan semua kata "
+"ditulis dengan benar dan sudah memilih cukup kategori."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Pencarian cepat"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Halaman Ini"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Perubahan pada Versi %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Daftar perubahan dibuat otomatis untuk versi %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Perubahan library"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Perubahan API C"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Perubahan lain"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Link permanent untuk headline ini"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Link permanent untuk definisi ini"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Sembunyikan Hasil Pencarian"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Pencarian"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Penyiapkan pencarian..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Pencarian selesai, menemukan %s halaman yang cocok dengan kueri pencarian."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", di"
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Buka sidebar"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Tutup sidebar"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Konten"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Rilis"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Catatan kaki"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "lanjutan dari halaman sebelumnya"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Lanjut ke halaman berikutnya"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[gambar: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[gambar]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Nilai return: Selalu NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Nilai return: Referensi baru."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Nilai return: Referensi pinjaman."
+
diff --git a/sphinx/locale/it/LC_MESSAGES/sphinx.js b/sphinx/locale/it/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..98bee3f
--- /dev/null
+++ b/sphinx/locale/it/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "it", "plural_expr": "(n != 1)", "messages": {"Next topic": "Argomento successivo", "Index": "Indice", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Benvenuto! Questa \u00e8", "Copyright": "Copyright", "C API changes": "Modifiche nelle API C", "quick access to all modules": "accesso veloce ai moduli", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global Module Index": "Ind [...]
\ No newline at end of file
diff --git a/sphinx/locale/it/LC_MESSAGES/sphinx.mo b/sphinx/locale/it/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..ad20441
Binary files /dev/null and b/sphinx/locale/it/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/it/LC_MESSAGES/sphinx.po b/sphinx/locale/it/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..e81f30b
--- /dev/null
+++ b/sphinx/locale/it/LC_MESSAGES/sphinx.po
@@ -0,0 +1,845 @@
+# Italian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Paolo Cavallini <cavallini at faunalia.it>, 2013
+# Roland Puntaier <roland.puntaier at chello.at>, 2013
+# Sandro Dentella <sandro at e-den.it>, 2008
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Roland Puntaier <roland.puntaier at chello.at>\n"
+"Language-Team: Italian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/it/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s documentazione"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "vedi %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "vedi anche %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Simboli"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Builtins"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Al livello del modulo"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d/%b/%Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Indice generale"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "indice"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "successivo"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "precedente"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (in "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autore della sezione: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autore del modulo: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Autore del codice: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autore: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametri"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Ritorna"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Tipo di ritorno"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (funzione C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (membro C )"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (tipo C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (variabile C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funzione"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "membro"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "macro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tipo"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variabile"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Solleva"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (classe C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (tipo C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (membro C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (funzione C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "classe"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (funzione built-in)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metodo)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (classe)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (variabile globale o costante)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s attributo)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Parametri"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "dati"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "attributo"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variabili"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Solleva"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (nel modulo %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (variabile built-in)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (nel modulo %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (classe built-in)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (classe in %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metodo)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s metodo statico)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s metodo statico)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s metodo della classe)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s metodo della classe)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s attributo)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modulo)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Indice del modulo Python"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduli"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Deprecato"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "eccezione"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metodo"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "metodo della classe"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "metodo statico"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modulo"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (deprecato)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direttiva)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (ruolo)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direttiva"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "ruolo"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "variabile d'ambiente, %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sopzione di linea di comando; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "voce del glossario"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "elemento grammaticale"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "etichetta di riferimento"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "variabile d'ambiente"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "opzione del programma"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Indice"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Indice dei Moduli"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Cerca"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr "Basi: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias per :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[grafico: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[grafico]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(in %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[sorgente]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Da fare"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(La <<riga originale>> si trova in %s, linea %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "riga originale"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[documenti]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Codice del modulo"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Codice sorgente per %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Vista generale: codice del modulo"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Tutti i moduli di cui è disponibile il codice</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Attenzione"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Attenzione"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Pericolo"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Errore"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Consiglio"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Importante"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Nota"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Vedi anche"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Suggerimento"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Avvertimento"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Nuovo nella versione %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Cambiato nella versione %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Deprecato dalla versione %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "keyword"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operatore"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "oggetto"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "statement"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "funzione built-in"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Tabella dei contenuti"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Cerca"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Vai"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Inserisci un termine di ricerca un modulo, classe o nome di funzione"
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Mostra sorgente"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Sintesi"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Benvenuto! Questa è"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "la documentazione per"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "ultimo aggiornamento"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indici e tabelle:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Tabella dei contenuti completa"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "elenca l'insieme delle sezioni e sottosezioni"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "cerca in questa documentazione"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Indice dei moduli"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "accesso veloce ai moduli"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "tutte le funzioni, classi e moduli"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Indice – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Indice completo in una pagina"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Indice delle pagine per lettera"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "può essere enorme"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigazione"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Cerca in %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "A proposito di questi documenti"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Ultimo aggiornamento %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Creato con <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Cerca %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Argomento precedente"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "capitolo precedente"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Argomento successivo"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "capitolo successivo"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Attiva JavaScript per abilitare la funzione⏎\n"
+"di ricerca."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Puoi effettuare una ricerca in questi documenti. Immetti le parole chiave"
+" \n"
+" della tua ricerca nel riquadro sottostante \"cerca\". Nota che la "
+"funzione\n"
+" di ricerca cerca automaticamente per tutte le parole. Le pagine\n"
+" che contendono meno parole non compariranno nei risultati di ricerca."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "cerca"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Risultati della ricerca"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"La tua ricerca non corrisponde a nessun documento. Verifica che tutte le "
+"parole siano scritte correttamente e di aver scelto un numero sufficiente"
+" di categorie."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Ricerca veloce"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Questa pagina"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Modifiche nella Versione %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Lista delle modifiche generata automaticamente nella versione %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Modifiche nella libreria"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Modifiche nelle API C"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Altre modifiche"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "link permanente per questa intestazione"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "link permanente per questa definizione"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Nascondi i risultati della ricerca"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Cerca"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Preparo la ricerca..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Ricerca completata, trovata/e %s pagina/e corrispondenti."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", in"
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Espandi la barra laterale"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Comprimi la barra laterale"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Contenuti"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Release"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Note a piè di pagina"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "continua dalla pagina precedente"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Continua alla pagina successiva"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[immagine: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[immagine]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Restituisci il valore: Sempre NULL"
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Restituisci il valore: Nuovo riferimento"
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Restituisci il valore: riferimento in prestito"
+
diff --git a/sphinx/locale/ja/LC_MESSAGES/sphinx.js b/sphinx/locale/ja/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..d8a3e6d
--- /dev/null
+++ b/sphinx/locale/ja/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "ja", "plural_expr": "0", "messages": {"Next topic": "\u6b21\u306e\u30c8\u30d4\u30c3\u30af\u3078", "Index": "\u7d22\u5f15", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Welcome! This is", "Copyright": "\u8457\u4f5c\u6a29", "C API changes": "C API \u306b\u95a2\u3059\u308b\u5909\u66f4", "quick access to all modules": "\u5168\u30e2\u30b8\u30e5\u30fc\u30eb\u65e9\u898b\u8868", "© Copyright %(copy [...]
\ No newline at end of file
diff --git a/sphinx/locale/ja/LC_MESSAGES/sphinx.mo b/sphinx/locale/ja/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..099f730
Binary files /dev/null and b/sphinx/locale/ja/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/ja/LC_MESSAGES/sphinx.po b/sphinx/locale/ja/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..fa2a74a
--- /dev/null
+++ b/sphinx/locale/ja/LC_MESSAGES/sphinx.po
@@ -0,0 +1,837 @@
+# Japanese translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# WAKAYAMA Shirou <shirou.faw at gmail.com>, 2013
+# Akitoshi Ohta <fire.kuma8 at gmail.com>, 2011
+# Kouhei Sutou <kou at clear-code.com>, 2011
+# Takayuki Shimizukawa <shimizukawa at gmail.com>, 2013
+# WAKAYAMA Shirou <shirou.faw at gmail.com>, 2014
+# Yasushi Masuda <whosaysni at gmail.com>, 2008
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2014-07-31 01:13+0000\n"
+"Last-Translator: WAKAYAMA Shirou <shirou.faw at gmail.com>\n"
+"Language-Team: Japanese "
+"(http://www.transifex.com/projects/p/sphinx-1/language/ja/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s ドキュメント"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "%sを参照"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "%sも参照"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "記号"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%Y 年 %m 月 %d 日"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "組み込み"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "モジュールレベル"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%Y 年 %m 月 %d 日"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "総合索引"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "索引"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "次へ"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "前へ"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (in "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "この節の作者: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "モジュールの作者: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "コードの作者: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "作者: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "パラメタ"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "戻り値"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "戻り値の型"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C の関数)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C のメンバ変数)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C のマクロ)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C のデータ型)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C の変数)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "の関数"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "のメンバ変数"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "のマクロ"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "のデータ型"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "変数"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "例外"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ のクラス)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ のデータ型)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ のメンバ変数)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ の関数)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "クラス"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (組み込み関数)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s のメソッド)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (クラス)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (グローバル変数または定数)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s の属性)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "引数"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "データ"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "の属性"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "変数"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "例外"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (%s モジュール)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (組み込み変数)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (%s モジュール)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (組み込みクラス)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (%s のクラス)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s のメソッド)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s の静的メソッド)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s の静的メソッド)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s のクラスメソッド)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s のクラスメソッド)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s の属性)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (モジュール)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Pythonモジュール索引"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "モジュール"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "撤廃"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "例外"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "メソッド"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "クラスメソッド"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "の静的メソッド"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "モジュール"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (撤廃)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (ディレクティブ)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (ロール)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "ディレクティブ"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "ロール"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "環境変数; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sコマンドラインオプション; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "用語集の項目"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "文法トークン"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "参照ラベル"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "環境変数"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "プログラムオプション"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "索引"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "モジュール索引"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "検索ページ"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " ベースクラス: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ":class:`%s` のエイリアス"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[グラフ: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[グラフ]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(in %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[ソース]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "課題"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<元のエントリ>> は、 %s の %d 行目です)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "元のエントリ"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[ドキュメント]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "モジュールコード"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>%s のソースコード</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "概要: モジュールコード"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>全モジュールのうち、コードを読めるもの</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "注意"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "ご用心"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "危険"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "エラー"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "ヒント"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "重要"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "注釈"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "参考"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "ちなみに"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "警告"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "バージョン %s で追加"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "バージョン %s で変更"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "バージョン %s で撤廃"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "キーワード"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "演算子"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "オブジェクト"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "文"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "組み込み関数"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "目次"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "検索"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "検索"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "モジュール、クラス、または関数名を入力してください"
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "ソースコードを表示"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "概要"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Welcome! This is"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "the documentation for"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "最終更新"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "索引と表一覧:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "総合目次"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "章/節一覧"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "ドキュメントを検索"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "モジュール総索引"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "全モジュール早見表"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "関数、クラスおよび用語総覧"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "索引 – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "総索引"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "頭文字別索引"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "大きい場合があるので注意"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "ナビゲーション"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "%(docstitle)s 内を検索"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "このドキュメントについて"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "著作権"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "最終更新: %(last_updated)s"
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"このドキュメントは <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s で生成しました。"
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "%(docstitle)s 内を検索"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "前のトピックへ"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "前の章へ"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "次のトピックへ"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "次の章へ"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "検索機能を使うには JavaScript を有効にしてください。"
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr "このページからドキュメントを検索できます。キーワードを下のボックスに入力して、「検索」をクリックしてください。入力された全てのキーワードを含むページが検索されます。一部のキーワードしか含まないページは検索結果に表示されないので注意してください。"
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "検索"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "検索結果"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr "検索した文字列はどの文書にも見つかりませんでした。すべての単語が正確に記述されているか、あるいは、十分なカテゴリーが選択されているか確認してください。"
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "クイック検索"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "このページ"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "バージョン %(version)s の変更点 — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "バージョン %(version)s の変更点(このリストは自動生成されています)"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "ライブラリに関する変更"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API に関する変更"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "その他の変更"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "このヘッドラインへのパーマリンク"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "この定義へのパーマリンク"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "検索結果を隠す"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "検索中"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "検索を準備しています..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "検索が完了し、 %s ページ見つけました。"
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", in "
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "サイドバーを展開"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "サイドバーをたたむ"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "コンテンツ"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "リリース"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "注記"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "前のページからの続き"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "次のページに続く"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[画像: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[画像]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "返り値: 常にNULL。"
+
+#~ msgid "Return value: New reference."
+#~ msgstr "返り値: 新たな参照"
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "返り値: 借用参照"
+
diff --git a/sphinx/locale/ko/LC_MESSAGES/sphinx.js b/sphinx/locale/ko/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..a4339d8
--- /dev/null
+++ b/sphinx/locale/ko/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "ko", "plural_expr": "0", "messages": {"Next topic": "\ub2e4\uc74c \ud56d\ubaa9", "Index": "\uc0c9\uc778", "%(filename)s — %(docstitle)s": "", "Welcome! This is": "", "Copyright": "\uc800\uc791\uad8c", "C API changes": "C API\uc5d0 \ub300\ud55c \ubcc0\uacbd", "quick access to all modules": "\ubaa8\ub4e0 \ubaa8\ub4c8 \uc870\uacac\ud45c", "© Copyright %(copyright)s.": "", "Global Module Index": "\ubaa8\ub4c8 \ucd1d \uc0c9\uc778", "Your se [...]
\ No newline at end of file
diff --git a/sphinx/locale/ko/LC_MESSAGES/sphinx.mo b/sphinx/locale/ko/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..85b8949
Binary files /dev/null and b/sphinx/locale/ko/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/ko/LC_MESSAGES/sphinx.po b/sphinx/locale/ko/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..c955724
--- /dev/null
+++ b/sphinx/locale/ko/LC_MESSAGES/sphinx.po
@@ -0,0 +1,829 @@
+# Korean translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Korean "
+"(http://www.transifex.com/projects/p/sphinx-1/language/ko/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "%s 문서"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "%s 참조"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%Y년 %m월 %d일"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "기본"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "모듈 수준"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%Y년 %m월 %d일"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "전체 색인"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "색인"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "다음"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "이전"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr ""
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr ""
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr ""
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr ""
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "매개 변수"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "반환"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "반환 형식"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C 함수)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C 멤버 변수)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C 매크로)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C 데이터 형식)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C 변수)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "함수"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "멤버 변수"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "매크로"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "데이터 형식"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "변수"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "예외"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ 클래스)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ 데이터 형식)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++의 멤버 변수)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ 함수)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "클래스"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() 내장 함수)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s 메서드)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (클래스)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (전역 변수 또는 상수)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s의 속성)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "인수"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "데이터"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "속성"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "변수"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "예외"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (%s 모듈)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (내장 변수)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (%s 모듈)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (내장 변수)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (%s 종류)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr ""
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s의 정적 메서드)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s 클래스 메서드)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr ""
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (모듈)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python 모듈 목록"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "모듈"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "폐지"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "예외"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "메소드"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "클래스 메소드"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "정적 메서드"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "모듈"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (지시문)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (역할)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "지시자"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "역할"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "환경 변수; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%s 명령; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "용어의 항목"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "문법 토큰"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "참조 레이블"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "환경 변수"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "프로그램 옵션"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "색인"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "모듈 목록"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "검색 페이지"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[소스]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "과제"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "원래 항목"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[문서]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "모듈 코드"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "설명: 모듈 코드"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "주의"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "조심"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "위험"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "오류"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "힌트"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "중요"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "주석"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "더 보기"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "참고"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "경고"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "버전 %s에 추가"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "버전 %s으로 변경"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "버전 %s 폐지"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "키워드"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "연산자"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "객체"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "글"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "내장 함수"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "목차"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "검색"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "바로 가기"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "모듈, 클래스 또는 함수 이름을 입력하십시오."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "소스 코드를 보려면"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "개요"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "색인 및 표 목록:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "종합 목차"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "영역별 목차"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "문서 검색"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "모듈 총 색인"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "모든 모듈 조견표"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "함수, 클래스 및 용어 개관"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "일반 색인"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "알파벳별 색인"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "큰 경우가 있으므로 주의"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "탐색"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "%(docstitle)s에서 찾기"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "이 문서 정보"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "저작권"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "최종 업데이트: %(last_updated)s"
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "%(docstitle)s에서 찾기"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "이전 항목"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "이전 장"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "다음 항목"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "다음 장"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "검색"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "검색 결과"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "빠른 검색"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "현재 문서"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "버전 %(version)s의 변경 사항 (이 목록은 자동으로 생성합니다)"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "라이브러리에 대한 변경"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API에 대한 변경"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "다른 변경 사항"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "제목 주소"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "정의 주소"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "검색 결과 숨기기"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "사이드바 열기"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "사이드바 닫기"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "내용"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "출시"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "참고"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "이전 페이지에서 계속"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "일반 색인"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[그림]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/lt/LC_MESSAGES/sphinx.js b/sphinx/locale/lt/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..bae97ae
--- /dev/null
+++ b/sphinx/locale/lt/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "lt", "plural_expr": "(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)", "messages": {"Next topic": "Kita tema", "Index": "Indeksas", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Autoriaus teis\u0117s", "C API changes": "C API pakeitimai", "quick access to all modules": "greitas vis\u0173 moduli\u0173 pasiekimas", "© Copyright %(copyright)s.": "© [...]
\ No newline at end of file
diff --git a/sphinx/locale/lt/LC_MESSAGES/sphinx.mo b/sphinx/locale/lt/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..97c9145
Binary files /dev/null and b/sphinx/locale/lt/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/lt/LC_MESSAGES/sphinx.po b/sphinx/locale/lt/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..b053ff7
--- /dev/null
+++ b/sphinx/locale/lt/LC_MESSAGES/sphinx.po
@@ -0,0 +1,840 @@
+# Lithuanian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# DALIUS DOBRAVOLSKAS <DALIUS at SANDBOX.LT>, 2010
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Lithuanian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/lt/)\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"(n%100<10 || n%100>=20) ? 1 : 2)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%Y-%m-%d"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Įtaisytieji"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Modulio lygis"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%Y-%m-%d"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Bendras indeksas"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "indeksas"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "kitas"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "praeitas"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (kuris yra "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Skyriaus autorius: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Modulio autorius: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Kodo autorius: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autorius: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametrai"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Grąžinamos reikšmės"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Grąžinamos reikšmės tipas"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C funkcija)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C narys)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C makrokomanda)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C tipas)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C kintamasis)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funkcija"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "narys"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makrokomanda"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tipas"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "kintamasis"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Išmeta"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ tipas)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ narys)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ funkcija)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "klasė"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (itaisytoji funkcija)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metodas)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (klasė)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (globalus kintamasis arba konstanta)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s atributas)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumentais"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "duomenys"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atribudas"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Kintamieji"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Sukelia"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (modulyje %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (įtaisytasis kintamasis)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (modulje %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (įtaisytoji klasė)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (klasė iš %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metodas)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s statinis metodas)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s statinis metodas)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s klasės metodas)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s klasės metodas)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s atributas)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modulis)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduliai"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Atmestas"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "išimtis"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metodas"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "klasės metodas"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statinis metodas"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modulis"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (atmestas)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktyva)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (rolė)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktyva"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "rolė"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "aplinkos kintamasis; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%skomandinės eilutės parinktis; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "aiškinamasis terminas"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "gramatinė leksema"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "nuorodos požymis"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "aplinkos kintamasis"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "programos parinktis"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Indeksas"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Modulio indeksas"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Paieškos puslapis"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Bazės: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ":class:`%s` alternatyvus vardas"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[šaltinis]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Padaryti"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<original entry>> galima rasti %s, eilutėje %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "originalus įrašas"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[dokumentai]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Modulio kodas"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Kodas %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Apžvalga: modulio kodas"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Visi moduliai turintys kodą</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Dėmesio"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Atsargiai"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Pavojinga"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Klaida"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Patarimas"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Svarbu"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Pastaba"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Taip pat žiūrėkite"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Patarimas"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Įspėjimas"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Nauja %s versijoje"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Pakeista %s versijoje"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Nebepalaikoma nuo %s versijos"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "bazinis žodis"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operatorius"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objektas"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "sakinis"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "įtaisytoji funkcija"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Turinys"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Paieška"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Pirmyn"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Įveskite paieškos terminą arba modulio, klasės ar funkcijos vardą."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Rodyti pirminį kodą"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Apžvalga"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indeksai ir lentelės:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Pilnas Turinys"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "surašyti visus skyrius ir poskyrius"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "ieškoti šiame dokumente"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Globalus Modulio Indeksas"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "greitas visų modulių pasiekimas"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "visos funkcijos, klasės ir terminai"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Indeksas – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Pilnas indeksas viename puslapyje"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Indekso puslapiai pagal raidę"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "gali būti didelis"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigacija"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Ieškoti tarp %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Apie šiuos dokumentus"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Autoriaus teisės"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Autoriaus teisės</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Autoriaus teisės %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Paskutinis atnaujinimas %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Sukurta naudojant <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Ieškoti %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Praeita tema"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "praeita dalis"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Kita tema"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "kita dalis"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Prašome aktyvuoti JavaScript, kad veiktų paieškos\n"
+" funkcionalumas."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Čia jūs galite ieškoti šiuose dokumentuose. Įveskite savo paieškos\n"
+" žodžius į lauką apačioje ir paspauskite \"ieškoti\". Pastebėsime, kad"
+" paieškos\n"
+" funkcija automatiškai ieškos visų žodžių. Puslapiai,\n"
+" kuriuose yra mažiau žodžių nepasirodys tarp paieškos rezultatų."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "ieškoti"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Paieškos rezultatai"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Greitoji paieška"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Šis puslapis"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Pasikeitimai versijoje %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatiškai sugeneruotas pakeitimų %(version)s versijoje sąrašas"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Bibliotekos pakeitimai"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API pakeitimai"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Kiti pakeitimai"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Nuoroda į šią antraštę"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Nuoroda į šį apibrėžimą"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Paslėpti paieškos rezultatus"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Išplėsti šoninę juostą"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Paslėpti šoninę juostą"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Turinys"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Leidimas"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Išnašos"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "tęsinys iš praeito puslapio"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Tęsinys kitame puslapyje"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[paveiksliukas]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/lv/LC_MESSAGES/sphinx.js b/sphinx/locale/lv/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..669d6f0
--- /dev/null
+++ b/sphinx/locale/lv/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "lv", "plural_expr": "(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)", "messages": {"Next topic": "n\u0101ko\u0161a t\u0113ma", "Index": "Indekss", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Copyright", "C API changes": "Izmai\u0146as iek\u0161 C API", "quick access to all modules": "\u0101tra piek\u013cuve visiem moduliem", "© Copyright %(copyright)s.": "© Copyright %(c [...]
\ No newline at end of file
diff --git a/sphinx/locale/lv/LC_MESSAGES/sphinx.mo b/sphinx/locale/lv/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..ab1e9df
Binary files /dev/null and b/sphinx/locale/lv/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/lv/LC_MESSAGES/sphinx.po b/sphinx/locale/lv/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..880c1db
--- /dev/null
+++ b/sphinx/locale/lv/LC_MESSAGES/sphinx.po
@@ -0,0 +1,837 @@
+# Latvian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Latvian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/lv/)\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 :"
+" 2)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr ""
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d.%m.%Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Iebūvētie"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Moduļu līmenis"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d.%m.%Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Vispārējs indekss"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "indekss"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "nākošais"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "iepriekšējs"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (iekš "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Sekcijas autors: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Moduļa autors: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Koda autors: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autors: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametri"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Atgriež"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Atgriežamais tips"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C funkcija)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C loceklis)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C makross)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C tips)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C mainīgais)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funkcija"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "loceklis"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makross"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tips"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "mainīgais"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Izmet"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ klase)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ tips)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ loceklis)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ funkcija)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "klase"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (iebūvēta funkcija)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metods)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (globālais mainīgais vai konstanta)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s atributs)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumenti"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "dati"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atributs"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Mainīgie"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Ceļ"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (moduļī %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (iebūvētais mainīgais)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (moduļī %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (iebūvēta klase)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (klase iekš %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metods)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s statiskais metods)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s statiskais metods)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s klases metods)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s klases metods)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s atributs)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modulis)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduļi"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Nav ieteicams"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "izņēmums"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metods"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "klases metods"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statiskais metods"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modulis"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktīva)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (role)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktīva"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "role"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "apkārtnes mainīgais; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%skomandrindas opcija; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "glosārija termins"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "gramatiskais marķieris"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "atsauces virsraksts"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "apkārtnes mainīgais"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "programmas opcija"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Indekss"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Moduļu indekss"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Atlases lapa"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Bāzes: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "aizstājvārds klasei :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[kods]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Jāizdara"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<original entry>> atrodas iekš %s, rinda %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "sākotnējs ieraksts"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[dokumenti]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Moduļa teksts"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>%s izejas teksts</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Apskats: moduļa teksts"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Visi moduļi, kuriem ir izejas teksti</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Uzmanību"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Uzmanies"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Bīstami"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Kļūda"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Mājiens"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Svarīgi"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Piezīme"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Skat.arī"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Padoms"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Brīdinājums"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Jauns versijā %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Mainīts versijā %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Neieteicams no versijas %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "atslēgas vārds"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operators"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objekts"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "priekšraksts"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "iebūvēta funkcija"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Saturs"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Meklēt"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Izpildīt"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Ievadiet meklējamus terminus vai moduļa, klases vai funkcijas vārdu."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Rādīt izejas tekstu"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Apskats"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indeksi un tabulas:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Pilns saturs"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "rāda visas sekcijas un apakšsekcijas"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "meklēt šajā dokumentācijā"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Vispārējs moduļu indekss"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "ātra piekļuve visiem moduliem"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "visas funkcijas, klases un termini"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Indekss – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Pilns indekss vienā lappusē"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Lappušu indekss pēc burtiem"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "var būt milzīgs"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigācija"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Meklēt iekš %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Par šiem dokumentiem"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Pēdējas izmaiņas %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Sagatavots izmantojot <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "%(docstitle)s meklēšana"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "iepriekšēja tēma"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "iepriekšēja sadaļa"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "nākoša tēma"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "nākoša sadaļa"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Lai iespējotu meklēšanu, lūdzu aktivizēt JavaScript."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Šeit Jūs varat meklēt šajos dokumentos. Norādiet meklējamus vārdus\n"
+" ievada lauka un uzklikšķiniet pogu \"meklēt\". Lūdzu ievērojiet,\n"
+" ka meklēšanas programma atradīs tikai tos dokumentus, kuros ir\n"
+" visi ievadītie vārdi. Dokumenti, kuros ir tikai daļa no ievadītiem\n"
+" vārdiem, netiks atlasīti."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "meklēt"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Atlases rezultāti"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Ātra meklēšana"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Šī lappuse"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Izmaiņas versijā %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automātiski sagatavots izmaiņu saraksts versijai %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Bibliotēkas izmaiņas"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Izmaiņas iekš C API"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Citas izmaiņas"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Pastāvīga norāde šo virsrakstu"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Pastāvīga norāde uz šo definīciju"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Paslēpt atlases vārdus"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Izplest sānjoslu"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Savērst sānjoslu"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Saturs"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Izlaidums"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Vēres"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "turpinājums no iepriekšējās lappuses"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Turpnājums nākošā lappusē"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[attēls: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[attēls]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/mk/LC_MESSAGES/sphinx.js b/sphinx/locale/mk/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..8328cb6
--- /dev/null
+++ b/sphinx/locale/mk/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "mk", "plural_expr": "(n % 10 == 1 && n % 100 != 11) ? 0 : 1", "messages": {"Next topic": "", "Index": "", "%(filename)s — %(docstitle)s": "", "Welcome! This is": "", "Copyright": "", "C API changes": "", "quick access to all modules": "", "© Copyright %(copyright)s.": "", "Global Module Index": "", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories. [...]
\ No newline at end of file
diff --git a/sphinx/locale/mk/LC_MESSAGES/sphinx.mo b/sphinx/locale/mk/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..eac3eb1
Binary files /dev/null and b/sphinx/locale/mk/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/mk/LC_MESSAGES/sphinx.po b/sphinx/locale/mk/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..bab84ec
--- /dev/null
+++ b/sphinx/locale/mk/LC_MESSAGES/sphinx.po
@@ -0,0 +1,830 @@
+# Macedonian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# vvangelovski <vvangelovski at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: vvangelovski <vvangelovski at gmail.com>\n"
+"Language-Team: Macedonian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/mk/)\n"
+"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s документација"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "погледни %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "погледни %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Симболи"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Предлог за подобрување на Python; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Вградени"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Ниво на модул"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Главна содржина"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "содржина"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "следна"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "претходна"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (во "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Автор на секцијата:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Автор на модул:"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Автор на код:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Автор: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Параметри"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Враќа"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Повратен тип"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C функција)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C член)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C макро)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C тип)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C променлива)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "функција"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "член"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "макро"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "тип"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "променлива"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Фрла"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ класа)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ тип)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ член)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ функција)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "класа"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (вградена функција)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s метод)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (класа)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr ""
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr ""
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr ""
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr ""
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr ""
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr ""
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr ""
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr ""
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr ""
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr ""
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr ""
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr ""
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr ""
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr ""
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr ""
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr ""
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr ""
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr ""
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr ""
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr ""
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr ""
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr ""
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr ""
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr ""
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr ""
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr ""
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr ""
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr ""
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr ""
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr ""
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr ""
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr ""
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr ""
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr ""
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr ""
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr ""
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr ""
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr ""
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr ""
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr ""
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr ""
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr ""
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr ""
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr ""
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js b/sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..ae01bb8
--- /dev/null
+++ b/sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "nb_NO", "plural_expr": "(n != 1)", "messages": {"Next topic": "Neste emne", "Index": "Index", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Copyright", "C API changes": "Endringer i C API", "quick access to all modules": "snarvei til alle moduler", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global Module Index": "Global Modulindex", "Your search did no [...]
\ No newline at end of file
diff --git a/sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo b/sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..d3c0123
Binary files /dev/null and b/sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po b/sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..46094dc
--- /dev/null
+++ b/sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po
@@ -0,0 +1,832 @@
+# Norwegian Bokmål (Norway) translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Norwegian Bokmål (Norway) "
+"(http://www.transifex.com/projects/p/sphinx-1/language/nb_NO/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "se %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "se også %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%B %d, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Innebygde"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Modulnivå"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%b %d, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Hovedindex"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "index"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "neste"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "forrige"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr "(i "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Seksjon forfatter: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Modul forfattar: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Kildekode forfatter: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Forfatter: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametere"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Returnere"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Retur type"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C-funktion)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C-medlem)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C-makro)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C-type)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C-variabel)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funksjon"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "medlem"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "type"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variabel"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Kaster"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ klasse)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ type)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ medlem)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ funksjon)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "klasse"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (innebygd funksjon)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metode)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (klasse)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (global variabel eller konstant)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s attribut)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argument"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "data"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "attributt"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variabler"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Hever"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (i modul %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (innebygd variabel)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (i modul %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (innebygd klasse)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (klasse i %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metode)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s statisk metode)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s statisk metode)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s klassemetode)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s klassemetode)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s attributt)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python Modulindex"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduler"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Foreldet"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "untak"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metode"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "klassemetode"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statisk metode"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (foreldet)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktiv)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (rolle)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktiv"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "rolle"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "miljøvariabel; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%skommandolinje valg; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "ordliste"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "grammatikk token"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "referanse-etikett"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "miljøvariabel"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "programvalg"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Index"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Modulindex"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Søkeside"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Baser: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias for :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[kilde]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Todo"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(Den <<opprinnelige oppføringen>> finnes i %s, på linje %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "opprinnelig oppføring"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[dokumentasjon]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Modul kildekode"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Kildekode for %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Oversikt: modulkildekode"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Alla moduler hvor kildekode finnes</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Obs"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Advarsel"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Fare"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Feil"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Hint"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Viktig"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Obs"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Se også"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tips"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Advarsel"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Nytt i version %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Endret i version %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Foreldet siden version %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "nøkkelord"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "uttrykk"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "innebygde funksjoner"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Innholdsfortegnelse"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Søk"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Gå"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Angi søkeord eller modul-, klasse- eller funksjonsnavn."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Vis kildekode"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Oversikt"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Index og tabeller"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Komplett Innholdsfortegnelse"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "liste over alle paragrafer og underparagrafer"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "søk i dette dokumentet"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Global Modulindex"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "snarvei til alle moduler"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "alla funksjoner, klasser, vilkår"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Index – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Hele innholdsfortegnelsen på en side"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Innholdsfortegnelse per bokstav"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "kan bli stor"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigering"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Søk blant %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Om disse dokumenter"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Sist oppdatert %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr "Lagd med <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Søk %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Forrige tittel"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "Forrige kapittel"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Neste emne"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "neste kapittel"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Vennligst aktiver JavaScript for å aktivere søk."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"her kan du søke blant disse dokumentene. Angi søkeord nedfor og klikk "
+"\"søk\".\n"
+" Søket må treffe på samtlige søkeord."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "søk"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Søkeresultat"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Hurtigsøk"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Denne siden"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Endringer i version %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatisk generert liste over endringer i versjon %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Endringer i biblioteket"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Endringer i C API"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Andre endringer"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Permalink til denne oversikten"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Permalink til denne definisjonen"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Skjul søkeresultat"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Utvid sidepanelet"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Skjul sidepanelet"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Innhold"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Utgivelse"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Fotnoter"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "fortsettelse fra forrige side"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Fortsetter på neste side"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[bilde]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/ne/LC_MESSAGES/sphinx.js b/sphinx/locale/ne/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..00df298
--- /dev/null
+++ b/sphinx/locale/ne/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "ne", "plural_expr": "(n != 1)", "messages": {"Next topic": "\u092a\u091b\u093f\u0932\u094d\u0932\u094b \u0935\u093f\u0937\u092f", "Index": "\u0905\u0928\u0941\u0938\u0941\u091a\u0940", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "\u0915\u092a\u093f\u0930\u093e\u0907\u091f ", "C API changes": "C API \u0915\u093e \u092a\u0930\u093f\u0935\u0930\u094d\u0924\u0928\u0939\u0930\u0941 [...]
\ No newline at end of file
diff --git a/sphinx/locale/ne/LC_MESSAGES/sphinx.mo b/sphinx/locale/ne/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..e74f34c
Binary files /dev/null and b/sphinx/locale/ne/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/ne/LC_MESSAGES/sphinx.po b/sphinx/locale/ne/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..eaf080f
--- /dev/null
+++ b/sphinx/locale/ne/LC_MESSAGES/sphinx.po
@@ -0,0 +1,834 @@
+# Nepali translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2011
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Nepali "
+"(http://www.transifex.com/projects/p/sphinx-1/language/ne/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "%s हेर्नुहोस्"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "%s पनि हेर्नुहोस् "
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%B %d, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "बिइल्टिन्स"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "मडुलको तह"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%b %d, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "सामान्य अनुसुची"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "अनुसुची"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "पछिल्लो"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "अघिल्लो"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr "(in"
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "सेक्सनको लेखक"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "मडुलको लेखक"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Codeको लेखक "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "लेखक"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parameters"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Returns"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Return type"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C कार्य)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C सदस्य)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C बृहत)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C किसिम)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C चल)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "फन्क्सन"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "सदस्य"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "बृहत"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "किसिम"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "चल"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Throws"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ कक्षा)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ किसिम)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ सदस्य)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++कार्य)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "कक्षा"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (built-in function)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s विधी)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (कक्षा)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (global variable or constant)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s attribute)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Arguments"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "data"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "attribute"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "चलहरू"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Raises"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (in मडुल %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (built-in चल)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (in मडुल %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (built-in कक्षा)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (कक्षा in %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s विधी)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s static विधी)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s static विधी)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s कक्षा विधी)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s कक्षा विधी)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s attribute)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (मडुल)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python Module Index"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "modules"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Deprecated"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "अपबाद"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "विधी"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "कक्षा विधी"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "static विधी"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "मडुल"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr "(deprecated)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (निर्देशिक)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (भूमिका)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "निर्देशिक"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "भूमिका"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "environment variable; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%scommand line option; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "शब्द-अर्थमा भएको"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "grammar token"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "सन्दर्व सामग्री"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "environment variable"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "कार्यक्रमका बिकल्प"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "अनुसुची"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "मडुल अनुसुची"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "पानामा खोज्नुहोस्"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr "Bases: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias of :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[स्रोत]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Todo"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<original entry>> यहाँ %s, line %d रहेको छ । "
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "मौलिक इन्ट्री"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[docs]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Module code"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Source code for %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "पुनरावलोकन: module code"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>All modules for which code is available</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "ध्यानाकर्षण"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "होसियार "
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "खतरा"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "गलत"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "सङ्केत"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "जरुरी"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "टिप्पणी"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "पनि हेर्नुहोस"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tip"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "साबधान"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "भर्सन %s मा नयाँ"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "भर्सन %s मा बदलिएको"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Deprecated since version %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "मुख्य शब्द"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "सन्चालक"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "object"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "भनाई"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "built-in फन्क्सन"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "विषयसूची"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "खोज्नुहोस् "
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "जानुहोस्"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "खोज्ने टर्मस् अथवा एक मडुल्, कक्षा अथवा फन्क्सनको नाम लेख्नुहोस "
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "स्रोत देखाउनुहोस् "
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "पुनरावलोकन "
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "इन्डीसीस्स र तलिका"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "पुरा विषयसूची"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "सबै सेक्सन र सवसेक्सन देखाउनुहोस्"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "यो डकुमेन्ट खोज्नुहोस्"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "ग्लोबल मडुल अनुसुची"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "सबै मोदुलेसमा छिटै जानुहोस्"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "सबै फन्क्सनस्, कक्षाहरू र टर्मस्"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Index – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "पुरा अनुसुची एकै पानामा"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "अक्षर अनुसार अनुसुचीका पाना"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "धेरै ठुलो हुन सक्छ"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "नेभिगेसन "
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "यी डकुमेन्टहरुको बारेमा"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "कपिराइट "
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "यो भन्दा अगाडी %(last_updated)s मा अपडेट भएको"
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "अघिल्लो विषय "
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "अघिल्लो खन्ड"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "पछिल्लो विषय"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "पछिल्लो खन्ड"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "खोज्ने कार्य आगाडी बढाउनको लागि जाभास्कृप्ट चलाईदिनुहोस "
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"यहाँबाट तपाईंले यी ड्कुमेन्टहरु खोज्नसक्नु हुन्छ । खोज्न शब्दहरु\n"
+"तलको बक्समा लेख्नुहोस र \"खोज्नुहोस्\"थिच्नुहोस । खोज्नुहोस्\n"
+"फन्क्सनले आफै सबै शब्दहरु खोज्छ । \n"
+"थोरै शब्दहरु भएको पानाहरु नतिजामा देखिन्न । "
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "खोज्नुहोस्"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "खोजेको नतिजा"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "छिट्टो खोज्नुहोस्"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "यो पाना"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "%(version)s — %(docstitle)s मा भएका फरकहरु "
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "भर्सन %(version)s मा भएका फरक हरु आफै जेनेरेट भए "
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "लाईब्रेरीका परिवर्तनहरु"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API का परिवर्तनहरु "
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "अरु परिवर्तनहरु "
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "यो शिर्षकको लागि पर्मालिन्क । "
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "यो अर्थको लागि पर्मालिन्क"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "खोजेको नतिजाहरु लुकाउनुहोस्"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "साइडबर ठुलो बनाउनुहोस्"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "साइडबर सानो बनाउनुहोस्"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "विषयसूची"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "रीलीज"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "फूट्नोट्स"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "अघिल्लो पानासँग जोडीएको"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "अर्को पानासँग जोडीएको"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[चित्र]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/nl/LC_MESSAGES/sphinx.js b/sphinx/locale/nl/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..fcd84b5
--- /dev/null
+++ b/sphinx/locale/nl/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "nl", "plural_expr": "(n != 1)", "messages": {"Next topic": "Volgend onderwerp", "Index": "Index", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Copyright", "C API changes": "Veranderingen in de C-API", "quick access to all modules": "sneltoegang naar alle modules", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global Module Index": "Globale Module-index", [...]
\ No newline at end of file
diff --git a/sphinx/locale/nl/LC_MESSAGES/sphinx.mo b/sphinx/locale/nl/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..8176b91
Binary files /dev/null and b/sphinx/locale/nl/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/nl/LC_MESSAGES/sphinx.po b/sphinx/locale/nl/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..96f385d
--- /dev/null
+++ b/sphinx/locale/nl/LC_MESSAGES/sphinx.po
@@ -0,0 +1,838 @@
+# Dutch translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2008
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Dutch "
+"(http://www.transifex.com/projects/p/sphinx-1/language/nl/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s documentatie"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "zie %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "zie %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d. %B %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Builtins"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Moduleniveau"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d.%b.%Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Algemene index"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "Index"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "volgende"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "vorige"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr ""
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Auteur van deze sectie: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Auteur van deze module: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Auteur: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parameters"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Returns"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Return type"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C-functie)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C member)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C-macro)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C type)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C-variabele)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "functie"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "member"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "macro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "type"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variabele"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ klasse)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ type)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ member)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ functie)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "klasse"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (geïntegreerde functie)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s methode)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (klasse)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (globale variabele of constante)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s attribuut)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "attribuut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Veroorzaakt"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (in module %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (geïntegreerde variabele)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (in module %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (geïntegreerde klasse)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (klasse in %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s methode)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s statische methode)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s statische methode)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s attribuut)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (module)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "modules"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Verouderd"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "exceptie"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statische methode"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "module"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (verouderd)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "omgevingsvariabele; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sopdrachtregel optie; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "omgevingsvariabele"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Index"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Module-index"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Zoekpagina"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Te doen"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(Het <<originele item>> is te vinden in %s, regel %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "originele item"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Let op"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Pas op"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Gevaar"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Fout"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Hint"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Belangrijk"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Notitie"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Zie ook"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tip"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Waarschuwing"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Nieuw in versie %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Veranderd in versie %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Verouderd sinds versie %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "trefwoord"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "object"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "statement"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "ingebouwde functie"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Inhoudsopgave"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Zoeken"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Ga"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Geef zoekterm of de naam van een module, klasse of functie."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Broncode weergeven"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Overzicht"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indices en tabellen:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Volledige inhoudsopgave"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "geeft alle secties en subsecties weer"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "zoeken in deze documentatie"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Globale Module-index"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "sneltoegang naar alle modules"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "alle functies, klasses en begrippen"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Index – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Volledige index op een pagina"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Index pagineerd per letter"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "kan heel groot zijn"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigatie"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Zoeken in %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Over deze documenten"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Laatste aanpassing op %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Aangemaakt met <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Zoeken %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Vorig onderwerp"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "Vorig hoofdstuk"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Volgend onderwerp"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "volgend hoofdstuk"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Activeer JavaSscript om de zoekfunctionaliteit in te schakelen."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Hier kan u de documenten doorzoeken. Geef enkele trefwoorden\n"
+" in het veld hieronder en klik \"zoeken\". Merk op dat de zoekfunctie"
+"\n"
+" steeds naar alle woorden zoekt. Pagina's die minder woorden bevatten"
+"\n"
+" zullen niet tussen de resultaten verschijnen."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "zoeken"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Zoekresultaten"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Snel zoeken"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Deze pagina"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Veranderingen in versie %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatisch gegenereerde lijst van veranderingen in versie %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Veranderingen in de bibliotheek"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Veranderingen in de C-API"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Andere veranderingen"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Permalink naar deze titel"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Permalink naar deze definitie"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Zoekresultaten verbergen"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Inhoud"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Release"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Voetnoten"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "Vervolgd van vorige pagina"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Vervolgd op volgende pagina"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[afbeelding]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/pl/LC_MESSAGES/sphinx.js b/sphinx/locale/pl/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..494394d
--- /dev/null
+++ b/sphinx/locale/pl/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "pl", "plural_expr": "(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)", "messages": {"Next topic": "Nast\u0119pny temat", "Index": "Indeks", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Witaj! To jest", "Copyright": "Copyright", "C API changes": "Zmiany w C API", "quick access to all modules": "szybki dost\u0119p do wszystkich modu\u0142\u00f3w", "© Copyright %(copyright)s [...]
\ No newline at end of file
diff --git a/sphinx/locale/pl/LC_MESSAGES/sphinx.mo b/sphinx/locale/pl/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..fd2ceb3
Binary files /dev/null and b/sphinx/locale/pl/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/pl/LC_MESSAGES/sphinx.po b/sphinx/locale/pl/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..a34dbeb
--- /dev/null
+++ b/sphinx/locale/pl/LC_MESSAGES/sphinx.po
@@ -0,0 +1,843 @@
+# Polish translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Tawez, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Tawez\n"
+"Language-Team: Polish "
+"(http://www.transifex.com/projects/p/sphinx-1/language/pl/)\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && "
+"(n%100<10 || n%100>=20) ? 1 : 2)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s - dokumentacja"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "zobacz %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "zobacz także %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Symbole"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%B %d %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Wbudowane"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Poziom modułu"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%b %d %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Indeks ogólny"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "indeks"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "dalej"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "wstecz"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (w "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autor rozdziału: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autor modułu: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Autor kodu: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametry"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Zwraca"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Typ zwracany"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (funkcja C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (pole C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (makro C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (typ C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (zmienna C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funkcja"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "pole"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "typ"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "zmienna"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Wyrzuca"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (klasa C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (typ C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (pole C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (funkcja C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "klasa"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (funkcja wbudowana)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metoda)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (klasa)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (zmienna lub stała globalna)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s atrybut)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumenty"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "dane"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atrybut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Zmienne"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Wyrzuca"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (w module %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (zmienna wbudowana)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (w module %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (klasa wbudowana)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (klasa w module %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metoda)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s metoda statyczna)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s metoda statyczna)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s metoda klasy)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s metoda klasy)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (atrybut %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (moduł)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Indeks modułów pythona"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduły"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Niezalecane"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "wyjątek"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metoda"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "metoda klasy"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statyczna metoda"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "moduł"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (niezalecane)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (dyrektywa)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (rola)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "dyrektywa"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "rola"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "zmienna środowiskowa; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sopcja linii komend; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "termin glosariusza"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "symbol gramatyki"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "etykieta odsyłacza"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "zmienna środowiskowa"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "opcja programu"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Indeks"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Indeks modułów"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Wyszukiwanie"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Klasy bazowe: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias klasy :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[wykres: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[wykres]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(w %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[źródło]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Todo"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<Oryginalny wpis>> znajduje się w pliku %s, w linii %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "oryginalny wpis"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[dokumenty]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Kod modułu"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Kod źródłowy modułu %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Przeglądanie: kod modułu"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Wszystkie moduły, dla których jest dostępny kod</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Uwaga"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Ostrzeżenie"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Niebezpieczeństwo"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Błąd"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Podpowiedź"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Ważne"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Informacja"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Zobacz także"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Wskazówka"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Ostrzeżenie"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Nowe w wersji %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Zmienione w wersji %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Niezalecane od wersji %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "słowo kluczowe"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "obiekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "instrukcja"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "funkcja wbudowana"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Spis treści"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Szukaj"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Szukaj"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Wprowadź szukany termin lub nazwę modułu, klasy lub funkcji."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Pokaż źródło"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Przegląd"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Witaj! To jest"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "dokumentacja do"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "ostatnio aktualizowana"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indeksy i tablice:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Kompletny spis treści"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "wszystkie rozdziały i podrozdziały"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "przeszukaj tę dokumentację"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Globalny indeks modułów"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "szybki dostęp do wszystkich modułów"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "wszystkie funkcje, klasy, terminy"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Indeks – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Cały indeks na jednej stronie"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Strony indeksu alfabetycznie"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "może być ogromny"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Nawigacja"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Szukaj pośród %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "O tych dokumentach"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Ostatnia modyfikacja %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Utworzone przy pomocy <a href=\"http://sphinx-doc.org/\">Sphinx</a>'a "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Przeszukaj %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Poprzedni temat"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "poprzedni rozdział"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Następny temat"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "następny rozdział"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Aby umożliwić wyszukiwanie, proszę włączyć JavaScript."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Stąd możesz przeszukać dokumentację. Wprowadź szukane\n"
+" słowa w poniższym okienku i kliknij \"Szukaj\". Zwróć uwagę, że\n"
+" funkcja szukająca będzie automatycznie szukała wszystkich słów. "
+"Strony\n"
+" nie zawierające wszystkich wpisanych słów nie znajdą się na wynikowej"
+" liście."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "szukaj"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Wyniki wyszukiwania"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"Twoje wyszukiwanie nie dało żadnych wyników. Upewnij się, że wszystkie "
+"słowa są wpisane prawidłowo i że wybrałeś dostateczną ilość kategorii."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Szybkie wyszukiwanie"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Ta strona"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Zmiany w wersji %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatycznie wygenerowana lista zmian w wersji %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Zmiany w bibliotekach"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Zmiany w C API"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Inne zmiany"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Stały odnośnik do tego nagłówka"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Stały odnośnik do tej definicji"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Ukryj wyniki wyszukiwania"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Wyszukiwanie"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Inicjalizacja wyszukiwania..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+"Wyszukiwanie zakończone. Ilość znalezionych stron pasujących do "
+"zapytania: %s."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", w "
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Rozwiń pasek boczny"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Zwiń pasek boczny"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Treść"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Wydanie"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Przypisy"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "kontynuacja poprzedniej strony"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Kontynuacja na następnej stronie"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[obraz: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[obraz]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Zwracana wartość: zawsze NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Zwracana wartość: nowa referencja."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Zwracana wartość: zapożyczona referencja."
+
diff --git a/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..12cb023
--- /dev/null
+++ b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "pt_BR", "plural_expr": "(n > 1)", "messages": {"Next topic": "Pr\u00f3ximo t\u00f3pico", "Index": "\u00cdndice", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Bem Vindo(a)! \u00c9 isso a\u00ed", "Copyright": "Copyright", "C API changes": "Altera\u00e7\u00f5es na API C", "quick access to all modules": "acesso r\u00e1pido para todos os m\u00f3dulos", "© Copyright %(copyright)s.": "© Copyr [...]
\ No newline at end of file
diff --git a/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..82f9fd0
Binary files /dev/null and b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..c2bd8df
--- /dev/null
+++ b/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po
@@ -0,0 +1,846 @@
+# Portuguese (Brazil) translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <roger.demetrescu at gmail.com>, 2008
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Portuguese (Brazil) "
+"(http://www.transifex.com/projects/p/sphinx-1/language/pt_BR/)\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s documentação"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "veja %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "veja também %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d/%m/%Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Internos"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Módulo"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d/%m/%Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Índice Geral"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "índice"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "próximo"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "anterior"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (em "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autor da seção: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autor do módulo: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Autor do código: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parâmetros"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Retorna"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Tipo de retorno"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (função C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (membro C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (tipo C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (variável C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "função"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "membro"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "macro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tipo"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variável"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Gera"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (classe C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (tipo C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (membro C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (função C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "classe"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (função interna)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (método %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (classe)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (variável global ou constante)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (atributo %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Parâmetros"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "dado"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atributo"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variáveis"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Levanta"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (no módulo %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (variável interna)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (no módulo %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (classe interna)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (classe em %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (método %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (método estático %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (método estático %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (método de classe %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (método de classe %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (atributo %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (módulo)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Índice de Módulos do Python"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "módulos"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Obsoleto"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "exceção"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "método"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "método de classe"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "método estático"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "módulo"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (obsoleto)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (diretiva)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (papel)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "diretiva"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "papel"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "váriavel de ambiente; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sopção de linha de comando; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "Termo de glossário"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "token de gramática"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "rótulo de referência"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "váriavel de ambiente"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "opção de programa"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Índice"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Índice do Módulo"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Página de Pesquisa"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Bases: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "apelido de :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[gráfico: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[gráfico]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(em %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[código fonte]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Por fazer"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(A <<entrada original>> está localizada em %s, linha %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "entrada original"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[documentos]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Código do módulo"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Código fonte de %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Visão geral: código do módulo"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Todos os módulos onde este código está disponível</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Atenção"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Cuidado"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Perigo"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Erro"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Dica"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Importante"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Nota"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Veja também"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Dica"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Aviso"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Novo na versão %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Alterado na versão %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Obsoleto desde a versão %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "palavra-chave"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operador"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objeto"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "comando"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "função interna"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Tabela de Conteúdo"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Pesquisar"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Ir"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Digite os termos da busca ou o nome de um módulo, classe ou função."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Exibir Fonte"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Visão geral"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Bem Vindo(a)! É isso aí"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "documentação para"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "última atualização"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Índices e tabelas:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Tabela de Conteúdo Completa"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "Lista todas seções e subseções"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "Pesquisar esta documentação"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Índice Global de Módulos"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "acesso rápido para todos os módulos"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "todas funções, classes, termos"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Índice – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Índice completo em uma página"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Paginas de índice por letra"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "pode ser enorme"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navegação"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Pesquisar dentro de %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Sobre estes documentos"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Última atualização em %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Criado usando <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Pesquisar em %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Tópico anterior"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "capítulo anterior"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Próximo tópico"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "próximo capítulo"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Por favor ative o JavaScript para habilitar a\n"
+"\"\n"
+"\" funcionalidade de pesquisa."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"A partir daqui você pode pesquisar estes documentos. Preencha suas \n"
+" palavras de pesquisa na caixa abaixo e clique em \"pesquisar\".\n"
+" Observe que a função de pesquisa\n"
+" irá procurar automaticamente por todas as palavras.\n"
+" Páginas contendo menos palavras não irão aparecer na lista de\n"
+" resultado."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "pesquisar"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Resultados da Pesquisa"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"Sua pesquisa não encontrou nenhum documento. Por favor, confirme que "
+"todas as palavras estão grafadas corretamente e que você selecionou "
+"categorias suficientes."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Pesquisa rápida"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Esta Página"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Alterações na Versão%(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Lista de alterações na versão %(version)s gerada automaticamente"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Alterações na biblioteca"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Alterações na API C"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Outras alterações"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Link permanente para este título"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Link permanente para esta definição"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Esconder Resultados da Pesquisa"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Pesquisando"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Preparando a pesquisa..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+"Pesquisa concluída, foram encontrada(s) %s página(s) que \"\n"
+"\"combinam com a consulta feita."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", em "
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Expandir painel lateral"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Recolher painel lateral"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Conteúdo"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Versão"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Notas de rodapé"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "continuação da página anterior"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Continuação na próxima página"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[imagem: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[imagem]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Valor Retorno: Sempre NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Valor Retorno: Nova referência."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Valor Retorn: Referência emprestada."
+
diff --git a/sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js b/sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..e1fcc9a
--- /dev/null
+++ b/sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "pt_PT", "plural_expr": "(n != 1)", "messages": {"Next topic": "Pr\u00f3ximo t\u00f3pico", "Index": "\u00cdndice", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Bem Vindo(a)! Esta \u00e9", "Copyright": "Copyright", "C API changes": "Altera\u00e7\u00f5es na API C", "quick access to all modules": "acesso r\u00e1pido a todos os m\u00f3dulos", "© Copyright %(copyright)s.": "© Copyright %(cop [...]
\ No newline at end of file
diff --git a/sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo b/sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..130d902
Binary files /dev/null and b/sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po b/sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..2ccff45
--- /dev/null
+++ b/sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po
@@ -0,0 +1,844 @@
+# Portuguese (Portugal) translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Pedro Algarvio <pedro at algarvio.me>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Pedro Algarvio <pedro at algarvio.me>\n"
+"Language-Team: Portuguese (Portugal) "
+"(http://www.transifex.com/projects/p/sphinx-1/language/pt_PT/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "Documentação %s %s"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "ver %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "ver também %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Símbolos"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Internos"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Módulos"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Índice Geral"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "índice"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "próximo"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "anterior"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (em "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autor da secção: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autor do módulo: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Autor do código: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parâmetros"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Retorno"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Tipo de retorno"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (função C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (membro C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (tipo C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (variável C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "função"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "membro"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "macro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tipo"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variável"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Gera"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (classe C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (tipo C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (membro C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (função C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "classe"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (função interna)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (método %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (classe)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (variável global ou constante)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (atributo %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Parâmetros"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "dados"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atributo"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variáveis"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Levanta"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (no módulo %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (variável interna)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (no módulo %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (classe interna)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (classe em %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (método %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (método estático %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (método estático %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (método de classe %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (método de classe %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (atributo %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (módulo)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Índice de Módulos do Python"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "módulos"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Obsoleto"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "excepção"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "método"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "método de classe"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "método estático"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "módulo"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (obsoleto)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (directiva)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (papel)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "directiva"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "papel"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "variável de ambiente; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sopção de linha de comando; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "Termo de glossário"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "token de gramática"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "rótulo de referência"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "variável de ambiente"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "opção de programa"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Índice"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Índice de Módulos"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Página de Pesquisa"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr "Bases: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "pseudónimo de :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[gráfico: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[gráfico]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(em %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[código fonte]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Por fazer"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(A <<entrada original>> está localizada em %s, linha %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "entrada original"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[documentos]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Código do módulo"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Código fonte de %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Visão geral: código do módulo"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Todos os módulos onde este código está disponível</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Atenção"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Cuidado"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Perigo"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Erro"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Dica"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Importante"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Nota"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Veja também"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Dica"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Aviso"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Novo na versão %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Alterado na versão %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Obsoleto desde a versão %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "palavra-chave"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operador"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objecto"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "comando"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "função interna"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Tabela de Conteúdos"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Pesquisar"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Ir"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Digite os termos da busca ou o nome de um módulo, classe ou função."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Exibir Fonte"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Visão geral"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Bem Vindo(a)! Esta é"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "a documentação de"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "última actualização"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Índices e tabelas:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Tabela de Conteúdos Completa"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "Listar todas as secções e subsecções"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "Pesquisar esta documentação"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Índice Global de Módulos"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "acesso rápido a todos os módulos"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "todas as funções, classes, termos"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Índice – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Índice completo numa página"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Paginas de índice por letra"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "pode ser enorme"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navegação"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Pesquisar dentro de %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Sobre estes documentos"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Última actualização em %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Criado utilizando <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Pesquisar %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Tópico anterior"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "capítulo anterior"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Próximo tópico"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "próximo capítulo"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Por favor ligue o JavaScript para habilitar a\n"
+"funcionalidade de pesquisa."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"A partir daqui pode pesquisar estes documentos. Preencha as\n"
+"palavras de pesquisa na caixa abaixo e clique em \"pesquisar\".\n"
+"Note que a função de pesquisa irá procurar automaticamente\n"
+"por todas as palavras. Páginas que contenham menos palavras\n"
+"não irão aparecer na lista de resultados."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "pesquisar"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Resultados da Pesquisa"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"A sua pesquisa não encontrou nenhum documento. Por favor, confirme que "
+"todas as palavras estão escritas corretamente e que selecionou categorias"
+" suficientes."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Pesquisa rápida"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Esta Página"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Alterações na Versão%(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Lista de alterações gerada automaticamente na versão %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Alterações na biblioteca"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Alterações na API C"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Outras alterações"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Link permanente para este título"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Link permanente para esta definição"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Esconder Resultados da Pesquisa"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "A Pesquisar"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "A preparar a pesquisa..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+"Pesquisa concluída, foram encontrada(s) %s página(s) que combinam com a "
+"consulta feita."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", em"
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Expandir painel lateral"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Recolher painel lateral"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Conteúdo"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Versão"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Notas de rodapé"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "continuação da página anterior"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Continuação na próxima página"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[imagem: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[imagem]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Valor de Retorno: Sempre NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Valor de Retorno: Nova referência."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Valor de Retorno: Referência emprestada."
+
diff --git a/sphinx/locale/ru/LC_MESSAGES/sphinx.js b/sphinx/locale/ru/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..ad6c48e
--- /dev/null
+++ b/sphinx/locale/ru/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "ru", "plural_expr": "(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)", "messages": {"Next topic": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437\u0434\u0435\u043b", "Index": "\u0410\u043b\u0444\u0430\u0432\u0438\u0442\u043d\u044b\u0439 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is" [...]
\ No newline at end of file
diff --git a/sphinx/locale/ru/LC_MESSAGES/sphinx.mo b/sphinx/locale/ru/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..59d3618
Binary files /dev/null and b/sphinx/locale/ru/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/ru/LC_MESSAGES/sphinx.po b/sphinx/locale/ru/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..775e8b7
--- /dev/null
+++ b/sphinx/locale/ru/LC_MESSAGES/sphinx.po
@@ -0,0 +1,841 @@
+# Russian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Dmitry Shachnev <mitya57 at gmail.com>, 2013
+# ferm32 <ferm32 at gmail.com>, 2014
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2014-02-24 21:25+0000\n"
+"Last-Translator: ferm32 <ferm32 at gmail.com>\n"
+"Language-Team: Russian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/ru/)\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "Документация %s %s"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "см. %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "также см. %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Символы"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Предложения об улучшениях Python; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Встроенные функции"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Модуль"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Алфавитный указатель"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "указатель"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "вперёд"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "назад"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (в "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Автор раздела: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Автор модуля: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Автор кода:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Автор: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Параметры"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Результат"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Тип результата"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (функция C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (поле C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (макроподстановка C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (тип C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (переменная C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "функция"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "поле"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "макрос"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "тип"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "переменная"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Бросает исключение"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (класс C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (тип C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (поле C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (функция C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "класс"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (встроенная функция)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (метод %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (класс)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (глобальная переменная или константа)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (атрибут %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Аргументы"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "данные"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "атрибут"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Переменные"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Исключение"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (в модуле %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (встроенная переменная)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (в модуле %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (встроенный класс)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (класс в %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (метод %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (статический метод %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (статический метод %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (метод класса %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (метод класса %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (атрибут %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (модуль)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Содержание модулей Python"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "модули"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Не рекомендуется"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "исключение"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "метод"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "метод класса"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "статический метод"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "модуль"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr "(использование не рекомендуется)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (директива)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (роль)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "директива"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "роль"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "переменная окружения; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "Опция командной строки %s; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "элемент словаря"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "токен грамматики"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "текст ссылки"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "переменная окружения"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "опция программы"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Алфавитный указатель"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Состав модуля"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Поиск"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Базовые классы: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "псевдоним класса :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[иллюстрация: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[иллюстрация]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(в %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[исходный код]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "План"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<Исходный элемент>> находится в %s, в строке %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "исходный элемент"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[документация]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Код модуля"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Исходный код %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Обзор: исходный код модуля"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Все модули, в которых есть код</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Внимание"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Осторожно"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Опасно"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Ошибка"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Подсказка"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Важно"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Примечание"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "См.также"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Совет"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Предупреждение"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Добавлено в версии %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Изменено в версии %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Не рекомендуется, начиная с версии %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "ключевое слово"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "оператор"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "объект"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "команда"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "базовая функция"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Оглавление"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Поиск"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Искать"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Введите слова для поиска или имя модуля, класса или функции."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Исходный текст"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Обзор"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Добро пожаловать! Это"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "документация"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "последнее изменение"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Таблицы и указатели:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Полное оглавление"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "список всех разделов и подразделов"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "поиск в документации"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Алфавитный указатель модулей"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "сводный список всех модулей"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "все функции, классы, переменные и константы"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Алфавитный указатель – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Полный алфавитный указатель на одной странице"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Указатели по буквам алфавита"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "может быть очень большим"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Навигация"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Поиск в документе «%(docstitle)s»"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Об этих документах"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Авторские права"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Авторские права</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Обновлено: %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Создано с помощью <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Поиск в документе «%(docstitle)s»"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Предыдущий раздел"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "предыдущая глава"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Следующий раздел"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "следующая глава"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Для работы поиска включите JavaScript в браузере."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Здесь можно делать поиск по всем разделам этой документации. Введите "
+"ключевые слова в текстовое поле и нажмите кнопку «искать». Внимание: "
+"будут найдены только те страницы, в которых есть все указанные слова."
+" Страницы, где есть только часть этих слов, отобраны не будут."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "искать"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Результаты поиска"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"По вашему поиску не найдено ни одного документа. Проверьте, что все слова"
+" написаны без ошибок, и что вы выбрали достаточно категорий."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Быстрый поиск"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Эта страница"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Изменения в версии %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Автоматически созданный список изменений в версии %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Изменения в библиотеке"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Изменения в API C"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Другие изменения"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Ссылка на этот заголовок"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Ссылка на это определение"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Снять выделение"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Идёт поиск"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Подготовка поиска…"
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Поиск завершён, найдено %s страниц, удовлетворяющих запросу."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", в"
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Развернуть боковую панель"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Свернуть боковую панель"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Содержание"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Выпуск"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Сноски"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "продолжение с предыдущей страницы"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Продолжается на следующей странице"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[рисунок: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[рисунок]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Возвращает: всегда NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Возвращает: новую ссылку."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Возвращает: заимствованную ссылку."
+
diff --git a/sphinx/locale/si/LC_MESSAGES/sphinx.js b/sphinx/locale/si/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..71c4d09
--- /dev/null
+++ b/sphinx/locale/si/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "si", "plural_expr": "(n != 1)", "messages": {"Next topic": "\u0d8a\u0dc5\u0d9f \u0db8\u0dcf\u0dad\u0dd8\u0d9a\u0dcf\u0dc0", "Index": "", "%(filename)s — %(docstitle)s": "", "Welcome! This is": "", "Copyright": "", "C API changes": "C API \u0dc0\u0dd9\u0db1\u0dc3\u0dca\u0d9a\u0db8\u0dca", "quick access to all modules": "", "© Copyright %(copyright)s.": "", "Global Module Index": "", "Your search did not match any documents. Please make [...]
\ No newline at end of file
diff --git a/sphinx/locale/si/LC_MESSAGES/sphinx.mo b/sphinx/locale/si/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..1b9a714
Binary files /dev/null and b/sphinx/locale/si/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/si/LC_MESSAGES/sphinx.po b/sphinx/locale/si/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..e2ea311
--- /dev/null
+++ b/sphinx/locale/si/LC_MESSAGES/sphinx.po
@@ -0,0 +1,830 @@
+# Sinhala translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# callkalpa <callkalpa at gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: callkalpa <callkalpa at gmail.com>\n"
+"Language-Team: Sinhala "
+"(http://www.transifex.com/projects/p/sphinx-1/language/si/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s ලේඛණය"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "%s බලන්න"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "%s ද බලන්න"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "සංකේත"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr ""
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%B %d, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr ""
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr ""
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%b %d, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr ""
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr ""
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "ඊළඟ"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "පෙර"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr ""
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr ""
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr ""
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "කේත ලේඛක:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "ලේඛක:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "පරාමිතීන්"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr ""
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr ""
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr ""
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr ""
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr ""
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr ""
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr ""
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "ක්රියාව"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "සාමාජික"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "මැක්රෝ"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "වර්ගය"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "විචල්යය"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr ""
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "දත්ත"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr ""
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "විචල්ය"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr ""
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr ""
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr ""
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr ""
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr ""
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr ""
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr ""
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr ""
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr ""
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr ""
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr ""
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr ""
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr ""
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr ""
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr ""
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr ""
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "සෙවුම් පිටුව"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[graph: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[graph]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(%s හි%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[source]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "කිරීමට තිබෙන"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[docs]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr ""
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr ""
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr ""
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "දෝෂය"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "හැඟවීම"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr ""
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "සටහන"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "මෙයද බලන්න"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr ""
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "අනතුරු ඇඟවීම"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "%s වෙළුමේ අලුත්"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "%s වෙළුමේ වෙනස් කල"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr ""
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr ""
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr ""
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "වස්තුව"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr ""
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "පටුන"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "සොයන්න"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "යන්න"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "මූලය පෙන්වන්න"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "අවසන්වරට යාවත්කාල කල"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "සම්පූර්ණ පටුන"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "විශාල විය හැක"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "ගමන් කිරීම"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "මෙම ලේඛණ ගැන"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "%(docstitle)s සොයන්න"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "පෙර මාතෘකාව"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "පෙර පරිච්ඡේදය"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "ඊළඟ මාතෘකාව"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "ඊළඟ පරිච්ඡේදය"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "සොයන්න"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "සෙවුම් ප්රතිඵල"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "ඉක්මන් සෙවුම"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "මෙම පිටුව"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "පුස්තකාල වෙනස්කම්"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API වෙනස්කම්"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "වෙනත් වෙනස්කම්"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "සොයමින්..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "සෙවුම සූදානම් කරමින්...."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "අන්තර්ගතය"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "නිකුත් කිරීම"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr ""
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr ""
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[image: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[image]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/sk/LC_MESSAGES/sphinx.js b/sphinx/locale/sk/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..a2d4436
--- /dev/null
+++ b/sphinx/locale/sk/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "sk", "plural_expr": "(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2", "messages": {"Next topic": "\u010eal\u0161ia t\u00e9ma", "Index": "Index", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Vitajte! Toto je", "Copyright": "Copyright", "C API changes": "Zmeny C API", "quick access to all modules": "r\u00fdchly pr\u00edstup ku v\u0161etk\u00fdm modulom", "© Copyright %(copyright)s.": "© Copyright % [...]
\ No newline at end of file
diff --git a/sphinx/locale/sk/LC_MESSAGES/sphinx.mo b/sphinx/locale/sk/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..3b023a9
Binary files /dev/null and b/sphinx/locale/sk/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/sk/LC_MESSAGES/sphinx.po b/sphinx/locale/sk/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..95be47b
--- /dev/null
+++ b/sphinx/locale/sk/LC_MESSAGES/sphinx.po
@@ -0,0 +1,842 @@
+# Slovak translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2008
+# Slavko <linux at slavino.sk>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Takayuki Shimizukawa <shimizukawa at gmail.com>\n"
+"Language-Team: Slovak "
+"(http://www.transifex.com/projects/p/sphinx-1/language/sk/)\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "Dokumentácia %s %s"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "pozri %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "pozri aj %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Symboly"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d. %B %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Zabudované funkcie"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Úroveň modulu"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d. %b %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Všeobecný index"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "index"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "predošlý"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "ďalší"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr "(v"
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Autor sekcie:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Autor modulu:"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Autor kódu:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Autor:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametre"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Vracia"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Návratový typ"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (funkcia C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (člen C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (makro C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (typ C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (premenná C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funkcia"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "člen"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "typ"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "premenná"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Vyvoláva"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (trieda C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (typ C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (člen C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (funkcia C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "trieda"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (zabudovaná funkcia)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (metóda %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (trieda)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (globálna premenná alebo konštanta)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (atribút %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argumenty"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "dáta"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atribút"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Premenné"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Vyzdvihuje"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (v module %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (zabudovaná premenná)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (v module %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (zabudovaná trieda)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (trieda v %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (metóda %s.%s)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (statická metóda %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (statická metóda %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (metóda triedy %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (metóda triedy %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (atribút %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Index modulov Python"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduly"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Zastarané"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "výnimka"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metóda"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "metóda triedy"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statická metóda"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (zastarané)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktíva)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (rola)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktíva"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "rola"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "premenná prostredia; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%s voľba príkazového riadka; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "termín glosára"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "jazykový token"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "menovka odkazu"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "premenná prostredia"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "voľba programu"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Index"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Index modulov"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Stránka hľadania"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Základné: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias pre :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[graf: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[graf]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(v %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[zdroj]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Todo"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<pôvodná položka>> je umiestnená v %s, riadok %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "pôvodná položka"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[dokumenty]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Kód modulu"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Zdrojový kód %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Prehľad: kód modulu"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Všetky moduly, pre ktoré je dostupný kód</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Výstraha"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Pozor"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Nebezpečné"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Chyba"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Rada"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Dôležité"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Poznámka"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Pozri aj"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tip"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Varovanie"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Nové vo verzii %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Zmenené vo verzii %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Zastarané od verzie %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "kľúč. slovo"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operátor"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "príkaz"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "zabudovaná funkcia"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Obsah"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Hľadať"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "OK"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Zadajte hľadané výrazy alebo modul, triedu, či meno funkcie."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Zobraziť zdroj"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Prehľad"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Vitajte! Toto je"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "dokumentácia"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "posledná aktualizácia"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Indexy a tabuľky"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Celkový obsah"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "zoznam sekcií a podsekcií"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "hľadať v tejto dokumentácii"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Celkový index modulov"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "rýchly prístup ku všetkým modulom"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "všetky funkcie, triedy, termíny"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Index – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Celý index na jednej strane"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Indexové stránky po písmenách"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "môže byť rozsiahle"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigácia"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Hľadať v %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "O týchto dokumentoch"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Naposledy aktualizované %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Vytvorené pomocou <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Hľadať v %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Predošlá téma"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "predošlá kapitola"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Ďalšia téma"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "ďalšia kapitola"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Prosím, na zapnutie funkcie hľadania,aktivujte \n"
+" JavaScript ."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Tu môžete hľadať v tejto dokumentácii. Zadajte hľadané slová\n"
+" do políčka nižšie a kliknite na \"hľadať\". Pamätajte, že funkcia\n"
+" hľadania bude automaticky hľadať všetky slová. Strany, ktoré\n"
+" obsahujú len niektoré zo slov, nebudú v zozname výsledkov."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "hľadať"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Výsledky hľadania"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"Vášmu hľadaniu nezodpovedá žiadny dokument. Prosím, skontrolujte, že "
+"všetky zadané slová sú správne napísané a že ste zvolili vhodné "
+"kategórie."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Rýchle hľadanie"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Táto stránka"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Zmeny vo verzii %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automaticky generovaný zoznam zmien vo verzii %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Zmeny knižnice"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Zmeny C API"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Ostatné zmeny"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Trvalý odkaz na tento nadpis"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Trvalý odkaz na túto definíciu"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Skryť výsledky hľadania"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Hľadanie"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Príprava hľadania..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Hľadanie dokončené, nájdené %s strán(y), ktoré vyhovujú hľadanému výrazu."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", v "
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Rozbaliť bočný panel"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Zbaliť bočný panel"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Obsah"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Vydanie"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Poznámky pod čiarou"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "pokračovanie z predošlej strany"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Pokračovanie na ďalšej strane"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[obrázok: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[obrázok]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Návratová hodnota: vždy NULL."
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Návratová hodnota: Nový odkaz."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Návratová hodnota: Požičaný odkaz."
+
diff --git a/sphinx/locale/sl/LC_MESSAGES/sphinx.js b/sphinx/locale/sl/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..3ec35d5
--- /dev/null
+++ b/sphinx/locale/sl/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "sl", "plural_expr": "(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)", "messages": {"Next topic": "Naslednja tema", "Index": "Abecedni seznam", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Vse pravice pridr\u017eane", "C API changes": "C API spremembe", "quick access to all modules": "hiter dostop do vseh modulov", "© Copyright %(copyright)s.": "© Vse prav [...]
\ No newline at end of file
diff --git a/sphinx/locale/sl/LC_MESSAGES/sphinx.mo b/sphinx/locale/sl/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..6ef7ced
Binary files /dev/null and b/sphinx/locale/sl/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/sl/LC_MESSAGES/sphinx.po b/sphinx/locale/sl/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..578baad
--- /dev/null
+++ b/sphinx/locale/sl/LC_MESSAGES/sphinx.po
@@ -0,0 +1,838 @@
+# Slovenian translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Slovenian "
+"(http://www.transifex.com/projects/p/sphinx-1/language/sl/)\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 "
+"|| n%100==4 ? 2 : 3)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Vgrajeni deli"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Nivo modula"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Splošni abecedni seznam"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "abecedni seznam"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "naprej"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "nazaj"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (v "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Avtor sekcije: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Avtor modula: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Avtor: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametri"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Vrne"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Vrne tip"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C funkcija)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C član)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C makro)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C tip)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C spremenljivka)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funkcija"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "član"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr ""
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tip"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr ""
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ razred)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ tip)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ član)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ funkcija)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "razred"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (vgrajene funkcije)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metoda)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (razred)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s atribut)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "atribut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Sproži izjemo"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (v modulu %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (vgrajene spremenljivke)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (v modulu %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (vgrajen razred)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (razred v %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metoda)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s statična metoda)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s statična metoda)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s atribut)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "Moduli"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Zastarelo"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "izjema"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statična metoda"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (zastarelo)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "okoljska spremenljivka; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%scommand line parameter; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "okoljska spremenljivka"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Abecedni seznam"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Seznam modulov"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Iskalnik"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Baza: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "vzdevek za :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Todo"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Pozor"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Previdno"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Nevarno"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Napaka"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Nasvet"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Pomembno"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Opomba"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Poglej Tudi"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Nasvet"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Opozorilo"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Novo v verziji %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Spremenjeno v verziji %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Zastarelo od verzije %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "ključna beseda"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "izjava"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "vgrajene funkcije"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Seznam Vsebine"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Išči"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Potrdi"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Vnesi ime modula, razreda ali funkcije."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Prikaži izvorno kodo"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Pregled"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Kazalo in seznami:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Popoln Seznam Vsebine"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "prikazi vse sekcije in podsekcije"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "išči po dokumentaciji"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Splošen seznam modulov"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "hiter dostop do vseh modulov"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "vse funkcije, razredi, izrazi"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Seznam – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Poln indeks na eni strani"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Indeksiraj strani po črki"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "lahko je veliko"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigacija"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Išči med %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "O dokumentih"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Vse pravice pridržane"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Vse pravice pridržane</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Vse pravice pridržane %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Zadnjič posodobljeno %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Narejeno s <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Išči %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Prejšnja tema"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "prejšnje poglavje"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Naslednja tema"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "naslednje poglavje"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Za pravilno delovanje Iskanja morete vklopiti\n"
+" JavaScript."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Tukaj lahko iščete dokumente. Vnesite iskalni\n"
+" niz v polje spodaj in pritisnite \"išči\". Sproženo iskanje\n"
+" bo iskalo po vseh besedah v iskalnem nizu. Strani, ki ne\n"
+" vsebujejo vseh besed ne bodo prikazane na seznamu rezultatov."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "išči"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Rezultati Iskanja"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Hitro iskanje"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Trenutna stran"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Spremembe v Verziji %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Avtomatsko generiran seznam sprememb v verziji %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Spremembe knjižnice"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API spremembe"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Ostale spremembe"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Povezava na naslov"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Povezava na to definicijo"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Skrij resultate iskanja"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Izdaja"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Opombe"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "nadaljevanje iz prejšnje strani"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Nadaljevanje na naslednji strani"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[slika]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/sphinx.pot b/sphinx/locale/sphinx.pot
new file mode 100644
index 0000000..e19aea7
--- /dev/null
+++ b/sphinx/locale/sphinx.pot
@@ -0,0 +1,819 @@
+# Translations template for Sphinx.
+# Copyright (C) 2014 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2014.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx 1.2.2+/6728a8b81a26+\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr ""
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr ""
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr ""
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr ""
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr ""
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr ""
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr ""
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr ""
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr ""
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr ""
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr ""
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr ""
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr ""
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr ""
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr ""
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr ""
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr ""
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr ""
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr ""
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr ""
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr ""
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr ""
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr ""
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr ""
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr ""
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr ""
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr ""
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr ""
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr ""
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr ""
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr ""
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr ""
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr ""
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr ""
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr ""
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr ""
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr ""
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr ""
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr ""
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr ""
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr ""
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr ""
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr ""
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr ""
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr ""
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr ""
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr ""
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr ""
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr ""
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr ""
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr ""
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr ""
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr ""
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr ""
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr ""
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr ""
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr ""
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr ""
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr ""
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr ""
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr ""
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr ""
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr ""
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr ""
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr ""
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr ""
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr ""
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr ""
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr ""
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr ""
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr ""
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr ""
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr ""
+
diff --git a/sphinx/locale/sv/LC_MESSAGES/sphinx.js b/sphinx/locale/sv/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..460f080
--- /dev/null
+++ b/sphinx/locale/sv/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "sv", "plural_expr": "(n != 1)", "messages": {"Next topic": "N\u00e4sta titel", "Index": "Index", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "Copyright", "C API changes": "F\u00f6r\u00e4ndringar i C-API", "quick access to all modules": "genv\u00e4g till alla moduler", "© Copyright %(copyright)s.": "© Copyright %(copyright)s.", "Global Module Index": "Global Modulindex" [...]
\ No newline at end of file
diff --git a/sphinx/locale/sv/LC_MESSAGES/sphinx.mo b/sphinx/locale/sv/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..151aef9
Binary files /dev/null and b/sphinx/locale/sv/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/sv/LC_MESSAGES/sphinx.po b/sphinx/locale/sv/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..95a5ebe
--- /dev/null
+++ b/sphinx/locale/sv/LC_MESSAGES/sphinx.po
@@ -0,0 +1,834 @@
+# Swedish translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Swedish "
+"(http://www.transifex.com/projects/p/sphinx-1/language/sv/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "se %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "se även %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%B %d, %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Inbyggda"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Modulnivå"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%b %d, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Huvudindex"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "index"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "nästa"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "föregående"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr "(i "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Sektionsförfattare"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Modulförfattare"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Källkodsförfattare"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Upphovsman:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametrar"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Returnerar"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Returtyp"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C-funktion)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C-medlem)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C-makro)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C-typ)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C-variabel)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "funktion"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "medlem"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "typ"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "variabel"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Kastar"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++-klass)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++-typ)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++-medlem)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++-funktion)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "klass"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (inbyggd funktion)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metod)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (klass)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (global variabel eller konstant)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s attribut)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argument"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "data"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "attribut"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Variabler"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Väcker"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (i modul %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (inbyggd variabel)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (i modul %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (inbyggd klass)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (klass i %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metod)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s statisk metod)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s statisk metod)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s klassmetod)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s klassmetod)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s attribut)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modul)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python Modulindex"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "moduler"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Ersatt"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "undantag"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metod"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "klassmetod"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statisk metod"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modul"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (direktiv)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (roll)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "direktiv"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "roll"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "miljövariabel; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%skommandorad växel; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "ordlista"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "grammatisk token"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "referensetikett"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "miljövariabel"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "programväxel"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Index"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Modulindex"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Söksida"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Baserad: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "alias för :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[source]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Att göra"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<Ursprunget>> finns i %s, på rad %d.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "ursprungsvärde"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[docs]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Modulkällkod"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>Källkod för %s</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Översikt: modulkällkod"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Alla moduler där källkod finns</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Uppmärksamma"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Varning"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Risk"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Fel"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Råd"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Viktigt"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Observera"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Se även"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tips"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Varning"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Nyheter i version %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Förändrat i version %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Ersatt sedan version %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "nyckelord"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "operator"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "objekt"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "uttryck"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "inbyggda funktioner"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Innehållsförteckning"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Sök"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Gå"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Ange sökord eller modul-, klass- eller funktionsnamn."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Visa källfil"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Översikt"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Index och tabeller"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Komplett Innehållsförteckning"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "lista över alla paragrafer och underparagrafer"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "sök i det här dokumentet"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Global Modulindex"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "genväg till alla moduler"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "alla funktioner, klasser, villkor"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Index – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Hela innehållsförteckningen på en sida"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Innehållsförteckning per inledande bokstav"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "kan bli stort"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Navigation"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Sök bland %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Om dessa dokument"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Senast uppdaterad %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Skapad med <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Sök %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Föregående titel"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "Föregående kapitel"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Nästa titel"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "Nästa kapitel"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "Var god aktivera JavaScript för sökfunktionalitet."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Här kan du söka bland dessa dokument. Ange sökord nedan och klicka "
+"\"sök\".\n"
+" Sökningen måste träffa på samtliga angivna sökord."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "sök"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Sökresultat"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Snabbsök"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Denna Sida"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Förändringar i Version %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Automatiskt genererad lista över förändringar i version %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Förändringar i bibliotek"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Förändringar i C-API"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Övriga förändringar"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Permalink till denna rubrik"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Permalink till denna definition"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Dölj Sökresultat"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Expandera sidolist"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Dölj sidolist"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "Innehåll"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Utgåva"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Fotnoter"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "fortsättning från föregående sida"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Fortsätter på nästa sida"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[image]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/tr/LC_MESSAGES/sphinx.js b/sphinx/locale/tr/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..e421a77
--- /dev/null
+++ b/sphinx/locale/tr/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "tr", "plural_expr": "(n > 1)", "messages": {"Next topic": "Sonraki konu", "Index": "Dizin", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "Ho\u015fgeldiniz! Kar\u015f\u0131n\u0131zda", "Copyright": "Copyright", "C API changes": "C API'sindeki de\u011fi\u015fiklikler", "quick access to all modules": "b\u00fct\u00fcn mod\u00fcllere h\u0131zl\u0131 eri\u015fim", "© Copyright %(copyright)s.": "&c [...]
\ No newline at end of file
diff --git a/sphinx/locale/tr/LC_MESSAGES/sphinx.mo b/sphinx/locale/tr/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..b9739e9
Binary files /dev/null and b/sphinx/locale/tr/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/tr/LC_MESSAGES/sphinx.po b/sphinx/locale/tr/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..173f20d
--- /dev/null
+++ b/sphinx/locale/tr/LC_MESSAGES/sphinx.po
@@ -0,0 +1,841 @@
+# Turkish translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Fırat Özgül <ozgulfirat at gmail.com>, 2013
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2011
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Fırat Özgül <ozgulfirat at gmail.com>\n"
+"Language-Team: Turkish "
+"(http://www.transifex.com/projects/p/sphinx-1/language/tr/)\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s belgelendirme çalışması"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "bkz. %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "ayrıca bkz. %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Simgeler"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python'u İyileştirme Önerileri; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B %Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Gömülüler"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Modül düzeyi"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d %b %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Genel Dizin"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "dizin"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "sonraki"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "önceki"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (şunun içinde: "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Bölümü yazan: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Modülü yazan: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Kodu yazan: "
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Yazan: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Parametreler"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Dönüş değeri:"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Dönüş tipi"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C fonksiyonu)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C öğesi)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C makrosu)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C tipi)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C değişkeni)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "fonksiyonu"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "öğesi"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "makrosu"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "tipi"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "değişkeni"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Şunu verir: "
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ sınıfı)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ tipi)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ öğesi)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ fonksiyonu)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "sınıfı"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (gömülü fonksiyon)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metodu)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (sınıfı)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (global değişken veya sabit)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s niteliği)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Argümanlar"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "verisi"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "niteliği"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Değişkenler"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Şunu üretir:"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (%s modülü içinde)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (gömülü değişken)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (%s modülü içinde)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (gömülü sınıf)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (%s içinde bir sınıf)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metodu)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s statik metodu)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s statik metodu)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s sınıf metodu)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s sınıf metodu)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s niteliği)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modül)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python Modül Dizini"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "modüller"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Önerilmiyor"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "istisnası"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "metodu"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "sınıf metodu"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "statik metodu"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "modülü"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (önerilmiyor)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (yönerge)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (rol)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "yönergesi"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "rolü"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "çevre değişkeni; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%skomut satırı seçeneği; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "sözlük terimi"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "dilbilgisi girdisi"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "referans etiketi"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "çevre değişkeni"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "program seçeneği"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Dizin"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Modül Dizini"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Arama Sayfası"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Taban: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "şunun takma adı: :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[çizim: %s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[çizim]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(%s v%s içinde)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[kaynak]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Yapılacaklar"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<özgün girdi>> %s içinde ve %d satırında bulunuyor.)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "özgün girdi"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[belgeler]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "Modül kodu"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>%s öğesinin kaynak kodu</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "Genel bakış: modül kodu"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>Kodları mevcut bütün modüller</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Dikkat"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Uyarı"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Tehlike"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Hata"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "İpucu"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Önemli"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Not"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Ayrıca bkz."
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Tüyo"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Uyarı"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "%s sürümüyle geldi"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "%s sürümünde değişti"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "%s sürümünden beri önerilmiyor"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "anahtar sözcük"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "işleç"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "nesne"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "deyim"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "gömülü fonksiyon"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "İçindekiler Tablosu"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Ara"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Git"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Aranacak terimleri veya modül, sınıf ya da fonksiyon adını yazınız"
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Kaynağı Göster"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Genel Bakış"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Hoşgeldiniz! Karşınızda"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "belgelendirme konusu: "
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "son güncelleme"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Dizinler ve tablolar"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Ayrıntılı İçindekiler Tablosu"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "bütün bölümler ve alt bölümler listelenir"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "Bu belgelerde ara"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Global Modül Dizini"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "bütün modüllere hızlı erişim"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "bütün fonksiyonlar, sınıflar, terimler"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Dizin – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Bütün dizin tek sayfada"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Harfe göre dizin sayfaları"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "çok büyük olabilir"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Gezinti"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "%(docstitle)s içinde ara"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Bu belgeler hakkında"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Son güncelleme: %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"<a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s ile "
+"oluşturulmuştur."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Ara: %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Önceki konu"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "önceki bölüm"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Sonraki konu"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "sonraki bölüm"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Arama işlevini kullanabilmek için lütfen JavaScript'i\n"
+" etkinleştirin."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Burada belgeler içinde arama yapabilirsiniz. Aradığınız kelimeyi \n"
+"aşağıdaki kutuya yazıp \"ara\" düğmesine basınız. Arama işlevi \n"
+"otomatik olarak bütün kelimeleri arayacaktır. Eksik kelime içeren \n"
+"sayfalar sonuç listesinde görünmez."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "ara"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Arama Sonuçları"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"Arama sonucunda herhangi bir belge bulunamadı. Bütün kelimeleri doğru "
+"yazdığınızdan ve gerekli bütün kategorileri seçtiğinizden emin olun."
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Hızlı Arama"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Bu Sayfa"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Sürüm %(version)s — %(docstitle)s içindeki Değişiklikler"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "%(version)s sürümündeki değişikliklerin otomatik olarak üretilmiş listesi"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Kütüphane değişiklikleri"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API'sindeki değişiklikler"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Diğer değişiklikler"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Bu başlığın kalıcı bağlantısı"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Bu tanımın kalıcı bağlantısı"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Arama Sonuçlarını Gizle"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "Aranıyor"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "Aramaya hazırlanıyor..."
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Arama tamamlandı. Sorguyu içeren %s sayfa bulundu."
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ", şunun içinde:"
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "Yan çubuğu genişlet"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "Yan çubuğu daralt"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "İçindekiler"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Sürüm"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "Dipnotları"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "önceki sayfadan devam"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "Devamı sonraki sayfada"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[resim: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[resim]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "Dönüş değeri: Her zaman NULL"
+
+#~ msgid "Return value: New reference."
+#~ msgstr "Dönüş değeri: Yeni referans."
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "Dönüş değeri: Ödünç referans"
+
diff --git a/sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js b/sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..7800cab
--- /dev/null
+++ b/sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "uk_UA", "plural_expr": "(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)", "messages": {"Next topic": "\u041d\u0430\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u0435\u043c\u0430", "Index": "\u0406\u043d\u0434\u0435\u043a\u0441", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "", "Copyright": "\u0410\u0432\u0442\u043e\u0440\u0441\u044c\u043a\u0456 \u043f\u0440\u0430\ [...]
\ No newline at end of file
diff --git a/sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo b/sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..2581ecf
Binary files /dev/null and b/sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po b/sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..1445b78
--- /dev/null
+++ b/sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po
@@ -0,0 +1,840 @@
+# Ukrainian (Ukraine) translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Petro Sasnyk <petro at sasnyk.name>, 2009
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Ukrainian (Ukraine) "
+"(http://www.transifex.com/projects/p/sphinx-1/language/uk_UA/)\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python Enhancement Proposals; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr ""
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Вбудовані елементи"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Рівень модуля"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%b %d, %Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Загальний індекс"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "індекс"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "наступний"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "попередній"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr " (в "
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Автор секції: "
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Автор модуля: "
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Автор: "
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Параметри"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Повертає"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Тип повернення"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (С функція)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C член)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C макрос)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C тип)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C змінна)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "функція"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "член"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "макрос"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "тип"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr ""
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ клас)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ тип)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ член)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ функція)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "клас"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (вбудована функція)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s метод)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (клас)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s атрибут)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "атрибут"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Викликає"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (в модулі %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (вбудована змінна)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (в модулі %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (вбудований клас)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (клас в %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s метод)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s статичний метод)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s статичний метод)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s атрибут)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (модуль)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "модулі"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Застарілий"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "виняткова ситуація"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "статичний метод"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "модуль"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (застарілий)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "змінна оточення; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sопція командного рядка; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "змінна оточення"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "Індекс"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "Індекс модулів"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "Сторінка пошуку"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " Базовий: %s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr "синонім :class:`%s`"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "Доробити"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Увага"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Застереження"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Небезпека"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Помилка"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Підказка"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Важливо"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Примітка"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Дивись також"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Порада"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Попередження"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Нове в версії %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Змінено в версії %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Застаріло починаючи з версії %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "ключове слово"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "оператор"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "об'єкт"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "вираз"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "вбудована функція"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Зміст"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Пошук"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Вперед"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Введіть пошуковий термін, модуль, клас чи назву функції."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Відобразити вихідний текст"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Огляд"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Індекси та таблиці:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Повний Зміст"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "перелічити всі секції та підсекції"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "шукати цю документацію"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Загальний індекс модулів"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "швидкий доступ до всіх модулів"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "всі функції, класи, терміни"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Індекс – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Повний індекс на одній сторінці"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Індексні сторінки по символам"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "може бути величезним"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Навігація"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Шукати в %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Про ці документи"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Авторські права"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Copyright %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Востаннє оновлено %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Створено з використанням <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Пошук %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Попередній розділ"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "Попередній розділ"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Наступна тема"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "наступний розділ"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Будь-ласка вімкніть підтримку JavaScript, щоб ввікнути\n"
+"\"\n"
+"\" пошук."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+"Звідси ви можете шукати ці документи. Введіть ваші пошукові\n"
+" слова в поле нижче та натисніть \"пошук\". Зауважте що функція\n"
+" пошуку автоматично шукатиме за всіма словами. Сторінки\n"
+" що містять менше слів не з'являться в результуючому списку."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "пошук"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "Результати пошуку"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "Швидкий пошук"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "Ця сторінка"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "Зміни в Версії %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Автоматичного згенерований список змін в версії %(version)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Зміни в бібліотеці"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "зміни C API"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Інші зміни"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "Постійне посилання на цей заголовок"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "Постійне посилання на це визначення"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "Приховати співпадіння пошуку"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "Реліз"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr ""
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr ""
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr ""
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/vi/LC_MESSAGES/sphinx.js b/sphinx/locale/vi/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..588d99e
--- /dev/null
+++ b/sphinx/locale/vi/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "vi", "plural_expr": "0", "messages": {"Next topic": "Ch\u1ee7 \u0111\u1ec1 ti\u1ebfp", "Index": "", "%(filename)s — %(docstitle)s": "", "Welcome! This is": "Ch\u00e0o m\u1eebng! \u0110\u00e2y l\u00e0", "Copyright": "B\u1ea3n quy\u1ec1n", "C API changes": "", "quick access to all modules": "truy c\u1eadp nhanh t\u1ea5t c\u1ea3 c\u00e1c m\u00f4-\u0111un", "© Copyright %(copyright)s.": "© B\u1ea3n quy\u1ec1n thu\u1ed9c %(copyright)s. [...]
\ No newline at end of file
diff --git a/sphinx/locale/vi/LC_MESSAGES/sphinx.mo b/sphinx/locale/vi/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..9699923
Binary files /dev/null and b/sphinx/locale/vi/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/vi/LC_MESSAGES/sphinx.po b/sphinx/locale/vi/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..de1ce16
--- /dev/null
+++ b/sphinx/locale/vi/LC_MESSAGES/sphinx.po
@@ -0,0 +1,834 @@
+# Vietnamese translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Hoat Le Van <hoatlevan at gmail.com>, 2014
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2014-01-15 08:16+0000\n"
+"Last-Translator: Hoat Le Van <hoatlevan at gmail.com>\n"
+"Language-Team: Vietnamese "
+"(http://www.transifex.com/projects/p/sphinx-1/language/vi/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "Tài liệu %s %s"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "xem %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "nên xem %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "Biểu tượng"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Các đề nghị nâng cao Python; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d/%m/%Y"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "Dựng sẵn"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "Mức mô-đun"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d/%m/%Y"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "Chỉ mục chung"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "chỉ mục"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "xem tiếp"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "xem lại"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr "(trong"
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Tác giả mục:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "Tác giả mô-đun:"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "Tác giả mã lệnh:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "Tác giả:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "Tham số"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "Trả về"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "Kiểu trả về"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (hàm C)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (thuộc tính C)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro C)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (kiểu C)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (biến C)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "hàm"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "thuộc tính"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "macro"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "kiểu"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "biến"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "Ném"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (lớp C++)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (kiểu C++)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (thuộc tính C++)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (hàm C++)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "lớp"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (hàm dựng sẵn)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (phương thức %s)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (lớp)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (biến toàn cục hoặc hằng số)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (thuộc tính %s)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "Đối số"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "dữ liệu"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "thuộc tính"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "Các biến"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "Đưa ra"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (trong mô-đun %s)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (biến dựng sẵn)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (trong mô-đun %s)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (lớp dựng sẵn)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (lớp trong %s)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (phương thức %s.%s) "
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (phương thức tĩnh %s.%s)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (phương thức tĩnh %s)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (phương thức lớp %s.%s)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (phương thức lớp %s)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (thuộc tính %s.%s)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (mô-đun)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Chỉ Mục Mô-đun Python"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "các mô-đun"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "Sắp loại bỏ"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "ngoại lệ"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "phương thức"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "phương thức lớp"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "phương thức tĩnh"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "mô-đun"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr "(sắp loại bỏ)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (chỉ thị)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (vai trò)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "chỉ thị"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "vai trò"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "các biến môi trường; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "tuỳ chọn dòng lệnh%s; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "chú giải thuật ngữ"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr ""
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr ""
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr ""
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr ""
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "Chú ý"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "Cảnh báo"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "Nguy hiểm"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "Lỗi"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "Gợi ý"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "Quan trọng"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "Ghi chú"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "Xem thêm"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "Mẹo"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "Cảnh báo"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "Mới từ phiên bản %s"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "Thay đổi trong phiên bản %s"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Sắp loại bỏ từ phiên bản %s"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "từ khoá"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "toán tử"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "đối tượng"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "câu lệnh"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "hàm dựng sẵn"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "Mục Lục"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "Tìm Kiếm"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "Thực hiện"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "Nhập thuật ngữ, tên một mô-đun, lớp hay hàm cần tìm."
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "Hiển thị mã nguồn"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "Tổng quan"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "Chào mừng! Đây là"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "tài liệu cho"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "cập nhật mới nhất"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "Các chỉ mục và bảng biểu:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "Mục Lục Đầy Đủ"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "liệt kê tất cả các mục và mục con"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "tìm kiếm trong tài liệu này"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "Chỉ Mục Mô-đun Toàn Cục"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "truy cập nhanh tất cả các mô-đun"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "tất cả các hàm, lớp, thuật ngữ"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "Chỉ mục – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "Toàn bộ chỉ mục trên một trang"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "Các trang chỉ mục theo chữ cái"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "có thể rất nhiều"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "Điều hướng"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Tìm kiếm trong %(docstitle)s"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "Về các tài liệu này"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "Bản quyền"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">Bản quyền thuộc</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© Bản quyền thuộc %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Cập nhật mới nhất vào %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Được tạo nhờ <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Tìm %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "Chủ đề trước"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "chương trước "
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "Chủ đề tiếp"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "chương tiếp"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+"Hãy bật JavaScript để dùng tính năng\n"
+"tìm kiếm."
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr ""
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr ""
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr ""
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr ""
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr ""
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr ""
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr ""
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr ""
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/locale/zh_CN/LC_MESSAGES/sphinx.js b/sphinx/locale/zh_CN/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..d68c834
--- /dev/null
+++ b/sphinx/locale/zh_CN/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "zh_Hans_CN", "plural_expr": "0", "messages": {"Next topic": "\u4e0b\u4e00\u4e2a\u4e3b\u9898", "Index": "\u7d22\u5f15", "%(filename)s — %(docstitle)s": "%(filename)s — %(docstitle)s", "Welcome! This is": "\u6b22\u8fce\uff01\u8fd9\u662f", "Copyright": "\u7248\u6743\u6240\u6709", "C API changes": "C API \u66f4\u6539", "quick access to all modules": "\u5feb\u901f\u67e5\u770b\u6240\u6709\u7684\u6a21\u5757", "© Copyright %(copyright)s. [...]
\ No newline at end of file
diff --git a/sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo b/sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..04857b3
Binary files /dev/null and b/sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po b/sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..33ca4d0
--- /dev/null
+++ b/sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po
@@ -0,0 +1,833 @@
+# Chinese (Simplified, China) translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# 刘振涛 <lenville at gmail.com>, 2013
+# Ryekee Zhong <ryekee at gmail.com>, 2013
+# Tower Joo<zhutao.iscas at gmail.com>, 2009
+# Aifen Qin <yinian1992 at live.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Ryekee Zhong <ryekee at gmail.com>\n"
+"Language-Team: Chinese (China) "
+"(http://www.transifex.com/projects/p/sphinx-1/language/zh_CN/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr "%s %s 文档"
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr "见 %s"
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr "参见 %s"
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr "符号"
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr "Python 提高建议; PEP %s"
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%Y 年 %m 月 %d 日"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr "内置"
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr "模块级别"
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%Y 年 %m 月 %d 日"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "总目录"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "索引"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "下一页"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "上一页"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr "(在"
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "节作者:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "模块作者:"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr "代码作者:"
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "作者:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr "%s %s"
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "参数"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "返回"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "返回类型"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C 函数)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C 成员)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C 宏)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C 类型)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C 变量)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "函数"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "成员"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "宏"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "类型"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr "变量"
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr "抛出"
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr "%s (C++ 类)"
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ 类型)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ 成员)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ 函数)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr "类"
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (內置函数)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s 方法)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr "%s() (类)"
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr "%s (全局变量或常量)"
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s 属性)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr "参数"
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr "数据"
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "属性"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr "变量"
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr "引发"
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (在 %s 模块中)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (內置变量)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s() (在 %s 模块中)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (內置类)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (%s 中的类)"
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s 方法)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s 静态方法)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s 静态方法)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr "%s() (%s.%s 类方法)"
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr "%s() (%s 类方法)"
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s 属性)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (模块)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr "Python 模块索引"
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "模块"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "已移除"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "例外"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr "方法"
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr "类方法"
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "静态方法"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "模块"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr " (已移除)"
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr "%s (指示)"
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr "%s (角色)"
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr "指示"
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr "角色"
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "环境变量; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%s命令行选项; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr "术语"
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr "语法记号"
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr "引用标签"
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "环境变量"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr "程序选项"
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "索引"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "模块索引"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "搜索页面"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr " 基类:%s"
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ":class:`%s` 的别名"
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr "[图表:%s]"
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr "[图表]"
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr "(在 %s v%s)"
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr "[源代码]"
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "待处理"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr "(<<原始记录>> 见 %s,第 %d 行)"
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr "原始记录"
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr "[文档]"
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr "模块代码"
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr "<h1>%s 源代码</h1>"
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr "概览:模块代码"
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr "<h1>代码可用的所有模块</h1>"
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "注意"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "警告"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "危险"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "错误"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "提示"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "重要"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "注解"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr "参见"
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "小技巧"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "警告"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "%s 新版功能"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "在 %s 版更改"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "%s 版后已移除"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "关键字"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "运算符"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "对象"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr "语句"
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "內置函数"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "內容目录"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "搜索"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr "转向"
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr "输入相关的术语,模块,类或者函数名称进行搜索"
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "显示源代码"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr "概述"
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr "欢迎!这是"
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr "这份文档是"
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr "最后更新于"
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr "索引和表格:"
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr "完整的内容表"
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr "列出所有的章节和部分"
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr "搜索文档"
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr "全局模块索引"
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr "快速查看所有的模块"
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr "所的函数,类,术语"
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr "索引 – %(key)s"
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr "一页的全部索引"
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr "按照字母的索引页"
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr "可能会很多"
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "导航"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "在 %(docstitle)s 中搜索"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr "关于这些文档"
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "版权所有"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "© <a href=\"%(path)s\">版权所有</a> %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr "© 版权所有 %(copyright)s."
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "最后更新于 %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr "由 <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s 创建。"
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "搜索 %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "上一个主题"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "上一章"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "下一个主题"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "下一章"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr "请激活 JavaScript 以开启搜索功能"
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr "在这儿,你可以对这些文档进行搜索。向搜索框中输入你所要搜索的关键字并点击“搜索”。注意:搜索引擎会自动搜索所有的关键字。将不会搜索到部分关键字的页面."
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "搜索"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "搜索结果"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr "没有任何文档匹配您的搜索。请确保你输入的词拼写正确并选择了合适的分类。"
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "快速搜索"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "本页"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr "更改发生在版本 %(version)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr "%(filename)s — %(docstitle)s"
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "自动生成的 %(version)s 版本中的更改列表"
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "库更改"
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API 更改"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "其他更改"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr "永久链接至标题"
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr "永久链接至目标"
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr "隐藏搜索结果"
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr "搜索中"
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr "准备搜索……"
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "搜索完成,有 %s 个页面匹配。"
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ",在"
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr "展开边栏"
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr "折叠边栏"
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr "目录"
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "发布"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr "脚注"
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr "续上页"
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr "下页继续"
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr "[图片: %s]"
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[图片]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr "返回值:总为 NULL。"
+
+#~ msgid "Return value: New reference."
+#~ msgstr "返回值:新的引用。"
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr "返回值:借引用。"
+
diff --git a/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js b/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js
new file mode 100644
index 0000000..1616bae
--- /dev/null
+++ b/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "zh_Hant_TW", "plural_expr": "0", "messages": {"Next topic": "\u4e0b\u4e00\u500b\u4e3b\u984c", "Index": "\u7d22\u5f15", "%(filename)s — %(docstitle)s": "", "Welcome! This is": "", "Copyright": "\u7248\u6b0a\u6240\u6709", "C API changes": "C API \u6539\u8b8a", "quick access to all modules": "", "© Copyright %(copyright)s.": "", "Global Module Index": "", "Your search did not match any documents. Please make sure that all words are spelle [...]
\ No newline at end of file
diff --git a/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo b/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo
new file mode 100644
index 0000000..ecc6807
Binary files /dev/null and b/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo differ
diff --git a/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po b/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po
new file mode 100644
index 0000000..bcf298f
--- /dev/null
+++ b/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po
@@ -0,0 +1,830 @@
+# Chinese (Traditional, Taiwan) translations for Sphinx.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+#
+# Translators:
+# Fred Lin <gasolin at gmail.com>, 2008
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
+"Last-Translator: Georg Brandl <g.brandl at gmx.net>\n"
+"Language-Team: Chinese (Taiwan) "
+"(http://www.transifex.com/projects/p/sphinx-1/language/zh_TW/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: sphinx/config.py:81
+#, python-format
+msgid "%s %s documentation"
+msgstr ""
+
+#: sphinx/environment.py:1550
+#, python-format
+msgid "see %s"
+msgstr ""
+
+#: sphinx/environment.py:1553
+#, python-format
+msgid "see also %s"
+msgstr ""
+
+#: sphinx/environment.py:1610
+msgid "Symbols"
+msgstr ""
+
+#: sphinx/roles.py:175
+#, python-format
+msgid "Python Enhancement Proposals; PEP %s"
+msgstr ""
+
+#: sphinx/transforms.py:56 sphinx/writers/latex.py:205
+#: sphinx/writers/manpage.py:68 sphinx/writers/texinfo.py:217
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%Y 年 %m 月 %d 日"
+
+#: sphinx/builders/changes.py:73
+msgid "Builtins"
+msgstr ""
+
+#: sphinx/builders/changes.py:75
+msgid "Module level"
+msgstr ""
+
+#: sphinx/builders/html.py:291
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%Y 年 %m 月 %d 日"
+
+#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+msgid "General Index"
+msgstr "總索引"
+
+#: sphinx/builders/html.py:310
+msgid "index"
+msgstr "索引"
+
+#: sphinx/builders/html.py:370
+msgid "next"
+msgstr "下一頁"
+
+#: sphinx/builders/html.py:379
+msgid "previous"
+msgstr "上一頁"
+
+#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+msgid " (in "
+msgstr ""
+
+#: sphinx/directives/other.py:138
+msgid "Section author: "
+msgstr "Section 作者:"
+
+#: sphinx/directives/other.py:140
+msgid "Module author: "
+msgstr "模組作者:"
+
+#: sphinx/directives/other.py:142
+msgid "Code author: "
+msgstr ""
+
+#: sphinx/directives/other.py:144
+msgid "Author: "
+msgstr "作者:"
+
+#: sphinx/domains/__init__.py:244
+#, python-format
+msgid "%s %s"
+msgstr ""
+
+#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+msgid "Parameters"
+msgstr "參數"
+
+#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+msgid "Returns"
+msgstr "返回"
+
+#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:109
+msgid "Return type"
+msgstr "返回類別"
+
+#: sphinx/domains/c.py:146
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (C 函式)"
+
+#: sphinx/domains/c.py:148
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (C 成員)"
+
+#: sphinx/domains/c.py:150
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (C 巨集)"
+
+#: sphinx/domains/c.py:152
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (C 類別)"
+
+#: sphinx/domains/c.py:154
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (C 變數)"
+
+#: sphinx/domains/c.py:211 sphinx/domains/cpp.py:1252
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:560
+msgid "function"
+msgstr "函式"
+
+#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+msgid "member"
+msgstr "成員"
+
+#: sphinx/domains/c.py:213
+msgid "macro"
+msgstr "巨集"
+
+#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+msgid "type"
+msgstr "類別"
+
+#: sphinx/domains/c.py:215
+msgid "variable"
+msgstr ""
+
+#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+msgid "Throws"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1083
+#, python-format
+msgid "%s (C++ class)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1106
+#, python-format
+msgid "%s (C++ type)"
+msgstr "%s (C++ 類別)"
+
+#: sphinx/domains/cpp.py:1126
+#, python-format
+msgid "%s (C++ member)"
+msgstr "%s (C++ 成員)"
+
+#: sphinx/domains/cpp.py:1182
+#, python-format
+msgid "%s (C++ function)"
+msgstr "%s (C++ 函式)"
+
+#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:562
+msgid "class"
+msgstr ""
+
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (內建函式)"
+
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s 方法)"
+
+#: sphinx/domains/javascript.py:109
+#, python-format
+msgid "%s() (class)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:111
+#, python-format
+msgid "%s (global variable or constant)"
+msgstr ""
+
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s 屬性)"
+
+#: sphinx/domains/javascript.py:122
+msgid "Arguments"
+msgstr ""
+
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+msgid "data"
+msgstr ""
+
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+msgid "attribute"
+msgstr "屬性"
+
+#: sphinx/domains/python.py:100
+msgid "Variables"
+msgstr ""
+
+#: sphinx/domains/python.py:104
+msgid "Raises"
+msgstr ""
+
+#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
+#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (在 %s 模組中)"
+
+#: sphinx/domains/python.py:257
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (內建變數)"
+
+#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s() (在 %s 模組中)"
+
+#: sphinx/domains/python.py:274
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (內建類別)"
+
+#: sphinx/domains/python.py:275
+#, python-format
+msgid "%s (class in %s)"
+msgstr ""
+
+#: sphinx/domains/python.py:315
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s 方法)"
+
+#: sphinx/domains/python.py:327
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s 靜態方法)"
+
+#: sphinx/domains/python.py:330
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s 靜態方法)"
+
+#: sphinx/domains/python.py:340
+#, python-format
+msgid "%s() (%s.%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:343
+#, python-format
+msgid "%s() (%s class method)"
+msgstr ""
+
+#: sphinx/domains/python.py:353
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s 屬性)"
+
+#: sphinx/domains/python.py:434
+#, python-format
+msgid "%s (module)"
+msgstr "%s (模組)"
+
+#: sphinx/domains/python.py:491
+msgid "Python Module Index"
+msgstr ""
+
+#: sphinx/domains/python.py:492
+msgid "modules"
+msgstr "模組"
+
+#: sphinx/domains/python.py:538
+msgid "Deprecated"
+msgstr "已移除"
+
+#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+msgid "exception"
+msgstr "例外"
+
+#: sphinx/domains/python.py:564
+msgid "method"
+msgstr ""
+
+#: sphinx/domains/python.py:565
+msgid "class method"
+msgstr ""
+
+#: sphinx/domains/python.py:566
+msgid "static method"
+msgstr "靜態方法"
+
+#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+msgid "module"
+msgstr "模組"
+
+#: sphinx/domains/python.py:696
+msgid " (deprecated)"
+msgstr ""
+
+#: sphinx/domains/rst.py:53
+#, python-format
+msgid "%s (directive)"
+msgstr ""
+
+#: sphinx/domains/rst.py:55
+#, python-format
+msgid "%s (role)"
+msgstr ""
+
+#: sphinx/domains/rst.py:104
+msgid "directive"
+msgstr ""
+
+#: sphinx/domains/rst.py:105
+msgid "role"
+msgstr ""
+
+#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#, python-format
+msgid "environment variable; %s"
+msgstr "環境變數; %s"
+
+#: sphinx/domains/std.py:180
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%s命令列選項; %s"
+
+#: sphinx/domains/std.py:457
+msgid "glossary term"
+msgstr ""
+
+#: sphinx/domains/std.py:458
+msgid "grammar token"
+msgstr ""
+
+#: sphinx/domains/std.py:459
+msgid "reference label"
+msgstr ""
+
+#: sphinx/domains/std.py:461
+msgid "environment variable"
+msgstr "環境變數"
+
+#: sphinx/domains/std.py:462
+msgid "program option"
+msgstr ""
+
+#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/themes/basic/genindex-single.html:57
+#: sphinx/themes/basic/genindex-split.html:11
+#: sphinx/themes/basic/genindex-split.html:14
+#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
+#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
+#: sphinx/writers/latex.py:194 sphinx/writers/texinfo.py:475
+msgid "Index"
+msgstr "索引"
+
+#: sphinx/domains/std.py:493
+msgid "Module Index"
+msgstr "模組索引"
+
+#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+msgid "Search Page"
+msgstr "搜尋頁面"
+
+#: sphinx/ext/autodoc.py:1065
+#, python-format
+msgid " Bases: %s"
+msgstr ""
+
+#: sphinx/ext/autodoc.py:1113
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#, python-format
+msgid "[graph: %s]"
+msgstr ""
+
+#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+msgid "[graph]"
+msgstr ""
+
+#: sphinx/ext/intersphinx.py:244
+#, python-format
+msgid "(in %s v%s)"
+msgstr ""
+
+#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+msgid "[source]"
+msgstr ""
+
+#: sphinx/ext/todo.py:42
+msgid "Todo"
+msgstr "待辦"
+
+#: sphinx/ext/todo.py:112
+#, python-format
+msgid "(The <<original entry>> is located in %s, line %d.)"
+msgstr ""
+
+#: sphinx/ext/todo.py:121
+msgid "original entry"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:117
+msgid "[docs]"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:131
+msgid "Module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:137
+#, python-format
+msgid "<h1>Source code for %s</h1>"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:164
+msgid "Overview: module code"
+msgstr ""
+
+#: sphinx/ext/viewcode.py:165
+msgid "<h1>All modules for which code is available</h1>"
+msgstr ""
+
+#: sphinx/locale/__init__.py:155
+msgid "Attention"
+msgstr "注意"
+
+#: sphinx/locale/__init__.py:156
+msgid "Caution"
+msgstr "警示"
+
+#: sphinx/locale/__init__.py:157
+msgid "Danger"
+msgstr "危險"
+
+#: sphinx/locale/__init__.py:158
+msgid "Error"
+msgstr "錯誤"
+
+#: sphinx/locale/__init__.py:159
+msgid "Hint"
+msgstr "提示"
+
+#: sphinx/locale/__init__.py:160
+msgid "Important"
+msgstr "重要"
+
+#: sphinx/locale/__init__.py:161
+msgid "Note"
+msgstr "註解"
+
+#: sphinx/locale/__init__.py:162
+msgid "See also"
+msgstr ""
+
+#: sphinx/locale/__init__.py:163
+msgid "Tip"
+msgstr "小技巧"
+
+#: sphinx/locale/__init__.py:164
+msgid "Warning"
+msgstr "警告"
+
+#: sphinx/locale/__init__.py:168
+#, python-format
+msgid "New in version %s"
+msgstr "%s 版新功能"
+
+#: sphinx/locale/__init__.py:169
+#, python-format
+msgid "Changed in version %s"
+msgstr "在 %s 版改變"
+
+#: sphinx/locale/__init__.py:170
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "%s 版後已移除"
+
+#: sphinx/locale/__init__.py:176
+msgid "keyword"
+msgstr "關鍵字"
+
+#: sphinx/locale/__init__.py:177
+msgid "operator"
+msgstr "運算子"
+
+#: sphinx/locale/__init__.py:178
+msgid "object"
+msgstr "物件"
+
+#: sphinx/locale/__init__.py:180
+msgid "statement"
+msgstr ""
+
+#: sphinx/locale/__init__.py:181
+msgid "built-in function"
+msgstr "內建函式"
+
+#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
+#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
+msgid "Table Of Contents"
+msgstr "內容目錄"
+
+#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
+#: sphinx/themes/basic/searchresults.html:10
+msgid "Search"
+msgstr "搜尋"
+
+#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
+msgid "Go"
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+msgid "Enter search terms or a module, class or function name."
+msgstr ""
+
+#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
+msgid "Show Source"
+msgstr "顯示原始碼"
+
+#: sphinx/themes/basic/defindex.html:11
+msgid "Overview"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:15
+msgid "Welcome! This is"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:16
+msgid "the documentation for"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:17
+msgid "last updated"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:20
+msgid "Indices and tables:"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:23
+msgid "Complete Table of Contents"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:24
+msgid "lists all sections and subsections"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:26
+msgid "search this documentation"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:28
+msgid "Global Module Index"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:29
+msgid "quick access to all modules"
+msgstr ""
+
+#: sphinx/themes/basic/defindex.html:31
+msgid "all functions, classes, terms"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:35
+#, python-format
+msgid "Index – %(key)s"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-single.html:63
+#: sphinx/themes/basic/genindex-split.html:24
+#: sphinx/themes/basic/genindex-split.html:38
+#: sphinx/themes/basic/genindex.html:74
+msgid "Full index on one page"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-split.html:16
+msgid "Index pages by letter"
+msgstr ""
+
+#: sphinx/themes/basic/genindex-split.html:25
+msgid "can be huge"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:29
+msgid "Navigation"
+msgstr "瀏覽"
+
+#: sphinx/themes/basic/layout.html:122
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "在 %(docstitle)s 中搜尋"
+
+#: sphinx/themes/basic/layout.html:131
+msgid "About these documents"
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:140
+msgid "Copyright"
+msgstr "版權所有"
+
+#: sphinx/themes/basic/layout.html:189
+#, python-format
+msgid "© <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:191
+#, python-format
+msgid "© Copyright %(copyright)s."
+msgstr ""
+
+#: sphinx/themes/basic/layout.html:195
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "最後更新日期是 %(last_updated)s."
+
+#: sphinx/themes/basic/layout.html:198
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+
+#: sphinx/themes/basic/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "搜尋 %(docstitle)s"
+
+#: sphinx/themes/basic/relations.html:11
+msgid "Previous topic"
+msgstr "上一個主題"
+
+#: sphinx/themes/basic/relations.html:13
+msgid "previous chapter"
+msgstr "上一章"
+
+#: sphinx/themes/basic/relations.html:16
+msgid "Next topic"
+msgstr "下一個主題"
+
+#: sphinx/themes/basic/relations.html:18
+msgid "next chapter"
+msgstr "下一章"
+
+#: sphinx/themes/basic/search.html:27
+msgid ""
+"Please activate JavaScript to enable the search\n"
+" functionality."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:32
+msgid ""
+"From here you can search these documents. Enter your search\n"
+" words into the box below and click \"search\". Note that the search\n"
+" function will automatically search for all of the words. Pages\n"
+" containing fewer words won't appear in the result list."
+msgstr ""
+
+#: sphinx/themes/basic/search.html:39 sphinx/themes/basic/searchresults.html:17
+msgid "search"
+msgstr "搜尋"
+
+#: sphinx/themes/basic/search.html:43 sphinx/themes/basic/searchresults.html:21
+#: sphinx/themes/basic/static/searchtools.js_t:281
+msgid "Search Results"
+msgstr "搜尋結果"
+
+#: sphinx/themes/basic/search.html:45 sphinx/themes/basic/searchresults.html:23
+#: sphinx/themes/basic/static/searchtools.js_t:283
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+
+#: sphinx/themes/basic/searchbox.html:12
+msgid "Quick search"
+msgstr "快速搜尋"
+
+#: sphinx/themes/basic/sourcelink.html:11
+msgid "This Page"
+msgstr "本頁"
+
+#: sphinx/themes/basic/changes/frameset.html:5
+#: sphinx/themes/basic/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s — %(docstitle)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr ""
+
+#: sphinx/themes/basic/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "C API 改變"
+
+#: sphinx/themes/basic/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "其他改變:"
+
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
+#: sphinx/writers/html.py:548
+msgid "Permalink to this headline"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+msgid "Permalink to this definition"
+msgstr ""
+
+#: sphinx/themes/basic/static/doctools.js:180
+msgid "Hide Search Matches"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:119
+msgid "Searching"
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:124
+msgid "Preparing search..."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:285
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr ""
+
+#: sphinx/themes/basic/static/searchtools.js_t:337
+msgid ", in "
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:83
+msgid "Expand sidebar"
+msgstr ""
+
+#: sphinx/themes/default/static/sidebar.js_t:96
+#: sphinx/themes/default/static/sidebar.js_t:124
+msgid "Collapse sidebar"
+msgstr ""
+
+#: sphinx/themes/haiku/layout.html:24
+msgid "Contents"
+msgstr ""
+
+#: sphinx/writers/latex.py:192
+msgid "Release"
+msgstr "釋出"
+
+#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
+#: sphinx/writers/texinfo.py:612
+msgid "Footnotes"
+msgstr ""
+
+#: sphinx/writers/latex.py:709
+msgid "continued from previous page"
+msgstr ""
+
+#: sphinx/writers/latex.py:715
+msgid "Continued on next page"
+msgstr ""
+
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#, python-format
+msgid "[image: %s]"
+msgstr ""
+
+#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+msgid "[image]"
+msgstr "[圖片]"
+
+#~ msgid "Return value: Always NULL."
+#~ msgstr ""
+
+#~ msgid "Return value: New reference."
+#~ msgstr ""
+
+#~ msgid "Return value: Borrowed reference."
+#~ msgstr ""
+
diff --git a/sphinx/make_mode.py b/sphinx/make_mode.py
new file mode 100644
index 0000000..b4b5b74
--- /dev/null
+++ b/sphinx/make_mode.py
@@ -0,0 +1,259 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.make_mode
+ ~~~~~~~~~~~~~~~~
+
+ sphinx-build -M command-line handling.
+
+ This replaces the old, platform-dependent and once-generated content
+ of Makefile / make.bat.
+
+ This is in its own module so that importing it is fast. It should not
+ import the main Sphinx modules (like sphinx.applications, sphinx.builders).
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import sys
+import shutil
+from os import path
+from subprocess import call
+
+import sphinx
+from sphinx.util.console import bold, blue
+
+proj_name = os.getenv('SPHINXPROJ', '<project>')
+
+
+BUILDERS = [
+ ("", "html", "to make standalone HTML files"),
+ ("", "dirhtml", "to make HTML files named index.html in directories"),
+ ("", "singlehtml","to make a single large HTML file"),
+ ("", "pickle", "to make pickle files"),
+ ("", "json", "to make JSON files"),
+ ("", "htmlhelp", "to make HTML files and a HTML help project"),
+ ("", "qthelp", "to make HTML files and a qthelp project"),
+ ("", "devhelp", "to make HTML files and a Devhelp project"),
+ ("", "epub", "to make an epub"),
+ ("", "latex", "to make LaTeX files, you can set PAPER=a4 or PAPER=letter"),
+ ("posix", "latexpdf", "to make LaTeX files and run them through pdflatex"),
+ ("posix", "latexpdfja","to make LaTeX files and run them through platex/dvipdfmx"),
+ ("", "text", "to make text files"),
+ ("", "man", "to make manual pages"),
+ ("", "texinfo", "to make Texinfo files"),
+ ("posix", "info", "to make Texinfo files and run them through makeinfo"),
+ ("", "gettext", "to make PO message catalogs"),
+ ("", "changes", "to make an overview of all changed/added/deprecated items"),
+ ("", "xml", "to make Docutils-native XML files"),
+ ("", "pseudoxml", "to make pseudoxml-XML files for display purposes"),
+ ("", "linkcheck", "to check all external links for integrity"),
+ ("", "doctest", "to run all doctests embedded in the documentation "
+ "(if enabled)"),
+ ("", "coverage", "to run coverage check of the documentation (if enabled)"),
+]
+
+
+class Make(object):
+
+ def __init__(self, srcdir, builddir, opts):
+ self.srcdir = srcdir
+ self.builddir = builddir
+ self.opts = opts
+
+ def builddir_join(self, *comps):
+ return path.join(self.builddir, *comps)
+
+ def build_clean(self):
+ if not path.exists(self.builddir):
+ return
+ elif not path.isdir(self.builddir):
+ print "Error: %r is not a directory!" % self.builddir
+ return 1
+ print "Removing everything under %r..." % self.builddir
+ for item in os.listdir(self.builddir):
+ shutil.rmtree(self.builddir_join(item))
+
+ def build_help(self):
+ print bold("Sphinx v%s" % sphinx.__version__)
+ print "Please use `make %s' where %s is one of" % ((blue('target'),)*2)
+ for osname, bname, description in BUILDERS:
+ if not osname or os.name == osname:
+ print ' %s %s' % (blue(bname.ljust(10)), description)
+
+ def build_html(self):
+ if self.run_generic_build('html') > 0:
+ return 1
+ print
+ print 'Build finished. The HTML pages are in %s.' % self.builddir_join('html')
+
+ def build_dirhtml(self):
+ if self.run_generic_build('dirhtml') > 0:
+ return 1
+ print
+ print 'Build finished. The HTML pages are in %s.' % self.builddir_join('dirhtml')
+
+ def build_singlehtml(self):
+ if self.run_generic_build('singlehtml') > 0:
+ return 1
+ print
+ print 'Build finished. The HTML page is in %s.' % \
+ self.builddir_join('singlehtml')
+
+ def build_pickle(self):
+ if self.run_generic_build('pickle') > 0:
+ return 1
+ print
+ print 'Build finished; now you can process the pickle files.'
+
+ def build_json(self):
+ if self.run_generic_build('json') > 0:
+ return 1
+ print
+ print 'Build finished; now you can process the JSON files.'
+
+ def build_htmlhelp(self):
+ if self.run_generic_build('htmlhelp') > 0:
+ return 1
+ print
+ print ('Build finished; now you can run HTML Help Workshop with the '
+ '.hhp project file in %s.') % self.builddir_join('htmlhelp')
+
+ def build_qthelp(self):
+ if self.run_generic_build('qthelp') > 0:
+ return 1
+ print
+ print ('Build finished; now you can run "qcollectiongenerator" with the '
+ '.qhcp project file in %s, like this:') % self.builddir_join('qthelp')
+ print '$ qcollectiongenerator %s.qhcp' % self.builddir_join('qthelp', proj_name)
+ print 'To view the help file:'
+ print '$ assistant -collectionFile %s.qhc' % \
+ self.builddir_join('qthelp', proj_name)
+
+ def build_devhelp(self):
+ if self.run_generic_build('devhelp') > 0:
+ return 1
+ print
+ print "Build finished."
+ print "To view the help file:"
+ print "$ mkdir -p $HOME/.local/share/devhelp/" + proj_name
+ print "$ ln -s %s $HOME/.local/share/devhelp/%s" % \
+ (self.builddir_join('devhelp'), proj_name)
+ print "$ devhelp"
+
+ def build_epub(self):
+ if self.run_generic_build('epub') > 0:
+ return 1
+ print
+ print 'Build finished. The ePub file is in %s.' % self.builddir_join('epub')
+
+ def build_latex(self):
+ if self.run_generic_build('latex') > 0:
+ return 1
+ print "Build finished; the LaTeX files are in %s." % self.builddir_join('latex')
+ if os.name == 'posix':
+ print "Run `make' in that directory to run these through (pdf)latex"
+ print "(use `make latexpdf' here to do that automatically)."
+
+ def build_latexpdf(self):
+ if self.run_generic_build('latex') > 0:
+ return 1
+ os.system('make -C %s all-pdf' % self.builddir_join('latex'))
+
+ def build_latexpdfja(self):
+ if self.run_generic_build('latex') > 0:
+ return 1
+ os.system('make -C %s all-pdf-ja' % self.builddir_join('latex'))
+
+ def build_text(self):
+ if self.run_generic_build('text') > 0:
+ return 1
+ print
+ print 'Build finished. The text files are in %s.' % self.builddir_join('text')
+
+ def build_texinfo(self):
+ if self.run_generic_build('texinfo') > 0:
+ return 1
+ print "Build finished; the Texinfo files are in %s." % \
+ self.builddir_join('texinfo')
+ if os.name == 'posix':
+ print "Run `make' in that directory to run these through makeinfo"
+ print "(use `make info' here to do that automatically)."
+
+ def build_info(self):
+ if self.run_generic_build('texinfo') > 0:
+ return 1
+ os.system('make -C %s info' % self.builddir_join('texinfo'))
+
+ def build_gettext(self):
+ dtdir = self.builddir_join('gettext', '.doctrees')
+ if self.run_generic_build('gettext', doctreedir=dtdir) > 0:
+ return 1
+ print
+ print 'Build finished. The message catalogs are in %s.' % \
+ self.builddir_join('gettext')
+
+ def build_changes(self):
+ if self.run_generic_build('changes') > 0:
+ return 1
+ print
+ print 'Build finished. The overview file is in %s.' % \
+ self.builddir_join('changes')
+
+ def build_linkcheck(self):
+ res = self.run_generic_build('linkcheck')
+ print
+ print ('Link check complete; look for any errors in the above output '
+ 'or in %s.') % self.builddir_join('linkcheck', 'output.txt')
+ return res
+
+ def build_doctest(self):
+ res = self.run_generic_build('doctest')
+ print ("Testing of doctests in the sources finished, look at the "
+ "results in %s." % self.builddir_join('doctest', 'output.txt'))
+ return res
+
+ def build_coverage(self):
+ if self.run_generic_build('coverage') > 0:
+ print "Has the coverage extension been enabled?"
+ return 1
+ print
+ print ("Testing of coverage in the sources finished, look at the "
+ "results in %s." % self.builddir_join('coverage'))
+
+ def build_xml(self):
+ if self.run_generic_build('xml') > 0:
+ return 1
+ print
+ print 'Build finished. The XML files are in %s.' % self.builddir_join('xml')
+
+ def build_pseudoxml(self):
+ if self.run_generic_build('pseudoxml') > 0:
+ return 1
+ print
+ print 'Build finished. The pseudo-XML files are in %s.' % \
+ self.builddir_join('pseudoxml')
+
+ def run_generic_build(self, builder, doctreedir=None):
+ # compatibility with old Makefile
+ papersize = os.getenv('PAPER', '')
+ opts = self.opts
+ if papersize in ('a4', 'letter'):
+ opts.extend(['-D', 'latex_paper_size=' + papersize])
+ if doctreedir is None:
+ doctreedir = self.builddir_join('doctrees')
+ return call([sys.executable, sys.argv[0], '-b', builder] + opts +
+ ['-d', doctreedir, self.srcdir, self.builddir_join(builder)])
+
+
+def run_make_mode(args):
+ if len(args) < 3:
+ print >>sys.stderr, ('Error: at least 3 arguments (builder, source '
+ 'dir, build dir) are required.')
+ return 1
+ make = Make(args[1], args[2], args[3:])
+ run_method = 'build_' + args[0]
+ if hasattr(make, run_method):
+ return getattr(make, run_method)()
+ return make.run_generic_build(args[0])
diff --git a/sphinx/pycode/Grammar-py2.txt b/sphinx/pycode/Grammar-py2.txt
new file mode 100644
index 0000000..98bd1f2
--- /dev/null
+++ b/sphinx/pycode/Grammar-py2.txt
@@ -0,0 +1,135 @@
+# Grammar for Python 2.x
+
+# IMPORTANT: when copying over a new Grammar file, make sure file_input
+# is the first nonterminal in the file!
+
+# Start symbols for the grammar:
+# single_input is a single interactive statement;
+# file_input is a module or sequence of commands read from an input file;
+# eval_input is the input for the eval() and input() functions.
+# NB: compound_stmt in single_input is followed by extra NEWLINE!
+file_input: (NEWLINE | stmt)* ENDMARKER
+single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
+eval_input: testlist NEWLINE* ENDMARKER
+
+decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
+decorators: decorator+
+decorated: decorators (classdef | funcdef)
+funcdef: 'def' NAME parameters ':' suite
+parameters: '(' [varargslist] ')'
+varargslist: ((fpdef ['=' test] ',')*
+ ('*' NAME [',' '**' NAME] | '**' NAME) |
+ fpdef ['=' test] (',' fpdef ['=' test])* [','])
+fpdef: NAME | '(' fplist ')'
+fplist: fpdef (',' fpdef)* [',']
+
+stmt: simple_stmt | compound_stmt
+simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt |
+ import_stmt | global_stmt | exec_stmt | assert_stmt)
+expr_stmt: testlist (augassign (yield_expr|testlist) |
+ ('=' (yield_expr|testlist))*)
+augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
+ '<<=' | '>>=' | '**=' | '//=')
+# For normal assignments, additional restrictions enforced by the interpreter
+print_stmt: 'print' ( [ test (',' test)* [','] ] |
+ '>>' test [ (',' test)+ [','] ] )
+del_stmt: 'del' exprlist
+pass_stmt: 'pass'
+flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
+break_stmt: 'break'
+continue_stmt: 'continue'
+return_stmt: 'return' [testlist]
+yield_stmt: yield_expr
+raise_stmt: 'raise' [test [',' test [',' test]]]
+import_stmt: import_name | import_from
+import_name: 'import' dotted_as_names
+import_from: ('from' ('.'* dotted_name | '.'+)
+ 'import' ('*' | '(' import_as_names ')' | import_as_names))
+import_as_name: NAME ['as' NAME]
+dotted_as_name: dotted_name ['as' NAME]
+import_as_names: import_as_name (',' import_as_name)* [',']
+dotted_as_names: dotted_as_name (',' dotted_as_name)*
+dotted_name: NAME ('.' NAME)*
+global_stmt: 'global' NAME (',' NAME)*
+exec_stmt: 'exec' expr ['in' test [',' test]]
+assert_stmt: 'assert' test [',' test]
+
+compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
+if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+while_stmt: 'while' test ':' suite ['else' ':' suite]
+for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
+try_stmt: ('try' ':' suite
+ ((except_clause ':' suite)+
+ ['else' ':' suite]
+ ['finally' ':' suite] |
+ 'finally' ':' suite))
+with_stmt: 'with' with_item (',' with_item)* ':' suite
+with_item: test ['as' expr]
+# NB compile.c makes sure that the default except clause is last
+except_clause: 'except' [test [('as' | ',') test]]
+suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
+
+# Backward compatibility cruft to support:
+# [ x for x in lambda: True, lambda: False if x() ]
+# even while also allowing:
+# lambda x: 5 if x else 2
+# (But not a mix of the two)
+testlist_safe: old_test [(',' old_test)+ [',']]
+old_test: or_test | old_lambdef
+old_lambdef: 'lambda' [varargslist] ':' old_test
+
+test: or_test ['if' or_test 'else' test] | lambdef
+or_test: and_test ('or' and_test)*
+and_test: not_test ('and' not_test)*
+not_test: 'not' not_test | comparison
+comparison: expr (comp_op expr)*
+comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
+expr: xor_expr ('|' xor_expr)*
+xor_expr: and_expr ('^' and_expr)*
+and_expr: shift_expr ('&' shift_expr)*
+shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+arith_expr: term (('+'|'-') term)*
+term: factor (('*'|'/'|'%'|'//') factor)*
+factor: ('+'|'-'|'~') factor | power
+power: atom trailer* ['**' factor]
+atom: ('(' [yield_expr|testlist_comp] ')' |
+ '[' [listmaker] ']' |
+ '{' [dictorsetmaker] '}' |
+ '`' testlist1 '`' |
+ NAME | NUMBER | STRING+)
+listmaker: test ( list_for | (',' test)* [','] )
+testlist_comp: test ( comp_for | (',' test)* [','] )
+lambdef: 'lambda' [varargslist] ':' test
+trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+subscriptlist: subscript (',' subscript)* [',']
+subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
+sliceop: ':' [test]
+exprlist: expr (',' expr)* [',']
+testlist: test (',' test)* [',']
+dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
+ (test (comp_for | (',' test)* [','])) )
+
+classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
+
+arglist: (argument ',')* (argument [',']
+ |'*' test (',' argument)* [',' '**' test]
+ |'**' test)
+# The reason that keywords are test nodes instead of NAME is that using NAME
+# results in an ambiguity. ast.c makes sure it's a NAME.
+argument: test [comp_for] | test '=' test
+
+list_iter: list_for | list_if
+list_for: 'for' exprlist 'in' testlist_safe [list_iter]
+list_if: 'if' old_test [list_iter]
+
+comp_iter: comp_for | comp_if
+comp_for: 'for' exprlist 'in' or_test [comp_iter]
+comp_if: 'if' old_test [comp_iter]
+
+testlist1: test (',' test)*
+
+# not used in grammar, but may appear in "node" passed from Parser to Compiler
+encoding_decl: NAME
+
+yield_expr: 'yield' [testlist]
diff --git a/sphinx/pycode/Grammar-py3.txt b/sphinx/pycode/Grammar-py3.txt
new file mode 100644
index 0000000..083b5f9
--- /dev/null
+++ b/sphinx/pycode/Grammar-py3.txt
@@ -0,0 +1,126 @@
+# Grammar for Python 3.x (with at least x <= 4)
+
+# IMPORTANT: when copying over a new Grammar file, make sure file_input
+# is the first nonterminal in the file!
+
+# Start symbols for the grammar:
+# single_input is a single interactive statement;
+# file_input is a module or sequence of commands read from an input file;
+# eval_input is the input for the eval() functions.
+# NB: compound_stmt in single_input is followed by extra NEWLINE!
+file_input: (NEWLINE | stmt)* ENDMARKER
+single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
+eval_input: testlist NEWLINE* ENDMARKER
+
+decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
+decorators: decorator+
+decorated: decorators (classdef | funcdef)
+funcdef: 'def' NAME parameters ['->' test] ':' suite
+parameters: '(' [typedargslist] ')'
+typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [','
+ ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]]
+ | '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef)
+tfpdef: NAME [':' test]
+varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [','
+ ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]]
+ | '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef)
+vfpdef: NAME
+
+stmt: simple_stmt | compound_stmt
+simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
+ import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
+expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) |
+ ('=' (yield_expr|testlist_star_expr))*)
+testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
+augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
+ '<<=' | '>>=' | '**=' | '//=')
+# For normal assignments, additional restrictions enforced by the interpreter
+del_stmt: 'del' exprlist
+pass_stmt: 'pass'
+flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
+break_stmt: 'break'
+continue_stmt: 'continue'
+return_stmt: 'return' [testlist]
+yield_stmt: yield_expr
+raise_stmt: 'raise' [test ['from' test]]
+import_stmt: import_name | import_from
+import_name: 'import' dotted_as_names
+# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
+import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+)
+ 'import' ('*' | '(' import_as_names ')' | import_as_names))
+import_as_name: NAME ['as' NAME]
+dotted_as_name: dotted_name ['as' NAME]
+import_as_names: import_as_name (',' import_as_name)* [',']
+dotted_as_names: dotted_as_name (',' dotted_as_name)*
+dotted_name: NAME ('.' NAME)*
+global_stmt: 'global' NAME (',' NAME)*
+nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
+assert_stmt: 'assert' test [',' test]
+
+compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
+if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+while_stmt: 'while' test ':' suite ['else' ':' suite]
+for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
+try_stmt: ('try' ':' suite
+ ((except_clause ':' suite)+
+ ['else' ':' suite]
+ ['finally' ':' suite] |
+ 'finally' ':' suite))
+with_stmt: 'with' with_item (',' with_item)* ':' suite
+with_item: test ['as' expr]
+# NB compile.c makes sure that the default except clause is last
+except_clause: 'except' [test ['as' NAME]]
+suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
+
+test: or_test ['if' or_test 'else' test] | lambdef
+test_nocond: or_test | lambdef_nocond
+lambdef: 'lambda' [varargslist] ':' test
+lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
+or_test: and_test ('or' and_test)*
+and_test: not_test ('and' not_test)*
+not_test: 'not' not_test | comparison
+comparison: expr (comp_op expr)*
+# <> isn't actually a valid comparison operator in Python. It's here for the
+# sake of a __future__ import described in PEP 401
+comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
+star_expr: '*' expr
+expr: xor_expr ('|' xor_expr)*
+xor_expr: and_expr ('^' and_expr)*
+and_expr: shift_expr ('&' shift_expr)*
+shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+arith_expr: term (('+'|'-') term)*
+term: factor (('*'|'/'|'%'|'//') factor)*
+factor: ('+'|'-'|'~') factor | power
+power: atom trailer* ['**' factor]
+atom: ('(' [yield_expr|testlist_comp] ')' |
+ '[' [testlist_comp] ']' |
+ '{' [dictorsetmaker] '}' |
+ NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
+testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
+trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+subscriptlist: subscript (',' subscript)* [',']
+subscript: test | [test] ':' [test] [sliceop]
+sliceop: ':' [test]
+exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
+testlist: test (',' test)* [',']
+dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
+ (test (comp_for | (',' test)* [','])) )
+
+classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
+
+arglist: (argument ',')* (argument [',']
+ |'*' test (',' argument)* [',' '**' test]
+ |'**' test)
+# The reason that keywords are test nodes instead of NAME is that using NAME
+# results in an ambiguity. ast.c makes sure it's a NAME.
+argument: test [comp_for] | test '=' test # Really [keyword '='] test
+comp_iter: comp_for | comp_if
+comp_for: 'for' exprlist 'in' or_test [comp_iter]
+comp_if: 'if' test_nocond [comp_iter]
+
+# not used in grammar, but may appear in "node" passed from Parser to Compiler
+encoding_decl: NAME
+
+yield_expr: 'yield' [yield_arg]
+yield_arg: 'from' test | testlist
diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py
new file mode 100644
index 0000000..7a6f59b
--- /dev/null
+++ b/sphinx/pycode/__init__.py
@@ -0,0 +1,347 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.pycode
+ ~~~~~~~~~~~~~
+
+ Utilities parsing and analyzing Python code.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+from os import path
+
+from sphinx import package_dir
+from sphinx.errors import PycodeError
+from sphinx.pycode import nodes
+from sphinx.pycode.pgen2 import driver, token, tokenize, parse, literals
+from sphinx.util import get_module_source, detect_encoding
+from sphinx.util.pycompat import next, StringIO, BytesIO, TextIOWrapper
+from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc
+
+
+# load the Python grammar
+_grammarfile = path.join(package_dir, 'pycode',
+ 'Grammar-py%d.txt' % sys.version_info[0])
+pygrammar = driver.load_grammar(_grammarfile)
+pydriver = driver.Driver(pygrammar, convert=nodes.convert)
+
+# an object with attributes corresponding to token and symbol names
+class sym: pass
+for k, v in pygrammar.symbol2number.iteritems():
+ setattr(sym, k, v)
+for k, v in token.tok_name.iteritems():
+ setattr(sym, v, k)
+
+# a dict mapping terminal and nonterminal numbers to their names
+number2name = pygrammar.number2symbol.copy()
+number2name.update(token.tok_name)
+
+_eq = nodes.Leaf(token.EQUAL, '=')
+
+
+class AttrDocVisitor(nodes.NodeVisitor):
+ """
+ Visitor that collects docstrings for attribute assignments on toplevel and
+ in classes (class attributes and attributes set in __init__).
+
+ The docstrings can either be in special '#:' comments before the assignment
+ or in a docstring after it.
+ """
+ def init(self, scope, encoding):
+ self.scope = scope
+ self.in_init = 0
+ self.encoding = encoding
+ self.namespace = []
+ self.collected = {}
+ self.tagnumber = 0
+ self.tagorder = {}
+
+ def add_tag(self, name):
+ name = '.'.join(self.namespace + [name])
+ self.tagorder[name] = self.tagnumber
+ self.tagnumber += 1
+
+ def visit_classdef(self, node):
+ """Visit a class."""
+ self.add_tag(node[1].value)
+ self.namespace.append(node[1].value)
+ self.generic_visit(node)
+ self.namespace.pop()
+
+ def visit_funcdef(self, node):
+ """Visit a function (or method)."""
+ # usually, don't descend into functions -- nothing interesting there
+ self.add_tag(node[1].value)
+ if node[1].value == '__init__':
+ # however, collect attributes set in __init__ methods
+ self.in_init += 1
+ self.generic_visit(node)
+ self.in_init -= 1
+
+ def visit_expr_stmt(self, node):
+ """Visit an assignment which may have a special comment before (or
+ after) it.
+ """
+ if _eq not in node.children:
+ # not an assignment (we don't care for augmented assignments)
+ return
+ # look *after* the node; there may be a comment prefixing the NEWLINE
+ # of the simple_stmt
+ parent = node.parent
+ idx = parent.children.index(node) + 1
+ while idx < len(parent):
+ if parent[idx].type == sym.SEMI:
+ idx += 1
+ continue # skip over semicolon
+ if parent[idx].type == sym.NEWLINE:
+ prefix = parent[idx].get_prefix()
+ if not isinstance(prefix, unicode):
+ prefix = prefix.decode(self.encoding)
+ docstring = prepare_commentdoc(prefix)
+ if docstring:
+ self.add_docstring(node, docstring)
+ return # don't allow docstrings both before and after
+ break
+ # now look *before* the node
+ pnode = node[0]
+ prefix = pnode.get_prefix()
+ # if the assignment is the first statement on a new indentation
+ # level, its preceding whitespace and comments are not assigned
+ # to that token, but the first INDENT or DEDENT token
+ while not prefix:
+ pnode = pnode.get_prev_leaf()
+ if not pnode or pnode.type not in (token.INDENT, token.DEDENT):
+ break
+ prefix = pnode.get_prefix()
+ if not isinstance(prefix, unicode):
+ prefix = prefix.decode(self.encoding)
+ docstring = prepare_commentdoc(prefix)
+ self.add_docstring(node, docstring)
+
+ def visit_simple_stmt(self, node):
+ """Visit a docstring statement which may have an assignment before."""
+ if node[0].type != token.STRING:
+ # not a docstring; but still need to visit children
+ return self.generic_visit(node)
+ prev = node.get_prev_sibling()
+ if not prev:
+ return
+ if prev.type == sym.simple_stmt and \
+ prev[0].type == sym.expr_stmt and _eq in prev[0].children:
+ # need to "eval" the string because it's returned in its
+ # original form
+ docstring = literals.evalString(node[0].value, self.encoding)
+ docstring = prepare_docstring(docstring)
+ self.add_docstring(prev[0], docstring)
+
+ def add_docstring(self, node, docstring):
+ # add an item for each assignment target
+ for i in range(0, len(node) - 1, 2):
+ target = node[i]
+ if self.in_init and self.number2name[target.type] == 'power':
+ # maybe an attribute assignment -- check necessary conditions
+ if (# node must have two children
+ len(target) != 2 or
+ # first child must be "self"
+ target[0].type != token.NAME or target[0].value != 'self' or
+ # second child must be a "trailer" with two children
+ self.number2name[target[1].type] != 'trailer' or
+ len(target[1]) != 2 or
+ # first child must be a dot, second child a name
+ target[1][0].type != token.DOT or
+ target[1][1].type != token.NAME):
+ continue
+ name = target[1][1].value
+ elif target.type != token.NAME:
+ # don't care about other complex targets
+ continue
+ else:
+ name = target.value
+ self.add_tag(name)
+ if docstring:
+ namespace = '.'.join(self.namespace)
+ if namespace.startswith(self.scope):
+ self.collected[namespace, name] = docstring
+
+
+class ModuleAnalyzer(object):
+ # cache for analyzer objects -- caches both by module and file name
+ cache = {}
+
+ @classmethod
+ def for_string(cls, string, modname, srcname='<string>'):
+ if isinstance(string, bytes):
+ return cls(BytesIO(string), modname, srcname)
+ return cls(StringIO(string), modname, srcname, decoded=True)
+
+ @classmethod
+ def for_file(cls, filename, modname):
+ if ('file', filename) in cls.cache:
+ return cls.cache['file', filename]
+ try:
+ fileobj = open(filename, 'rb')
+ except Exception, err:
+ raise PycodeError('error opening %r' % filename, err)
+ obj = cls(fileobj, modname, filename)
+ cls.cache['file', filename] = obj
+ return obj
+
+ @classmethod
+ def for_module(cls, modname):
+ if ('module', modname) in cls.cache:
+ entry = cls.cache['module', modname]
+ if isinstance(entry, PycodeError):
+ raise entry
+ return entry
+
+ try:
+ type, source = get_module_source(modname)
+ if type == 'string':
+ obj = cls.for_string(source, modname)
+ else:
+ obj = cls.for_file(source, modname)
+ except PycodeError, err:
+ cls.cache['module', modname] = err
+ raise
+ cls.cache['module', modname] = obj
+ return obj
+
+ def __init__(self, source, modname, srcname, decoded=False):
+ # name of the module
+ self.modname = modname
+ # name of the source file
+ self.srcname = srcname
+ # file-like object yielding source lines
+ self.source = source
+
+ # cache the source code as well
+ pos = self.source.tell()
+ if not decoded:
+ self.encoding = detect_encoding(self.source.readline)
+ self.source.seek(pos)
+ self.code = self.source.read().decode(self.encoding)
+ self.source.seek(pos)
+ self.source = TextIOWrapper(self.source, self.encoding)
+ else:
+ self.encoding = None
+ self.code = self.source.read()
+ self.source.seek(pos)
+
+ # will be filled by tokenize()
+ self.tokens = None
+ # will be filled by parse()
+ self.parsetree = None
+ # will be filled by find_attr_docs()
+ self.attr_docs = None
+ self.tagorder = None
+ # will be filled by find_tags()
+ self.tags = None
+
+ def tokenize(self):
+ """Generate tokens from the source."""
+ if self.tokens is not None:
+ return
+ try:
+ self.tokens = list(tokenize.generate_tokens(self.source.readline))
+ except tokenize.TokenError, err:
+ raise PycodeError('tokenizing failed', err)
+ self.source.close()
+
+ def parse(self):
+ """Parse the generated source tokens."""
+ if self.parsetree is not None:
+ return
+ self.tokenize()
+ try:
+ self.parsetree = pydriver.parse_tokens(self.tokens)
+ except parse.ParseError, err:
+ raise PycodeError('parsing failed', err)
+
+ def find_attr_docs(self, scope=''):
+ """Find class and module-level attributes and their documentation."""
+ if self.attr_docs is not None:
+ return self.attr_docs
+ self.parse()
+ attr_visitor = AttrDocVisitor(number2name, scope, self.encoding)
+ attr_visitor.visit(self.parsetree)
+ self.attr_docs = attr_visitor.collected
+ self.tagorder = attr_visitor.tagorder
+ # now that we found everything we could in the tree, throw it away
+ # (it takes quite a bit of memory for large modules)
+ self.parsetree = None
+ return attr_visitor.collected
+
+ def find_tags(self):
+ """Find class, function and method definitions and their location."""
+ if self.tags is not None:
+ return self.tags
+ self.tokenize()
+ result = {}
+ namespace = []
+ stack = []
+ indent = 0
+ defline = False
+ expect_indent = False
+ def tokeniter(ignore = (token.COMMENT, token.NL)):
+ for tokentup in self.tokens:
+ if tokentup[0] not in ignore:
+ yield tokentup
+ tokeniter = tokeniter()
+ for type, tok, spos, epos, line in tokeniter:
+ if expect_indent:
+ if type != token.INDENT:
+ # no suite -- one-line definition
+ assert stack
+ dtype, fullname, startline, _ = stack.pop()
+ endline = epos[0]
+ namespace.pop()
+ result[fullname] = (dtype, startline, endline)
+ expect_indent = False
+ if tok in ('def', 'class'):
+ name = next(tokeniter)[1]
+ namespace.append(name)
+ fullname = '.'.join(namespace)
+ stack.append((tok, fullname, spos[0], indent))
+ defline = True
+ elif type == token.INDENT:
+ expect_indent = False
+ indent += 1
+ elif type == token.DEDENT:
+ indent -= 1
+ # if the stacklevel is the same as it was before the last
+ # def/class block, this dedent closes that block
+ if stack and indent == stack[-1][3]:
+ dtype, fullname, startline, _ = stack.pop()
+ endline = spos[0]
+ namespace.pop()
+ result[fullname] = (dtype, startline, endline)
+ elif type == token.NEWLINE:
+ # if this line contained a definition, expect an INDENT
+ # to start the suite; if there is no such INDENT
+ # it's a one-line definition
+ if defline:
+ defline = False
+ expect_indent = True
+ self.tags = result
+ return result
+
+
+if __name__ == '__main__':
+ import time, pprint
+ x0 = time.time()
+ #ma = ModuleAnalyzer.for_file(__file__.rstrip('c'), 'sphinx.builders.html')
+ ma = ModuleAnalyzer.for_file('sphinx/environment.py',
+ 'sphinx.environment')
+ ma.tokenize()
+ x1 = time.time()
+ ma.parse()
+ x2 = time.time()
+ #for (ns, name), doc in ma.find_attr_docs().iteritems():
+ # print '>>', ns, name
+ # print '\n'.join(doc)
+ pprint.pprint(ma.find_tags())
+ x3 = time.time()
+ #print nodes.nice_repr(ma.parsetree, number2name)
+ print "tokenizing %.4f, parsing %.4f, finding %.4f" % (x1-x0, x2-x1, x3-x2)
diff --git a/sphinx/pycode/nodes.py b/sphinx/pycode/nodes.py
new file mode 100644
index 0000000..8bba349
--- /dev/null
+++ b/sphinx/pycode/nodes.py
@@ -0,0 +1,207 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.pycode.nodes
+ ~~~~~~~~~~~~~~~~~~~
+
+ Parse tree node implementations.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+
+class BaseNode(object):
+ """
+ Node superclass for both terminal and nonterminal nodes.
+ """
+ parent = None
+
+ def _eq(self, other):
+ raise NotImplementedError
+
+ def __eq__(self, other):
+ if self.__class__ is not other.__class__:
+ return NotImplemented
+ return self._eq(other)
+
+ def __ne__(self, other):
+ if self.__class__ is not other.__class__:
+ return NotImplemented
+ return not self._eq(other)
+
+ __hash__ = None
+
+ def get_prev_sibling(self):
+ """Return previous child in parent's children, or None."""
+ if self.parent is None:
+ return None
+ for i, child in enumerate(self.parent.children):
+ if child is self:
+ if i == 0:
+ return None
+ return self.parent.children[i-1]
+
+ def get_next_sibling(self):
+ """Return next child in parent's children, or None."""
+ if self.parent is None:
+ return None
+ for i, child in enumerate(self.parent.children):
+ if child is self:
+ try:
+ return self.parent.children[i+1]
+ except IndexError:
+ return None
+
+ def get_prev_leaf(self):
+ """Return the leaf node that precedes this node in the parse tree."""
+ def last_child(node):
+ if isinstance(node, Leaf):
+ return node
+ elif not node.children:
+ return None
+ else:
+ return last_child(node.children[-1])
+ if self.parent is None:
+ return None
+ prev = self.get_prev_sibling()
+ if isinstance(prev, Leaf):
+ return prev
+ elif prev is not None:
+ return last_child(prev)
+ return self.parent.get_prev_leaf()
+
+ def get_next_leaf(self):
+ """Return self if leaf, otherwise the leaf node that succeeds this
+ node in the parse tree.
+ """
+ node = self
+ while not isinstance(node, Leaf):
+ assert node.children
+ node = node.children[0]
+ return node
+
+ def get_lineno(self):
+ """Return the line number which generated the invocant node."""
+ return self.get_next_leaf().lineno
+
+ def get_prefix(self):
+ """Return the prefix of the next leaf node."""
+ # only leaves carry a prefix
+ return self.get_next_leaf().prefix
+
+
+class Node(BaseNode):
+ """
+ Node implementation for nonterminals.
+ """
+
+ def __init__(self, type, children, context=None):
+ # type of nonterminals is >= 256
+ # assert type >= 256, type
+ self.type = type
+ self.children = list(children)
+ for ch in self.children:
+ # assert ch.parent is None, repr(ch)
+ ch.parent = self
+
+ def __repr__(self):
+ return '%s(%s, %r)' % (self.__class__.__name__,
+ self.type, self.children)
+
+ def __str__(self):
+ """This reproduces the input source exactly."""
+ return ''.join(map(str, self.children))
+
+ def _eq(self, other):
+ return (self.type, self.children) == (other.type, other.children)
+
+ # support indexing the node directly instead of .children
+
+ def __getitem__(self, index):
+ return self.children[index]
+
+ def __iter__(self):
+ return iter(self.children)
+
+ def __len__(self):
+ return len(self.children)
+
+
+class Leaf(BaseNode):
+ """
+ Node implementation for leaf nodes (terminals).
+ """
+ prefix = '' # Whitespace and comments preceding this token in the input
+ lineno = 0 # Line where this token starts in the input
+ column = 0 # Column where this token tarts in the input
+
+ def __init__(self, type, value, context=None):
+ # type of terminals is below 256
+ # assert 0 <= type < 256, type
+ self.type = type
+ self.value = value
+ if context is not None:
+ self.prefix, (self.lineno, self.column) = context
+
+ def __repr__(self):
+ return '%s(%r, %r, %r)' % (self.__class__.__name__,
+ self.type, self.value, self.prefix)
+
+ def __str__(self):
+ """This reproduces the input source exactly."""
+ return self.prefix + str(self.value)
+
+ def _eq(self, other):
+ """Compares two nodes for equality."""
+ return (self.type, self.value) == (other.type, other.value)
+
+
+def convert(grammar, raw_node):
+ """Convert raw node to a Node or Leaf instance."""
+ type, value, context, children = raw_node
+ if children or type in grammar.number2symbol:
+ # If there's exactly one child, return that child instead of
+ # creating a new node.
+ if len(children) == 1:
+ return children[0]
+ return Node(type, children, context=context)
+ else:
+ return Leaf(type, value, context=context)
+
+
+def nice_repr(node, number2name, prefix=False):
+ def _repr(node):
+ if isinstance(node, Leaf):
+ return "%s(%r)" % (number2name[node.type], node.value)
+ else:
+ return "%s(%s)" % (number2name[node.type],
+ ', '.join(map(_repr, node.children)))
+ def _prepr(node):
+ if isinstance(node, Leaf):
+ return "%s(%r, %r)" % (number2name[node.type],
+ node.prefix, node.value)
+ else:
+ return "%s(%s)" % (number2name[node.type],
+ ', '.join(map(_prepr, node.children)))
+ return (prefix and _prepr or _repr)(node)
+
+
+class NodeVisitor(object):
+ def __init__(self, number2name, *args):
+ self.number2name = number2name
+ self.init(*args)
+
+ def init(self, *args):
+ pass
+
+ def visit(self, node):
+ """Visit a node."""
+ method = 'visit_' + self.number2name[node.type]
+ visitor = getattr(self, method, self.generic_visit)
+ return visitor(node)
+
+ def generic_visit(self, node):
+ """Called if no explicit visitor function exists for a node."""
+ if isinstance(node, Node):
+ for child in node:
+ self.visit(child)
diff --git a/sphinx/pycode/pgen2/__init__.py b/sphinx/pycode/pgen2/__init__.py
new file mode 100644
index 0000000..af39048
--- /dev/null
+++ b/sphinx/pycode/pgen2/__init__.py
@@ -0,0 +1,4 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""The pgen2 package."""
diff --git a/sphinx/pycode/pgen2/driver.py b/sphinx/pycode/pgen2/driver.py
new file mode 100644
index 0000000..422671d
--- /dev/null
+++ b/sphinx/pycode/pgen2/driver.py
@@ -0,0 +1,148 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+# Modifications:
+# Copyright 2006 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Parser driver.
+
+This provides a high-level interface to parse a file into a syntax tree.
+
+"""
+
+__author__ = "Guido van Rossum <guido at python.org>"
+
+__all__ = ["Driver", "load_grammar"]
+
+# Python imports
+import os
+import logging
+
+import sphinx
+
+# Pgen imports
+from sphinx.pycode.pgen2 import grammar, parse, token, tokenize, pgen
+
+
+class Driver(object):
+
+ def __init__(self, grammar, convert=None, logger=None):
+ self.grammar = grammar
+ if logger is None:
+ logger = logging.getLogger()
+ self.logger = logger
+ self.convert = convert
+
+ def parse_tokens(self, tokens, debug=False):
+ """Parse a series of tokens and return the syntax tree."""
+ # X X X Move the prefix computation into a wrapper around tokenize.
+ p = parse.Parser(self.grammar, self.convert)
+ p.setup()
+ lineno = 1
+ column = 0
+ type = value = start = end = line_text = None
+ prefix = ""
+ opmap = grammar.opmap
+ for type, value, start, end, line_text in tokens:
+ if start != (lineno, column):
+ assert (lineno, column) <= start, ((lineno, column), start)
+ s_lineno, s_column = start
+ if lineno < s_lineno:
+ prefix += "\n" * (s_lineno - lineno)
+ lineno = s_lineno
+ column = 0
+ if column < s_column:
+ prefix += line_text[column:s_column]
+ column = s_column
+ if type in (tokenize.COMMENT, tokenize.NL):
+ prefix += value
+ lineno, column = end
+ if value.endswith("\n"):
+ lineno += 1
+ column = 0
+ continue
+ if type == token.OP:
+ type = opmap[value]
+ # if debug:
+ # self.logger.debug("%s %r (prefix=%r)",
+ # token.tok_name[type], value, prefix)
+ if p.addtoken(type, value, (prefix, start)):
+ # if debug:
+ # self.logger.debug("Stop.")
+ break
+ prefix = ""
+ lineno, column = end
+ if value.endswith("\n"):
+ lineno += 1
+ column = 0
+ else:
+ # We never broke out -- EOF is too soon (how can this happen???)
+ raise parse.ParseError("incomplete input", type, value, line_text)
+ return p.rootnode
+
+ def parse_stream_raw(self, stream, debug=False):
+ """Parse a stream and return the syntax tree."""
+ tokens = tokenize.generate_tokens(stream.readline)
+ return self.parse_tokens(tokens, debug)
+
+ def parse_stream(self, stream, debug=False):
+ """Parse a stream and return the syntax tree."""
+ return self.parse_stream_raw(stream, debug)
+
+ def parse_file(self, filename, debug=False):
+ """Parse a file and return the syntax tree."""
+ stream = open(filename)
+ try:
+ return self.parse_stream(stream, debug)
+ finally:
+ stream.close()
+
+ def parse_string(self, text, debug=False):
+ """Parse a string and return the syntax tree."""
+ tokens = tokenize.generate_tokens(generate_lines(text).next)
+ return self.parse_tokens(tokens, debug)
+
+
+def generate_lines(text):
+ """Generator that behaves like readline without using StringIO."""
+ for line in text.splitlines(True):
+ yield line
+ while True:
+ yield ""
+
+
+def load_grammar(gt="Grammar.txt", gp=None,
+ save=True, force=False, logger=None):
+ """Load the grammar (maybe from a pickle)."""
+ if logger is None:
+ logger = logging.getLogger()
+ if gp is None:
+ head, tail = os.path.splitext(gt)
+ if tail == ".txt":
+ tail = ""
+ # embed Sphinx major version for the case we ever change the grammar...
+ gp = head + tail + "-sphinx" + \
+ ".".join(map(str, sphinx.version_info[:2])) + ".pickle"
+ if force or not _newer(gp, gt):
+ logger.info("Generating grammar tables from %s", gt)
+ g = pgen.generate_grammar(gt)
+ if save:
+ logger.info("Writing grammar tables to %s", gp)
+ try:
+ g.dump(gp)
+ except IOError, e:
+ logger.info("Writing failed:"+str(e))
+ else:
+ g = grammar.Grammar()
+ g.load(gp)
+ return g
+
+
+def _newer(a, b):
+ """Inquire whether file a was written since file b."""
+ if not os.path.exists(a):
+ return False
+ if not os.path.exists(b):
+ return True
+ return os.path.getmtime(a) >= os.path.getmtime(b)
diff --git a/sphinx/pycode/pgen2/grammar.py b/sphinx/pycode/pgen2/grammar.py
new file mode 100644
index 0000000..01d8434
--- /dev/null
+++ b/sphinx/pycode/pgen2/grammar.py
@@ -0,0 +1,172 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""This module defines the data structures used to represent a grammar.
+
+These are a bit arcane because they are derived from the data
+structures used by Python's 'pgen' parser generator.
+
+There's also a table here mapping operators to their names in the
+token module; the Python tokenize module reports all operators as the
+fallback token code OP, but the parser needs the actual token code.
+
+"""
+
+# Python imports
+import pickle
+
+# Local imports
+from sphinx.pycode.pgen2 import token
+
+
+class Grammar(object):
+ """Pgen parsing tables tables conversion class.
+
+ Once initialized, this class supplies the grammar tables for the
+ parsing engine implemented by parse.py. The parsing engine
+ accesses the instance variables directly. The class here does not
+ provide initialization of the tables; several subclasses exist to
+ do this (see the conv and pgen modules).
+
+ The load() method reads the tables from a pickle file, which is
+ much faster than the other ways offered by subclasses. The pickle
+ file is written by calling dump() (after loading the grammar
+ tables using a subclass). The report() method prints a readable
+ representation of the tables to stdout, for debugging.
+
+ The instance variables are as follows:
+
+ symbol2number -- a dict mapping symbol names to numbers. Symbol
+ numbers are always 256 or higher, to distinguish
+ them from token numbers, which are between 0 and
+ 255 (inclusive).
+
+ number2symbol -- a dict mapping numbers to symbol names;
+ these two are each other's inverse.
+
+ states -- a list of DFAs, where each DFA is a list of
+ states, each state is is a list of arcs, and each
+ arc is a (i, j) pair where i is a label and j is
+ a state number. The DFA number is the index into
+ this list. (This name is slightly confusing.)
+ Final states are represented by a special arc of
+ the form (0, j) where j is its own state number.
+
+ dfas -- a dict mapping symbol numbers to (DFA, first)
+ pairs, where DFA is an item from the states list
+ above, and first is a set of tokens that can
+ begin this grammar rule (represented by a dict
+ whose values are always 1).
+
+ labels -- a list of (x, y) pairs where x is either a token
+ number or a symbol number, and y is either None
+ or a string; the strings are keywords. The label
+ number is the index in this list; label numbers
+ are used to mark state transitions (arcs) in the
+ DFAs.
+
+ start -- the number of the grammar's start symbol.
+
+ keywords -- a dict mapping keyword strings to arc labels.
+
+ tokens -- a dict mapping token numbers to arc labels.
+
+ """
+
+ def __init__(self):
+ self.symbol2number = {}
+ self.number2symbol = {}
+ self.states = []
+ self.dfas = {}
+ self.labels = [(0, "EMPTY")]
+ self.keywords = {}
+ self.tokens = {}
+ self.symbol2label = {}
+ self.start = 256
+
+ def dump(self, filename):
+ """Dump the grammar tables to a pickle file."""
+ f = open(filename, "wb")
+ pickle.dump(self.__dict__, f, 2)
+ f.close()
+
+ def load(self, filename):
+ """Load the grammar tables from a pickle file."""
+ f = open(filename, "rb")
+ d = pickle.load(f)
+ f.close()
+ self.__dict__.update(d)
+
+ def report(self):
+ """Dump the grammar tables to standard output, for debugging."""
+ from pprint import pprint
+ print "s2n"
+ pprint(self.symbol2number)
+ print "n2s"
+ pprint(self.number2symbol)
+ print "states"
+ pprint(self.states)
+ print "dfas"
+ pprint(self.dfas)
+ print "labels"
+ pprint(self.labels)
+ print "start", self.start
+
+
+# Map from operator to number (since tokenize doesn't do this)
+
+opmap_raw = """
+( LPAR
+) RPAR
+[ LSQB
+] RSQB
+: COLON
+, COMMA
+; SEMI
++ PLUS
+- MINUS
+* STAR
+/ SLASH
+| VBAR
+& AMPER
+< LESS
+> GREATER
+= EQUAL
+. DOT
+% PERCENT
+` BACKQUOTE
+{ LBRACE
+} RBRACE
+@ AT
+== EQEQUAL
+!= NOTEQUAL
+<> NOTEQUAL
+<= LESSEQUAL
+>= GREATEREQUAL
+~ TILDE
+^ CIRCUMFLEX
+<< LEFTSHIFT
+>> RIGHTSHIFT
+** DOUBLESTAR
++= PLUSEQUAL
+-= MINEQUAL
+*= STAREQUAL
+/= SLASHEQUAL
+%= PERCENTEQUAL
+&= AMPEREQUAL
+|= VBAREQUAL
+^= CIRCUMFLEXEQUAL
+<<= LEFTSHIFTEQUAL
+>>= RIGHTSHIFTEQUAL
+**= DOUBLESTAREQUAL
+// DOUBLESLASH
+//= DOUBLESLASHEQUAL
+-> RARROW
+... ELLIPSIS
+"""
+
+opmap = {}
+for line in opmap_raw.splitlines():
+ if line:
+ op, name = line.split()
+ opmap[op] = getattr(token, name)
diff --git a/sphinx/pycode/pgen2/literals.py b/sphinx/pycode/pgen2/literals.py
new file mode 100644
index 0000000..d489370
--- /dev/null
+++ b/sphinx/pycode/pgen2/literals.py
@@ -0,0 +1,96 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+# Extended to handle raw and unicode literals by Georg Brandl.
+
+"""Safely evaluate Python string literals without using eval()."""
+
+import re
+
+simple_escapes = {"a": "\a",
+ "b": "\b",
+ "f": "\f",
+ "n": "\n",
+ "r": "\r",
+ "t": "\t",
+ "v": "\v",
+ "'": "'",
+ '"': '"',
+ "\\": "\\"}
+
+def convert_hex(x, n):
+ if len(x) < n+1:
+ raise ValueError("invalid hex string escape ('\\%s')" % x)
+ try:
+ return int(x[1:], 16)
+ except ValueError:
+ raise ValueError("invalid hex string escape ('\\%s')" % x)
+
+def escape(m):
+ all, tail = m.group(0, 1)
+ assert all.startswith("\\")
+ esc = simple_escapes.get(tail)
+ if esc is not None:
+ return esc
+ elif tail.startswith("x"):
+ return chr(convert_hex(tail, 2))
+ elif tail.startswith('u'):
+ return unichr(convert_hex(tail, 4))
+ elif tail.startswith('U'):
+ return unichr(convert_hex(tail, 8))
+ elif tail.startswith('N'):
+ import unicodedata
+ try:
+ return unicodedata.lookup(tail[1:-1])
+ except KeyError:
+ raise ValueError("undefined character name %r" % tail[1:-1])
+ else:
+ try:
+ return chr(int(tail, 8))
+ except ValueError:
+ raise ValueError("invalid octal string escape ('\\%s')" % tail)
+
+def escaperaw(m):
+ all, tail = m.group(0, 1)
+ if tail.startswith('u'):
+ return unichr(convert_hex(tail, 4))
+ elif tail.startswith('U'):
+ return unichr(convert_hex(tail, 8))
+ else:
+ return all
+
+escape_re = re.compile(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3})")
+uni_escape_re = re.compile(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3}|"
+ r"u[0-9a-fA-F]{0,4}|U[0-9a-fA-F]{0,8}|N\{.+?\})")
+
+def evalString(s, encoding=None):
+ regex = escape_re
+ repl = escape
+ if encoding and not isinstance(s, unicode):
+ s = s.decode(encoding)
+ if s.startswith('u') or s.startswith('U'):
+ regex = uni_escape_re
+ s = s[1:]
+ if s.startswith('r') or s.startswith('R'):
+ repl = escaperaw
+ s = s[1:]
+ assert s.startswith("'") or s.startswith('"'), repr(s[:1])
+ q = s[0]
+ if s[:3] == q*3:
+ q = q*3
+ assert s.endswith(q), repr(s[-len(q):])
+ assert len(s) >= 2*len(q)
+ s = s[len(q):-len(q)]
+ return regex.sub(repl, s)
+
+def test():
+ for i in range(256):
+ c = chr(i)
+ s = repr(c)
+ e = evalString(s)
+ if e != c:
+ print i, c, s, e
+
+
+if __name__ == "__main__":
+ test()
diff --git a/sphinx/pycode/pgen2/parse.py b/sphinx/pycode/pgen2/parse.py
new file mode 100644
index 0000000..60eec05
--- /dev/null
+++ b/sphinx/pycode/pgen2/parse.py
@@ -0,0 +1,201 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Parser engine for the grammar tables generated by pgen.
+
+The grammar table must be loaded first.
+
+See Parser/parser.c in the Python distribution for additional info on
+how this parsing engine works.
+
+"""
+
+# Local imports
+from sphinx.pycode.pgen2 import token
+
+class ParseError(Exception):
+ """Exception to signal the parser is stuck."""
+
+ def __init__(self, msg, type, value, context):
+ Exception.__init__(self, "%s: type=%r, value=%r, context=%r" %
+ (msg, type, value, context))
+ self.msg = msg
+ self.type = type
+ self.value = value
+ self.context = context
+
+class Parser(object):
+ """Parser engine.
+
+ The proper usage sequence is:
+
+ p = Parser(grammar, [converter]) # create instance
+ p.setup([start]) # prepare for parsing
+ <for each input token>:
+ if p.addtoken(...): # parse a token; may raise ParseError
+ break
+ root = p.rootnode # root of abstract syntax tree
+
+ A Parser instance may be reused by calling setup() repeatedly.
+
+ A Parser instance contains state pertaining to the current token
+ sequence, and should not be used concurrently by different threads
+ to parse separate token sequences.
+
+ See driver.py for how to get input tokens by tokenizing a file or
+ string.
+
+ Parsing is complete when addtoken() returns True; the root of the
+ abstract syntax tree can then be retrieved from the rootnode
+ instance variable. When a syntax error occurs, addtoken() raises
+ the ParseError exception. There is no error recovery; the parser
+ cannot be used after a syntax error was reported (but it can be
+ reinitialized by calling setup()).
+
+ """
+
+ def __init__(self, grammar, convert=None):
+ """Constructor.
+
+ The grammar argument is a grammar.Grammar instance; see the
+ grammar module for more information.
+
+ The parser is not ready yet for parsing; you must call the
+ setup() method to get it started.
+
+ The optional convert argument is a function mapping concrete
+ syntax tree nodes to abstract syntax tree nodes. If not
+ given, no conversion is done and the syntax tree produced is
+ the concrete syntax tree. If given, it must be a function of
+ two arguments, the first being the grammar (a grammar.Grammar
+ instance), and the second being the concrete syntax tree node
+ to be converted. The syntax tree is converted from the bottom
+ up.
+
+ A concrete syntax tree node is a (type, value, context, nodes)
+ tuple, where type is the node type (a token or symbol number),
+ value is None for symbols and a string for tokens, context is
+ None or an opaque value used for error reporting (typically a
+ (lineno, offset) pair), and nodes is a list of children for
+ symbols, and None for tokens.
+
+ An abstract syntax tree node may be anything; this is entirely
+ up to the converter function.
+
+ """
+ self.grammar = grammar
+ self.convert = convert or (lambda grammar, node: node)
+
+ def setup(self, start=None):
+ """Prepare for parsing.
+
+ This *must* be called before starting to parse.
+
+ The optional argument is an alternative start symbol; it
+ defaults to the grammar's start symbol.
+
+ You can use a Parser instance to parse any number of programs;
+ each time you call setup() the parser is reset to an initial
+ state determined by the (implicit or explicit) start symbol.
+
+ """
+ if start is None:
+ start = self.grammar.start
+ # Each stack entry is a tuple: (dfa, state, node).
+ # A node is a tuple: (type, value, context, children),
+ # where children is a list of nodes or None, and context may be None.
+ newnode = (start, None, None, [])
+ stackentry = (self.grammar.dfas[start], 0, newnode)
+ self.stack = [stackentry]
+ self.rootnode = None
+ self.used_names = set() # Aliased to self.rootnode.used_names in pop()
+
+ def addtoken(self, type, value, context):
+ """Add a token; return True iff this is the end of the program."""
+ # Map from token to label
+ ilabel = self.classify(type, value, context)
+ # Loop until the token is shifted; may raise exceptions
+ while True:
+ dfa, state, node = self.stack[-1]
+ states, first = dfa
+ arcs = states[state]
+ # Look for a state with this label
+ for i, newstate in arcs:
+ t, v = self.grammar.labels[i]
+ if ilabel == i:
+ # Look it up in the list of labels
+ assert t < 256
+ # Shift a token; we're done with it
+ self.shift(type, value, newstate, context)
+ # Pop while we are in an accept-only state
+ state = newstate
+ while states[state] == [(0, state)]:
+ self.pop()
+ if not self.stack:
+ # Done parsing!
+ return True
+ dfa, state, node = self.stack[-1]
+ states, first = dfa
+ # Done with this token
+ return False
+ elif t >= 256:
+ # See if it's a symbol and if we're in its first set
+ itsdfa = self.grammar.dfas[t]
+ itsstates, itsfirst = itsdfa
+ if ilabel in itsfirst:
+ # Push a symbol
+ self.push(t, self.grammar.dfas[t], newstate, context)
+ break # To continue the outer while loop
+ else:
+ if (0, state) in arcs:
+ # An accepting state, pop it and try something else
+ self.pop()
+ if not self.stack:
+ # Done parsing, but another token is input
+ raise ParseError("too much input",
+ type, value, context)
+ else:
+ # No success finding a transition
+ raise ParseError("bad input", type, value, context)
+
+ def classify(self, type, value, context):
+ """Turn a token into a label. (Internal)"""
+ if type == token.NAME:
+ # Keep a listing of all used names
+ self.used_names.add(value)
+ # Check for reserved words
+ ilabel = self.grammar.keywords.get(value)
+ if ilabel is not None:
+ return ilabel
+ ilabel = self.grammar.tokens.get(type)
+ if ilabel is None:
+ raise ParseError("bad token", type, value, context)
+ return ilabel
+
+ def shift(self, type, value, newstate, context):
+ """Shift a token. (Internal)"""
+ dfa, state, node = self.stack[-1]
+ newnode = (type, value, context, None)
+ newnode = self.convert(self.grammar, newnode)
+ if newnode is not None:
+ node[-1].append(newnode)
+ self.stack[-1] = (dfa, newstate, node)
+
+ def push(self, type, newdfa, newstate, context):
+ """Push a nonterminal. (Internal)"""
+ dfa, state, node = self.stack[-1]
+ newnode = (type, None, context, [])
+ self.stack[-1] = (dfa, newstate, node)
+ self.stack.append((newdfa, 0, newnode))
+
+ def pop(self):
+ """Pop a nonterminal. (Internal)"""
+ popdfa, popstate, popnode = self.stack.pop()
+ newnode = self.convert(self.grammar, popnode)
+ if newnode is not None:
+ if self.stack:
+ dfa, state, node = self.stack[-1]
+ node[-1].append(newnode)
+ else:
+ self.rootnode = newnode
+ self.rootnode.used_names = self.used_names
diff --git a/sphinx/pycode/pgen2/pgen.py b/sphinx/pycode/pgen2/pgen.py
new file mode 100644
index 0000000..0a04447
--- /dev/null
+++ b/sphinx/pycode/pgen2/pgen.py
@@ -0,0 +1,384 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+# Pgen imports
+from sphinx.pycode.pgen2 import grammar, token, tokenize
+
+class PgenGrammar(grammar.Grammar):
+ pass
+
+class ParserGenerator(object):
+
+ def __init__(self, filename, stream=None):
+ close_stream = None
+ if stream is None:
+ stream = open(filename)
+ close_stream = stream.close
+ self.filename = filename
+ self.stream = stream
+ self.generator = tokenize.generate_tokens(stream.readline)
+ self.gettoken() # Initialize lookahead
+ self.dfas, self.startsymbol = self.parse()
+ if close_stream is not None:
+ close_stream()
+ self.first = {} # map from symbol name to set of tokens
+ self.addfirstsets()
+
+ def make_grammar(self):
+ c = PgenGrammar()
+ names = self.dfas.keys()
+ names.sort()
+ names.remove(self.startsymbol)
+ names.insert(0, self.startsymbol)
+ for name in names:
+ i = 256 + len(c.symbol2number)
+ c.symbol2number[name] = i
+ c.number2symbol[i] = name
+ for name in names:
+ dfa = self.dfas[name]
+ states = []
+ for state in dfa:
+ arcs = []
+ for label, next in state.arcs.iteritems():
+ arcs.append((self.make_label(c, label), dfa.index(next)))
+ if state.isfinal:
+ arcs.append((0, dfa.index(state)))
+ states.append(arcs)
+ c.states.append(states)
+ c.dfas[c.symbol2number[name]] = (states, self.make_first(c, name))
+ c.start = c.symbol2number[self.startsymbol]
+ return c
+
+ def make_first(self, c, name):
+ rawfirst = self.first[name]
+ first = {}
+ for label in rawfirst:
+ ilabel = self.make_label(c, label)
+ ##assert ilabel not in first # X X X failed on <> ... !=
+ first[ilabel] = 1
+ return first
+
+ def make_label(self, c, label):
+ # X X X Maybe this should be a method on a subclass of converter?
+ ilabel = len(c.labels)
+ if label[0].isalpha():
+ # Either a symbol name or a named token
+ if label in c.symbol2number:
+ # A symbol name (a non-terminal)
+ if label in c.symbol2label:
+ return c.symbol2label[label]
+ else:
+ c.labels.append((c.symbol2number[label], None))
+ c.symbol2label[label] = ilabel
+ return ilabel
+ else:
+ # A named token (NAME, NUMBER, STRING)
+ itoken = getattr(token, label, None)
+ assert isinstance(itoken, int), label
+ assert itoken in token.tok_name, label
+ if itoken in c.tokens:
+ return c.tokens[itoken]
+ else:
+ c.labels.append((itoken, None))
+ c.tokens[itoken] = ilabel
+ return ilabel
+ else:
+ # Either a keyword or an operator
+ assert label[0] in ('"', "'"), label
+ value = eval(label)
+ if value[0].isalpha():
+ # A keyword
+ if value in c.keywords:
+ return c.keywords[value]
+ else:
+ c.labels.append((token.NAME, value))
+ c.keywords[value] = ilabel
+ return ilabel
+ else:
+ # An operator (any non-numeric token)
+ itoken = grammar.opmap[value] # Fails if unknown token
+ if itoken in c.tokens:
+ return c.tokens[itoken]
+ else:
+ c.labels.append((itoken, None))
+ c.tokens[itoken] = ilabel
+ return ilabel
+
+ def addfirstsets(self):
+ names = self.dfas.keys()
+ names.sort()
+ for name in names:
+ if name not in self.first:
+ self.calcfirst(name)
+ #print name, self.first[name].keys()
+
+ def calcfirst(self, name):
+ dfa = self.dfas[name]
+ self.first[name] = None # dummy to detect left recursion
+ state = dfa[0]
+ totalset = {}
+ overlapcheck = {}
+ for label, next in state.arcs.iteritems():
+ if label in self.dfas:
+ if label in self.first:
+ fset = self.first[label]
+ if fset is None:
+ raise ValueError("recursion for rule %r" % name)
+ else:
+ self.calcfirst(label)
+ fset = self.first[label]
+ totalset.update(fset)
+ overlapcheck[label] = fset
+ else:
+ totalset[label] = 1
+ overlapcheck[label] = {label: 1}
+ inverse = {}
+ for label, itsfirst in overlapcheck.iteritems():
+ for symbol in itsfirst:
+ if symbol in inverse:
+ raise ValueError("rule %s is ambiguous; %s is in the"
+ " first sets of %s as well as %s" %
+ (name, symbol, label, inverse[symbol]))
+ inverse[symbol] = label
+ self.first[name] = totalset
+
+ def parse(self):
+ dfas = {}
+ startsymbol = None
+ # MSTART: (NEWLINE | RULE)* ENDMARKER
+ while self.type != token.ENDMARKER:
+ while self.type == token.NEWLINE:
+ self.gettoken()
+ # RULE: NAME ':' RHS NEWLINE
+ name = self.expect(token.NAME)
+ self.expect(token.OP, ":")
+ a, z = self.parse_rhs()
+ self.expect(token.NEWLINE)
+ #self.dump_nfa(name, a, z)
+ dfa = self.make_dfa(a, z)
+ #self.dump_dfa(name, dfa)
+ #oldlen = len(dfa)
+ self.simplify_dfa(dfa)
+ #newlen = len(dfa)
+ dfas[name] = dfa
+ #print name, oldlen, newlen
+ if startsymbol is None:
+ startsymbol = name
+ return dfas, startsymbol
+
+ def make_dfa(self, start, finish):
+ # To turn an NFA into a DFA, we define the states of the DFA
+ # to correspond to *sets* of states of the NFA. Then do some
+ # state reduction. Let's represent sets as dicts with 1 for
+ # values.
+ assert isinstance(start, NFAState)
+ assert isinstance(finish, NFAState)
+ def closure(state):
+ base = {}
+ addclosure(state, base)
+ return base
+ def addclosure(state, base):
+ assert isinstance(state, NFAState)
+ if state in base:
+ return
+ base[state] = 1
+ for label, next in state.arcs:
+ if label is None:
+ addclosure(next, base)
+ states = [DFAState(closure(start), finish)]
+ for state in states: # NB states grows while we're iterating
+ arcs = {}
+ for nfastate in state.nfaset:
+ for label, next in nfastate.arcs:
+ if label is not None:
+ addclosure(next, arcs.setdefault(label, {}))
+ for label, nfaset in arcs.iteritems():
+ for st in states:
+ if st.nfaset == nfaset:
+ break
+ else:
+ st = DFAState(nfaset, finish)
+ states.append(st)
+ state.addarc(st, label)
+ return states # List of DFAState instances; first one is start
+
+ def dump_nfa(self, name, start, finish):
+ print "Dump of NFA for", name
+ todo = [start]
+ for i, state in enumerate(todo):
+ print " State", i, state is finish and "(final)" or ""
+ for label, next in state.arcs:
+ if next in todo:
+ j = todo.index(next)
+ else:
+ j = len(todo)
+ todo.append(next)
+ if label is None:
+ print " -> %d" % j
+ else:
+ print " %s -> %d" % (label, j)
+
+ def dump_dfa(self, name, dfa):
+ print "Dump of DFA for", name
+ for i, state in enumerate(dfa):
+ print " State", i, state.isfinal and "(final)" or ""
+ for label, next in state.arcs.iteritems():
+ print " %s -> %d" % (label, dfa.index(next))
+
+ def simplify_dfa(self, dfa):
+ # This is not theoretically optimal, but works well enough.
+ # Algorithm: repeatedly look for two states that have the same
+ # set of arcs (same labels pointing to the same nodes) and
+ # unify them, until things stop changing.
+
+ # dfa is a list of DFAState instances
+ changes = True
+ while changes:
+ changes = False
+ for i, state_i in enumerate(dfa):
+ for j in range(i+1, len(dfa)):
+ state_j = dfa[j]
+ if state_i == state_j:
+ #print " unify", i, j
+ del dfa[j]
+ for state in dfa:
+ state.unifystate(state_j, state_i)
+ changes = True
+ break
+
+ def parse_rhs(self):
+ # RHS: ALT ('|' ALT)*
+ a, z = self.parse_alt()
+ if self.value != "|":
+ return a, z
+ else:
+ aa = NFAState()
+ zz = NFAState()
+ aa.addarc(a)
+ z.addarc(zz)
+ while self.value == "|":
+ self.gettoken()
+ a, z = self.parse_alt()
+ aa.addarc(a)
+ z.addarc(zz)
+ return aa, zz
+
+ def parse_alt(self):
+ # ALT: ITEM+
+ a, b = self.parse_item()
+ while (self.value in ("(", "[") or
+ self.type in (token.NAME, token.STRING)):
+ c, d = self.parse_item()
+ b.addarc(c)
+ b = d
+ return a, b
+
+ def parse_item(self):
+ # ITEM: '[' RHS ']' | ATOM ['+' | '*']
+ if self.value == "[":
+ self.gettoken()
+ a, z = self.parse_rhs()
+ self.expect(token.OP, "]")
+ a.addarc(z)
+ return a, z
+ else:
+ a, z = self.parse_atom()
+ value = self.value
+ if value not in ("+", "*"):
+ return a, z
+ self.gettoken()
+ z.addarc(a)
+ if value == "+":
+ return a, z
+ else:
+ return a, a
+
+ def parse_atom(self):
+ # ATOM: '(' RHS ')' | NAME | STRING
+ if self.value == "(":
+ self.gettoken()
+ a, z = self.parse_rhs()
+ self.expect(token.OP, ")")
+ return a, z
+ elif self.type in (token.NAME, token.STRING):
+ a = NFAState()
+ z = NFAState()
+ a.addarc(z, self.value)
+ self.gettoken()
+ return a, z
+ else:
+ self.raise_error("expected (...) or NAME or STRING, got %s/%s",
+ self.type, self.value)
+
+ def expect(self, type, value=None):
+ if self.type != type or (value is not None and self.value != value):
+ self.raise_error("expected %s/%s, got %s/%s",
+ type, value, self.type, self.value)
+ value = self.value
+ self.gettoken()
+ return value
+
+ def gettoken(self):
+ tup = self.generator.next()
+ while tup[0] in (tokenize.COMMENT, tokenize.NL):
+ tup = self.generator.next()
+ self.type, self.value, self.begin, self.end, self.line = tup
+ #print token.tok_name[self.type], repr(self.value)
+
+ def raise_error(self, msg, *args):
+ if args:
+ try:
+ msg = msg % args
+ except:
+ msg = " ".join([msg] + map(str, args))
+ raise SyntaxError(msg, (self.filename, self.end[0],
+ self.end[1], self.line))
+
+class NFAState(object):
+
+ def __init__(self):
+ self.arcs = [] # list of (label, NFAState) pairs
+
+ def addarc(self, next, label=None):
+ assert label is None or isinstance(label, str)
+ assert isinstance(next, NFAState)
+ self.arcs.append((label, next))
+
+class DFAState(object):
+
+ def __init__(self, nfaset, final):
+ assert isinstance(nfaset, dict)
+ assert isinstance(iter(nfaset).next(), NFAState)
+ assert isinstance(final, NFAState)
+ self.nfaset = nfaset
+ self.isfinal = final in nfaset
+ self.arcs = {} # map from label to DFAState
+
+ def addarc(self, next, label):
+ assert isinstance(label, str)
+ assert label not in self.arcs
+ assert isinstance(next, DFAState)
+ self.arcs[label] = next
+
+ def unifystate(self, old, new):
+ for label, next in self.arcs.iteritems():
+ if next is old:
+ self.arcs[label] = new
+
+ def __eq__(self, other):
+ # Equality test -- ignore the nfaset instance variable
+ assert isinstance(other, DFAState)
+ if self.isfinal != other.isfinal:
+ return False
+ # Can't just return self.arcs == other.arcs, because that
+ # would invoke this method recursively, with cycles...
+ if len(self.arcs) != len(other.arcs):
+ return False
+ for label, next in self.arcs.iteritems():
+ if next is not other.arcs.get(label):
+ return False
+ return True
+
+def generate_grammar(filename="Grammar.txt"):
+ p = ParserGenerator(filename)
+ return p.make_grammar()
diff --git a/sphinx/pycode/pgen2/token.py b/sphinx/pycode/pgen2/token.py
new file mode 100755
index 0000000..56a40ce
--- /dev/null
+++ b/sphinx/pycode/pgen2/token.py
@@ -0,0 +1,83 @@
+#! /usr/bin/env python
+
+"""Token constants (from "token.h")."""
+
+# Taken from Python (r53757) and modified to include some tokens
+# originally monkeypatched in by pgen2.tokenize
+
+#--start constants--
+ENDMARKER = 0
+NAME = 1
+NUMBER = 2
+STRING = 3
+NEWLINE = 4
+INDENT = 5
+DEDENT = 6
+LPAR = 7
+RPAR = 8
+LSQB = 9
+RSQB = 10
+COLON = 11
+COMMA = 12
+SEMI = 13
+PLUS = 14
+MINUS = 15
+STAR = 16
+SLASH = 17
+VBAR = 18
+AMPER = 19
+LESS = 20
+GREATER = 21
+EQUAL = 22
+DOT = 23
+PERCENT = 24
+BACKQUOTE = 25
+LBRACE = 26
+RBRACE = 27
+EQEQUAL = 28
+NOTEQUAL = 29
+LESSEQUAL = 30
+GREATEREQUAL = 31
+TILDE = 32
+CIRCUMFLEX = 33
+LEFTSHIFT = 34
+RIGHTSHIFT = 35
+DOUBLESTAR = 36
+PLUSEQUAL = 37
+MINEQUAL = 38
+STAREQUAL = 39
+SLASHEQUAL = 40
+PERCENTEQUAL = 41
+AMPEREQUAL = 42
+VBAREQUAL = 43
+CIRCUMFLEXEQUAL = 44
+LEFTSHIFTEQUAL = 45
+RIGHTSHIFTEQUAL = 46
+DOUBLESTAREQUAL = 47
+DOUBLESLASH = 48
+DOUBLESLASHEQUAL = 49
+AT = 50
+OP = 51
+COMMENT = 52
+NL = 53
+RARROW = 54
+ERRORTOKEN = 55
+ELLIPSIS = 56
+N_TOKENS = 57
+NT_OFFSET = 256
+#--end constants--
+
+tok_name = {}
+for _name, _value in globals().items():
+ if type(_value) is type(0):
+ tok_name[_value] = _name
+
+
+def ISTERMINAL(x):
+ return x < NT_OFFSET
+
+def ISNONTERMINAL(x):
+ return x >= NT_OFFSET
+
+def ISEOF(x):
+ return x == ENDMARKER
diff --git a/sphinx/pycode/pgen2/tokenize.py b/sphinx/pycode/pgen2/tokenize.py
new file mode 100644
index 0000000..7ad9f01
--- /dev/null
+++ b/sphinx/pycode/pgen2/tokenize.py
@@ -0,0 +1,412 @@
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation.
+# All rights reserved.
+
+"""Tokenization help for Python programs.
+
+generate_tokens(readline) is a generator that breaks a stream of
+text into Python tokens. It accepts a readline-like method which is called
+repeatedly to get the next line of input (or "" for EOF). It generates
+5-tuples with these members:
+
+ the token type (see token.py)
+ the token (a string)
+ the starting (row, column) indices of the token (a 2-tuple of ints)
+ the ending (row, column) indices of the token (a 2-tuple of ints)
+ the original line (string)
+
+It is designed to match the working of the Python tokenizer exactly, except
+that it produces COMMENT tokens for comments and gives type OP for all
+operators
+
+Older entry points
+ tokenize_loop(readline, tokeneater)
+ tokenize(readline, tokeneater=printtoken)
+are the same, except instead of generating tokens, tokeneater is a callback
+function to which the 5 fields described above are passed as 5 arguments,
+each time a new token is found."""
+
+__author__ = 'Ka-Ping Yee <ping at lfw.org>'
+__credits__ = \
+ 'GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, Skip Montanaro'
+
+import string, re
+from sphinx.pycode.pgen2.token import *
+from sphinx.pycode.pgen2 import token
+
+__all__ = [x for x in dir(token) if x[0] != '_'] + ["tokenize",
+ "generate_tokens", "untokenize"]
+del token
+
+def group(*choices): return '(' + '|'.join(choices) + ')'
+def any(*choices): return group(*choices) + '*'
+def maybe(*choices): return group(*choices) + '?'
+
+Whitespace = r'[ \f\t]*'
+Comment = r'#[^\r\n]*'
+Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
+Name = r'[a-zA-Z_]\w*'
+
+Binnumber = r'0[bB][01]*'
+Hexnumber = r'0[xX][\da-fA-F]*[lL]?'
+Octnumber = r'0[oO]?[0-7]*[lL]?'
+Decnumber = r'[1-9]\d*[lL]?'
+Intnumber = group(Binnumber, Hexnumber, Octnumber, Decnumber)
+Exponent = r'[eE][-+]?\d+'
+Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent)
+Expfloat = r'\d+' + Exponent
+Floatnumber = group(Pointfloat, Expfloat)
+Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]')
+Number = group(Imagnumber, Floatnumber, Intnumber)
+
+# Tail end of ' string.
+Single = r"[^'\\]*(?:\\.[^'\\]*)*'"
+# Tail end of " string.
+Double = r'[^"\\]*(?:\\.[^"\\]*)*"'
+# Tail end of ''' string.
+Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''"
+# Tail end of """ string.
+Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
+Triple = group("[ubUB]?[rR]?'''", '[ubUB]?[rR]?"""')
+# Single-line ' or " string.
+String = group(r"[uU]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*'",
+ r'[uU]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*"')
+
+# Because of leftmost-then-longest match semantics, be sure to put the
+# longest operators first (e.g., if = came before ==, == would get
+# recognized as two instances of =).
+Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"<>", r"!=",
+ r"//=?", r"->",
+ r"[+\-*/%&|^=<>]=?",
+ r"~")
+
+Bracket = '[][(){}]'
+Special = group(r'\r?\n', r'[:;.,`@]')
+Funny = group(Operator, Bracket, Special)
+
+PlainToken = group(Number, Funny, String, Name)
+Token = Ignore + PlainToken
+
+# First (or only) line of ' or " string.
+ContStr = group(r"[uUbB]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*" +
+ group("'", r'\\\r?\n'),
+ r'[uUbB]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*' +
+ group('"', r'\\\r?\n'))
+PseudoExtras = group(r'\\\r?\n', Comment, Triple)
+PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name)
+
+tokenprog, pseudoprog, single3prog, double3prog = map(
+ re.compile, (Token, PseudoToken, Single3, Double3))
+endprogs = {"'": re.compile(Single), '"': re.compile(Double),
+ "'''": single3prog, '"""': double3prog,
+ "r'''": single3prog, 'r"""': double3prog,
+ "u'''": single3prog, 'u"""': double3prog,
+ "b'''": single3prog, 'b"""': double3prog,
+ "ur'''": single3prog, 'ur"""': double3prog,
+ "br'''": single3prog, 'br"""': double3prog,
+ "R'''": single3prog, 'R"""': double3prog,
+ "U'''": single3prog, 'U"""': double3prog,
+ "B'''": single3prog, 'B"""': double3prog,
+ "uR'''": single3prog, 'uR"""': double3prog,
+ "Ur'''": single3prog, 'Ur"""': double3prog,
+ "UR'''": single3prog, 'UR"""': double3prog,
+ "bR'''": single3prog, 'bR"""': double3prog,
+ "Br'''": single3prog, 'Br"""': double3prog,
+ "BR'''": single3prog, 'BR"""': double3prog,
+ 'r': None, 'R': None,
+ 'u': None, 'U': None,
+ 'b': None, 'B': None}
+
+triple_quoted = {}
+for t in ("'''", '"""',
+ "r'''", 'r"""', "R'''", 'R"""',
+ "u'''", 'u"""', "U'''", 'U"""',
+ "b'''", 'b"""', "B'''", 'B"""',
+ "ur'''", 'ur"""', "Ur'''", 'Ur"""',
+ "uR'''", 'uR"""', "UR'''", 'UR"""',
+ "br'''", 'br"""', "Br'''", 'Br"""',
+ "bR'''", 'bR"""', "BR'''", 'BR"""',):
+ triple_quoted[t] = t
+single_quoted = {}
+for t in ("'", '"',
+ "r'", 'r"', "R'", 'R"',
+ "u'", 'u"', "U'", 'U"',
+ "b'", 'b"', "B'", 'B"',
+ "ur'", 'ur"', "Ur'", 'Ur"',
+ "uR'", 'uR"', "UR'", 'UR"',
+ "br'", 'br"', "Br'", 'Br"',
+ "bR'", 'bR"', "BR'", 'BR"', ):
+ single_quoted[t] = t
+
+tabsize = 8
+
+class TokenError(Exception): pass
+
+class StopTokenizing(Exception): pass
+
+def printtoken(type, token, scell, ecell, line): # for testing
+ srow, scol = scell
+ erow, ecol = ecell
+ print "%d,%d-%d,%d:\t%s\t%s" % \
+ (srow, scol, erow, ecol, tok_name[type], repr(token))
+
+def tokenize(readline, tokeneater=printtoken):
+ """
+ The tokenize() function accepts two parameters: one representing the
+ input stream, and one providing an output mechanism for tokenize().
+
+ The first parameter, readline, must be a callable object which provides
+ the same interface as the readline() method of built-in file objects.
+ Each call to the function should return one line of input as a string.
+
+ The second parameter, tokeneater, must also be a callable object. It is
+ called once for each token, with five arguments, corresponding to the
+ tuples generated by generate_tokens().
+ """
+ try:
+ tokenize_loop(readline, tokeneater)
+ except StopTokenizing:
+ pass
+
+# backwards compatible interface
+def tokenize_loop(readline, tokeneater):
+ for token_info in generate_tokens(readline):
+ tokeneater(*token_info)
+
+class Untokenizer:
+
+ def __init__(self):
+ self.tokens = []
+ self.prev_row = 1
+ self.prev_col = 0
+
+ def add_whitespace(self, start):
+ row, col = start
+ assert row <= self.prev_row
+ col_offset = col - self.prev_col
+ if col_offset:
+ self.tokens.append(" " * col_offset)
+
+ def untokenize(self, iterable):
+ for t in iterable:
+ if len(t) == 2:
+ self.compat(t, iterable)
+ break
+ tok_type, token, start, end, line = t
+ self.add_whitespace(start)
+ self.tokens.append(token)
+ self.prev_row, self.prev_col = end
+ if tok_type in (NEWLINE, NL):
+ self.prev_row += 1
+ self.prev_col = 0
+ return "".join(self.tokens)
+
+ def compat(self, token, iterable):
+ startline = False
+ indents = []
+ toks_append = self.tokens.append
+ toknum, tokval = token
+ if toknum in (NAME, NUMBER):
+ tokval += ' '
+ if toknum in (NEWLINE, NL):
+ startline = True
+ for tok in iterable:
+ toknum, tokval = tok[:2]
+
+ if toknum in (NAME, NUMBER):
+ tokval += ' '
+
+ if toknum == INDENT:
+ indents.append(tokval)
+ continue
+ elif toknum == DEDENT:
+ indents.pop()
+ continue
+ elif toknum in (NEWLINE, NL):
+ startline = True
+ elif startline and indents:
+ toks_append(indents[-1])
+ startline = False
+ toks_append(tokval)
+
+def untokenize(iterable):
+ """Transform tokens back into Python source code.
+
+ Each element returned by the iterable must be a token sequence
+ with at least two elements, a token number and token value. If
+ only two tokens are passed, the resulting output is poor.
+
+ Round-trip invariant for full input:
+ Untokenized source will match input source exactly
+
+ Round-trip invariant for limited intput:
+ # Output text will tokenize the back to the input
+ t1 = [tok[:2] for tok in generate_tokens(f.readline)]
+ newcode = untokenize(t1)
+ readline = iter(newcode.splitlines(1)).next
+ t2 = [tok[:2] for tokin generate_tokens(readline)]
+ assert t1 == t2
+ """
+ ut = Untokenizer()
+ return ut.untokenize(iterable)
+
+def generate_tokens(readline):
+ """
+ The generate_tokens() generator requires one argment, readline, which
+ must be a callable object which provides the same interface as the
+ readline() method of built-in file objects. Each call to the function
+ should return one line of input as a string. Alternately, readline
+ can be a callable function terminating with StopIteration:
+ readline = open(myfile).next # Example of alternate readline
+
+ The generator produces 5-tuples with these members: the token type; the
+ token string; a 2-tuple (srow, scol) of ints specifying the row and
+ column where the token begins in the source; a 2-tuple (erow, ecol) of
+ ints specifying the row and column where the token ends in the source;
+ and the line on which the token was found. The line passed is the
+ logical line; continuation lines are included.
+ """
+ lnum = parenlev = continued = 0
+ namechars, numchars = string.ascii_letters + '_', '0123456789'
+ contstr, needcont = '', 0
+ contline = None
+ indents = [0]
+
+ while 1: # loop over lines in stream
+ try:
+ line = readline()
+ except StopIteration:
+ line = ''
+ # if we are not at the end of the file make sure the
+ # line ends with a newline because the parser depends
+ # on that.
+ if line:
+ line = line.rstrip() + '\n'
+ lnum = lnum + 1
+ pos, max = 0, len(line)
+
+ if contstr: # continued string
+ if not line:
+ raise TokenError("EOF in multi-line string", strstart)
+ endmatch = endprog.match(line)
+ if endmatch:
+ pos = end = endmatch.end(0)
+ yield (STRING, contstr + line[:end],
+ strstart, (lnum, end), contline + line)
+ contstr, needcont = '', 0
+ contline = None
+ elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n':
+ yield (ERRORTOKEN, contstr + line,
+ strstart, (lnum, len(line)), contline)
+ contstr = ''
+ contline = None
+ continue
+ else:
+ contstr = contstr + line
+ contline = contline + line
+ continue
+
+ elif parenlev == 0 and not continued: # new statement
+ if not line: break
+ column = 0
+ while pos < max: # measure leading whitespace
+ if line[pos] == ' ': column = column + 1
+ elif line[pos] == '\t': column = (column/tabsize + 1)*tabsize
+ elif line[pos] == '\f': column = 0
+ else: break
+ pos = pos + 1
+ if pos == max: break
+
+ if line[pos] in '#\r\n': # skip comments or blank lines
+ if line[pos] == '#':
+ comment_token = line[pos:].rstrip('\r\n')
+ nl_pos = pos + len(comment_token)
+ yield (COMMENT, comment_token,
+ (lnum, pos), (lnum, pos + len(comment_token)), line)
+ yield (NL, line[nl_pos:],
+ (lnum, nl_pos), (lnum, len(line)), line)
+ else:
+ yield ((NL, COMMENT)[line[pos] == '#'], line[pos:],
+ (lnum, pos), (lnum, len(line)), line)
+ continue
+
+ if column > indents[-1]: # count indents or dedents
+ indents.append(column)
+ yield (INDENT, line[:pos], (lnum, 0), (lnum, pos), line)
+ while column < indents[-1]:
+ if column not in indents:
+ raise IndentationError(
+ "unindent does not match any outer indentation level",
+ ("<tokenize>", lnum, pos, line))
+ indents = indents[:-1]
+ yield (DEDENT, '', (lnum, pos), (lnum, pos), line)
+
+ else: # continued statement
+ if not line:
+ raise TokenError("EOF in multi-line statement", (lnum, 0))
+ continued = 0
+
+ while pos < max:
+ pseudomatch = pseudoprog.match(line, pos)
+ if pseudomatch: # scan for tokens
+ start, end = pseudomatch.span(1)
+ spos, epos, pos = (lnum, start), (lnum, end), end
+ token, initial = line[start:end], line[start]
+
+ if initial in numchars or \
+ (initial == '.' and token != '.'): # ordinary number
+ yield (NUMBER, token, spos, epos, line)
+ elif initial in '\r\n':
+ newline = NEWLINE
+ if parenlev > 0:
+ newline = NL
+ yield (newline, token, spos, epos, line)
+ elif initial == '#':
+ assert not token.endswith("\n")
+ yield (COMMENT, token, spos, epos, line)
+ elif token in triple_quoted:
+ endprog = endprogs[token]
+ endmatch = endprog.match(line, pos)
+ if endmatch: # all on one line
+ pos = endmatch.end(0)
+ token = line[start:pos]
+ yield (STRING, token, spos, (lnum, pos), line)
+ else:
+ strstart = (lnum, start) # multiple lines
+ contstr = line[start:]
+ contline = line
+ break
+ elif initial in single_quoted or \
+ token[:2] in single_quoted or \
+ token[:3] in single_quoted:
+ if token[-1] == '\n': # continued string
+ strstart = (lnum, start)
+ endprog = (endprogs[initial] or endprogs[token[1]] or
+ endprogs[token[2]])
+ contstr, needcont = line[start:], 1
+ contline = line
+ break
+ else: # ordinary string
+ yield (STRING, token, spos, epos, line)
+ elif initial in namechars: # ordinary name
+ yield (NAME, token, spos, epos, line)
+ elif initial == '\\': # continued stmt
+ # This yield is new; needed for better idempotency:
+ yield (NL, token, spos, (lnum, pos), line)
+ continued = 1
+ else:
+ if initial in '([{': parenlev = parenlev + 1
+ elif initial in ')]}': parenlev = parenlev - 1
+ yield (OP, token, spos, epos, line)
+ else:
+ yield (ERRORTOKEN, line[pos],
+ (lnum, pos), (lnum, pos+1), line)
+ pos = pos + 1
+
+ for indent in indents[1:]: # pop remaining indent levels
+ yield (DEDENT, '', (lnum, 0), (lnum, 0), '')
+ yield (ENDMARKER, '', (lnum, 0), (lnum, 0), '')
+
+if __name__ == '__main__': # testing
+ import sys
+ if len(sys.argv) > 1: tokenize(open(sys.argv[1]).readline)
+ else: tokenize(sys.stdin.readline)
diff --git a/sphinx/pygments_styles.py b/sphinx/pygments_styles.py
new file mode 100644
index 0000000..a7335e6
--- /dev/null
+++ b/sphinx/pygments_styles.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.pygments_styles
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx theme specific highlighting styles.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from pygments.style import Style
+from pygments.styles.friendly import FriendlyStyle
+from pygments.token import Generic, Comment, Number, Whitespace, Keyword, \
+ Operator, Name, String, Error
+
+
+class NoneStyle(Style):
+ """Style without any styling."""
+
+
+class SphinxStyle(Style):
+ """
+ Like friendly, but a bit darker to enhance contrast on the green
+ background.
+ """
+
+ background_color = '#eeffcc'
+ default_style = ''
+
+ styles = FriendlyStyle.styles
+ styles.update({
+ Generic.Output: '#333',
+ Comment: 'italic #408090',
+ Number: '#208050',
+ })
+
+
+class PyramidStyle(Style):
+ """
+ Pylons/pyramid pygments style based on friendly style, by Blaise Laflamme.
+ """
+
+ # work in progress...
+
+ background_color = "#f8f8f8"
+ default_style = ""
+
+ styles = {
+ Whitespace: "#bbbbbb",
+ Comment: "italic #60a0b0",
+ Comment.Preproc: "noitalic #007020",
+ Comment.Special: "noitalic bg:#fff0f0",
+
+ Keyword: "bold #007020",
+ Keyword.Pseudo: "nobold",
+ Keyword.Type: "nobold #902000",
+
+ Operator: "#666666",
+ Operator.Word: "bold #007020",
+
+ Name.Builtin: "#007020",
+ Name.Function: "#06287e",
+ Name.Class: "bold #0e84b5",
+ Name.Namespace: "bold #0e84b5",
+ Name.Exception: "#007020",
+ Name.Variable: "#bb60d5",
+ Name.Constant: "#60add5",
+ Name.Label: "bold #002070",
+ Name.Entity: "bold #d55537",
+ Name.Attribute: "#0e84b5",
+ Name.Tag: "bold #062873",
+ Name.Decorator: "bold #555555",
+
+ String: "#4070a0",
+ String.Doc: "italic",
+ String.Interpol: "italic #70a0d0",
+ String.Escape: "bold #4070a0",
+ String.Regex: "#235388",
+ String.Symbol: "#517918",
+ String.Other: "#c65d09",
+ Number: "#40a070",
+
+ Generic.Heading: "bold #000080",
+ Generic.Subheading: "bold #800080",
+ Generic.Deleted: "#A00000",
+ Generic.Inserted: "#00A000",
+ Generic.Error: "#FF0000",
+ Generic.Emph: "italic",
+ Generic.Strong: "bold",
+ Generic.Prompt: "bold #c65d09",
+ Generic.Output: "#888",
+ Generic.Traceback: "#04D",
+
+ Error: "#a40000 bg:#fbe3e4"
+ }
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py
new file mode 100644
index 0000000..5cf067e
--- /dev/null
+++ b/sphinx/quickstart.py
@@ -0,0 +1,1284 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.quickstart
+ ~~~~~~~~~~~~~~~~~
+
+ Quickly setup documentation source to work with Sphinx.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys, os, time, re
+from os import path
+
+TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
+
+from docutils.utils import column_width
+
+from sphinx import __version__
+from sphinx.util.osutil import make_filename
+from sphinx.util.console import purple, bold, red, turquoise, \
+ nocolor, color_terminal
+from sphinx.util import texescape
+from sphinx.util.pycompat import open
+
+# function to get input from terminal -- overridden by the test suite
+try:
+ # this raw_input is not converted by 2to3
+ term_input = raw_input
+except NameError:
+ term_input = input
+
+
+PROMPT_PREFIX = '> '
+
+if sys.version_info >= (3, 0):
+ # prevents that the file is checked for being written in Python 2.x syntax
+ QUICKSTART_CONF = u'#!/usr/bin/env python3\n'
+else:
+ QUICKSTART_CONF = u''
+
+QUICKSTART_CONF += u'''\
+# -*- coding: utf-8 -*-
+#
+# %(project)s documentation build configuration file, created by
+# sphinx-quickstart on %(now)s.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+
+# 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('.'))
+
+# -- 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 = [%(extensions)s]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['%(dot)stemplates']
+
+# The suffix of source filenames.
+source_suffix = '%(suffix)s'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = '%(master_str)s'
+
+# General information about the project.
+project = u'%(project_str)s'
+copyright = u'%(copyright_str)s'
+
+# 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 = '%(version_str)s'
+# The full version, including alpha/beta/rc tags.
+release = '%(release_str)s'
+
+# 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 = [%(exclude_patterns)s]
+
+# 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 = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+
+# -- 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'
+
+# 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 = None
+
+# 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 = ['%(dot)sstatic']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# 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 = '%(project_fn)sdoc'
+
+
+# -- 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, or own class]).
+latex_documents = [
+ ('%(master_str)s', '%(project_fn)s.tex', u'%(project_doc_texescaped_str)s',
+ u'%(author_texescaped_str)s', '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 = [
+ ('%(master_str)s', '%(project_manpage)s', u'%(project_doc_str)s',
+ [u'%(author_str)s'], 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 = [
+ ('%(master_str)s', '%(project_fn)s', u'%(project_doc_str)s',
+ u'%(author_str)s', '%(project_fn)s', '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'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+'''
+
+EPUB_CONFIG = u'''
+
+# -- Options for Epub output ----------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = u'%(project_str)s'
+epub_author = u'%(author_str)s'
+epub_publisher = u'%(author_str)s'
+epub_copyright = u'%(copyright_str)s'
+
+# The basename for the epub file. It defaults to the project name.
+#epub_basename = u'%(project_str)s'
+
+# The HTML theme for the epub output. Since the default themes are not optimized
+# for small screen space, using the same theme for HTML and epub output is
+# usually not wise. This defaults to 'epub', a theme designed to save visual
+# space.
+#epub_theme = 'epub'
+
+# The language of the text. It defaults to the language option
+# or en if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
+# A sequence of (type, uri, title) tuples for the guide element of content.opf.
+#epub_guide = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
+
+# Choose between 'default' and 'includehidden'.
+#epub_tocscope = 'default'
+
+# Fix unsupported image types using the PIL.
+#epub_fix_images = False
+
+# Scale large images.
+#epub_max_image_width = 0
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#epub_show_urls = 'inline'
+
+# If false, no index is generated.
+#epub_use_index = True
+'''
+
+INTERSPHINX_CONFIG = u'''
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}
+'''
+
+MASTER_FILE = u'''\
+.. %(project)s documentation master file, created by
+ sphinx-quickstart on %(now)s.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to %(project)s's documentation!
+===========%(project_underline)s=================
+
+Contents:
+
+.. toctree::
+ :maxdepth: %(mastertocmaxdepth)s
+
+%(mastertoctree)s
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+'''
+
+MAKEFILE = u'''\
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = %(rbuilddir)s
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error \
+The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx \
+installed, then set the SPHINXBUILD environment variable to point \
+to the full path of the '$(SPHINXBUILD)' executable. Alternatively you \
+can add the directory with the executable to your PATH. \
+If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) \
+$(SPHINXOPTS) %(rsrcdir)s
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) %(rsrcdir)s
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp \
+epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+\t at echo "Please use \\`make <target>' where <target> is one of"
+\t at echo " html to make standalone HTML files"
+\t at echo " dirhtml to make HTML files named index.html in directories"
+\t at echo " singlehtml to make a single large HTML file"
+\t at echo " pickle to make pickle files"
+\t at echo " json to make JSON files"
+\t at echo " htmlhelp to make HTML files and a HTML help project"
+\t at echo " qthelp to make HTML files and a qthelp project"
+\t at echo " devhelp to make HTML files and a Devhelp project"
+\t at echo " epub to make an epub"
+\t at echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+\t at echo " latexpdf to make LaTeX files and run them through pdflatex"
+\t at echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+\t at echo " text to make text files"
+\t at echo " man to make manual pages"
+\t at echo " texinfo to make Texinfo files"
+\t at echo " info to make Texinfo files and run them through makeinfo"
+\t at echo " gettext to make PO message catalogs"
+\t at echo " changes to make an overview of all changed/added/deprecated items"
+\t at echo " xml to make Docutils-native XML files"
+\t at echo " pseudoxml to make pseudoxml-XML files for display purposes"
+\t at echo " linkcheck to check all external links for integrity"
+\t at echo " doctest to run all doctests embedded in the documentation \
+(if enabled)"
+
+clean:
+\trm -rf $(BUILDDIR)/*
+
+html:
+\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+\t at echo
+\t at echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+\t at echo
+\t at echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+\t at echo
+\t at echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+\t at echo
+\t at echo "Build finished; now you can process the pickle files."
+
+json:
+\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+\t at echo
+\t at echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+\t at echo
+\t at echo "Build finished; now you can run HTML Help Workshop with the" \\
+\t ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+\t at echo
+\t at echo "Build finished; now you can run "qcollectiongenerator" with the" \\
+\t ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+\t at echo "# qcollectiongenerator $(BUILDDIR)/qthelp/%(project_fn)s.qhcp"
+\t at echo "To view the help file:"
+\t at echo "# assistant -collectionFile $(BUILDDIR)/qthelp/%(project_fn)s.qhc"
+
+devhelp:
+\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+\t at echo
+\t at echo "Build finished."
+\t at echo "To view the help file:"
+\t at echo "# mkdir -p $$HOME/.local/share/devhelp/%(project_fn)s"
+\t at echo "# ln -s $(BUILDDIR)/devhelp\
+ $$HOME/.local/share/devhelp/%(project_fn)s"
+\t at echo "# devhelp"
+
+epub:
+\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+\t at echo
+\t at echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+\t at echo
+\t at echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+\t at echo "Run \\`make' in that directory to run these through (pdf)latex" \\
+\t "(use \\`make latexpdf' here to do that automatically)."
+
+latexpdf:
+\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+\t at echo "Running LaTeX files through pdflatex..."
+\t$(MAKE) -C $(BUILDDIR)/latex all-pdf
+\t at echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+latexpdfja:
+\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+\t at echo "Running LaTeX files through platex and dvipdfmx..."
+\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+\t at echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+\t at echo
+\t at echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+\t at echo
+\t at echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+\t at echo
+\t at echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+\t at echo "Run \\`make' in that directory to run these through makeinfo" \\
+\t "(use \\`make info' here to do that automatically)."
+
+info:
+\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+\t at echo "Running Texinfo files through makeinfo..."
+\tmake -C $(BUILDDIR)/texinfo info
+\t at echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+\t at echo
+\t at echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+\t at echo
+\t at echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+\t at echo
+\t at echo "Link check complete; look for any errors in the above output " \\
+\t "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+\t at echo "Testing of doctests in the sources finished, look at the " \\
+\t "results in $(BUILDDIR)/doctest/output.txt."
+
+xml:
+\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+\t at echo
+\t at echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+\t at echo
+\t at echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+'''
+
+BATCHFILE = u'''\
+ at ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%%SPHINXBUILD%%" == "" (
+\tset SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=%(rbuilddir)s
+set ALLSPHINXOPTS=-d %%BUILDDIR%%/doctrees %%SPHINXOPTS%% %(rsrcdir)s
+set I18NSPHINXOPTS=%%SPHINXOPTS%% %(rsrcdir)s
+if NOT "%%PAPER%%" == "" (
+\tset ALLSPHINXOPTS=-D latex_paper_size=%%PAPER%% %%ALLSPHINXOPTS%%
+\tset I18NSPHINXOPTS=-D latex_paper_size=%%PAPER%% %%I18NSPHINXOPTS%%
+)
+
+if "%%1" == "" goto help
+
+if "%%1" == "help" (
+\t:help
+\techo.Please use `make ^<target^>` where ^<target^> is one of
+\techo. html to make standalone HTML files
+\techo. dirhtml to make HTML files named index.html in directories
+\techo. singlehtml to make a single large HTML file
+\techo. pickle to make pickle files
+\techo. json to make JSON files
+\techo. htmlhelp to make HTML files and a HTML help project
+\techo. qthelp to make HTML files and a qthelp project
+\techo. devhelp to make HTML files and a Devhelp project
+\techo. epub to make an epub
+\techo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+\techo. text to make text files
+\techo. man to make manual pages
+\techo. texinfo to make Texinfo files
+\techo. gettext to make PO message catalogs
+\techo. changes to make an overview over all changed/added/deprecated items
+\techo. xml to make Docutils-native XML files
+\techo. pseudoxml to make pseudoxml-XML files for display purposes
+\techo. linkcheck to check all external links for integrity
+\techo. doctest to run all doctests embedded in the documentation if enabled
+\tgoto end
+)
+
+if "%%1" == "clean" (
+\tfor /d %%%%i in (%%BUILDDIR%%\*) do rmdir /q /s %%%%i
+\tdel /q /s %%BUILDDIR%%\*
+\tgoto end
+)
+
+
+%%SPHINXBUILD%% 2> nul
+if errorlevel 9009 (
+\techo.
+\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+\techo.installed, then set the SPHINXBUILD environment variable to point
+\techo.to the full path of the 'sphinx-build' executable. Alternatively you
+\techo.may add the Sphinx directory to PATH.
+\techo.
+\techo.If you don't have Sphinx installed, grab it from
+\techo.http://sphinx-doc.org/
+\texit /b 1
+)
+
+if "%%1" == "html" (
+\t%%SPHINXBUILD%% -b html %%ALLSPHINXOPTS%% %%BUILDDIR%%/html
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The HTML pages are in %%BUILDDIR%%/html.
+\tgoto end
+)
+
+if "%%1" == "dirhtml" (
+\t%%SPHINXBUILD%% -b dirhtml %%ALLSPHINXOPTS%% %%BUILDDIR%%/dirhtml
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The HTML pages are in %%BUILDDIR%%/dirhtml.
+\tgoto end
+)
+
+if "%%1" == "singlehtml" (
+\t%%SPHINXBUILD%% -b singlehtml %%ALLSPHINXOPTS%% %%BUILDDIR%%/singlehtml
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The HTML pages are in %%BUILDDIR%%/singlehtml.
+\tgoto end
+)
+
+if "%%1" == "pickle" (
+\t%%SPHINXBUILD%% -b pickle %%ALLSPHINXOPTS%% %%BUILDDIR%%/pickle
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished; now you can process the pickle files.
+\tgoto end
+)
+
+if "%%1" == "json" (
+\t%%SPHINXBUILD%% -b json %%ALLSPHINXOPTS%% %%BUILDDIR%%/json
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished; now you can process the JSON files.
+\tgoto end
+)
+
+if "%%1" == "htmlhelp" (
+\t%%SPHINXBUILD%% -b htmlhelp %%ALLSPHINXOPTS%% %%BUILDDIR%%/htmlhelp
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %%BUILDDIR%%/htmlhelp.
+\tgoto end
+)
+
+if "%%1" == "qthelp" (
+\t%%SPHINXBUILD%% -b qthelp %%ALLSPHINXOPTS%% %%BUILDDIR%%/qthelp
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %%BUILDDIR%%/qthelp, like this:
+\techo.^> qcollectiongenerator %%BUILDDIR%%\\qthelp\\%(project_fn)s.qhcp
+\techo.To view the help file:
+\techo.^> assistant -collectionFile %%BUILDDIR%%\\qthelp\\%(project_fn)s.ghc
+\tgoto end
+)
+
+if "%%1" == "devhelp" (
+\t%%SPHINXBUILD%% -b devhelp %%ALLSPHINXOPTS%% %%BUILDDIR%%/devhelp
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished.
+\tgoto end
+)
+
+if "%%1" == "epub" (
+\t%%SPHINXBUILD%% -b epub %%ALLSPHINXOPTS%% %%BUILDDIR%%/epub
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The epub file is in %%BUILDDIR%%/epub.
+\tgoto end
+)
+
+if "%%1" == "latex" (
+\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished; the LaTeX files are in %%BUILDDIR%%/latex.
+\tgoto end
+)
+
+if "%%1" == "latexpdf" (
+\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
+\tcd %%BUILDDIR%%/latex
+\tmake all-pdf
+\tcd %%BUILDDIR%%/..
+\techo.
+\techo.Build finished; the PDF files are in %%BUILDDIR%%/latex.
+\tgoto end
+)
+
+if "%%1" == "latexpdfja" (
+\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
+\tcd %%BUILDDIR%%/latex
+\tmake all-pdf-ja
+\tcd %%BUILDDIR%%/..
+\techo.
+\techo.Build finished; the PDF files are in %%BUILDDIR%%/latex.
+\tgoto end
+)
+
+if "%%1" == "text" (
+\t%%SPHINXBUILD%% -b text %%ALLSPHINXOPTS%% %%BUILDDIR%%/text
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The text files are in %%BUILDDIR%%/text.
+\tgoto end
+)
+
+if "%%1" == "man" (
+\t%%SPHINXBUILD%% -b man %%ALLSPHINXOPTS%% %%BUILDDIR%%/man
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The manual pages are in %%BUILDDIR%%/man.
+\tgoto end
+)
+
+if "%%1" == "texinfo" (
+\t%%SPHINXBUILD%% -b texinfo %%ALLSPHINXOPTS%% %%BUILDDIR%%/texinfo
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The Texinfo files are in %%BUILDDIR%%/texinfo.
+\tgoto end
+)
+
+if "%%1" == "gettext" (
+\t%%SPHINXBUILD%% -b gettext %%I18NSPHINXOPTS%% %%BUILDDIR%%/locale
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The message catalogs are in %%BUILDDIR%%/locale.
+\tgoto end
+)
+
+if "%%1" == "changes" (
+\t%%SPHINXBUILD%% -b changes %%ALLSPHINXOPTS%% %%BUILDDIR%%/changes
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.The overview file is in %%BUILDDIR%%/changes.
+\tgoto end
+)
+
+if "%%1" == "linkcheck" (
+\t%%SPHINXBUILD%% -b linkcheck %%ALLSPHINXOPTS%% %%BUILDDIR%%/linkcheck
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Link check complete; look for any errors in the above output ^
+or in %%BUILDDIR%%/linkcheck/output.txt.
+\tgoto end
+)
+
+if "%%1" == "doctest" (
+\t%%SPHINXBUILD%% -b doctest %%ALLSPHINXOPTS%% %%BUILDDIR%%/doctest
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Testing of doctests in the sources finished, look at the ^
+results in %%BUILDDIR%%/doctest/output.txt.
+\tgoto end
+)
+
+if "%%1" == "xml" (
+\t%%SPHINXBUILD%% -b xml %%ALLSPHINXOPTS%% %%BUILDDIR%%/xml
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The XML files are in %%BUILDDIR%%/xml.
+\tgoto end
+)
+
+if "%%1" == "pseudoxml" (
+\t%%SPHINXBUILD%% -b pseudoxml %%ALLSPHINXOPTS%% %%BUILDDIR%%/pseudoxml
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Build finished. The pseudo-XML files are in %%BUILDDIR%%/pseudoxml.
+\tgoto end
+)
+
+:end
+'''
+
+# This will become the Makefile template for Sphinx 1.5.
+MAKEFILE_NEW = u'''\
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+SPHINXPROJ = %(project_fn)s
+SOURCEDIR = %(rsrcdir)s
+BUILDDIR = %(rbuilddir)s
+
+# User-friendly check for sphinx-build.
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error \
+The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx \
+installed, then set the SPHINXBUILD environment variable to point \
+to the full path of the '$(SPHINXBUILD)' executable. Alternatively you \
+can add the directory with the executable to your PATH. \
+If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Has to be explicit, otherwise we don't get "make" without targets right.
+help:
+\t@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+# You can add custom targets here.
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%:
+\t@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+'''
+
+# This will become the make.bat template for Sphinx 1.5.
+BATCHFILE_NEW = u'''\
+ at ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%%SPHINXBUILD%%" == "" (
+\tset SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=%(rbuilddir)s
+set SPHINXPROJ=%(project_fn)s
+
+if "%%1" == "" goto help
+
+%%SPHINXBUILD%% 2> nul
+if errorlevel 9009 (
+\techo.
+\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+\techo.installed, then set the SPHINXBUILD environment variable to point
+\techo.to the full path of the 'sphinx-build' executable. Alternatively you
+\techo.may add the Sphinx directory to PATH.
+\techo.
+\techo.If you don't have Sphinx installed, grab it from
+\techo.http://sphinx-doc.org/
+\texit /b 1
+)
+
+%%SPHINXBUILD%% -M %%1 %%BUILDDIR%% %%SPHINXOPTS%%
+goto end
+
+:help
+%%SPHINXBUILD%% -M help %%BUILDDIR%% %%SPHINXOPTS%%
+
+:end
+'''
+
+
+def mkdir_p(dir):
+ if path.isdir(dir):
+ return
+ os.makedirs(dir)
+
+
+class ValidationError(Exception):
+ """Raised for validation errors."""
+
+def is_path(x):
+ if path.exists(x) and not path.isdir(x):
+ raise ValidationError("Please enter a valid path name.")
+ return x
+
+def nonempty(x):
+ if not x:
+ raise ValidationError("Please enter some text.")
+ return x
+
+def choice(*l):
+ def val(x):
+ if x not in l:
+ raise ValidationError('Please enter one of %s.' % ', '.join(l))
+ return x
+ return val
+
+def boolean(x):
+ if x.upper() not in ('Y', 'YES', 'N', 'NO'):
+ raise ValidationError("Please enter either 'y' or 'n'.")
+ return x.upper() in ('Y', 'YES')
+
+def suffix(x):
+ if not (x[0:1] == '.' and len(x) > 1):
+ raise ValidationError("Please enter a file suffix, "
+ "e.g. '.rst' or '.txt'.")
+ return x
+
+def ok(x):
+ return x
+
+
+def do_prompt(d, key, text, default=None, validator=nonempty):
+ while True:
+ if default:
+ prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default)
+ else:
+ prompt = PROMPT_PREFIX + text + ': '
+ if sys.version_info < (3, 0):
+ # for Python 2.x, try to get a Unicode string out of it
+ if prompt.encode('ascii', 'replace').decode('ascii', 'replace') \
+ != prompt:
+ if TERM_ENCODING:
+ prompt = prompt.encode(TERM_ENCODING)
+ else:
+ print turquoise('* Note: non-ASCII default value provided '
+ 'and terminal encoding unknown -- assuming '
+ 'UTF-8 or Latin-1.')
+ try:
+ prompt = prompt.encode('utf-8')
+ except UnicodeEncodeError:
+ prompt = prompt.encode('latin1')
+ prompt = purple(prompt)
+ x = term_input(prompt).strip()
+ if default and not x:
+ x = default
+ if not isinstance(x, unicode):
+ # for Python 2.x, try to get a Unicode string out of it
+ if x.decode('ascii', 'replace').encode('ascii', 'replace') != x:
+ if TERM_ENCODING:
+ x = x.decode(TERM_ENCODING)
+ else:
+ print turquoise('* Note: non-ASCII characters entered '
+ 'and terminal encoding unknown -- assuming '
+ 'UTF-8 or Latin-1.')
+ try:
+ x = x.decode('utf-8')
+ except UnicodeDecodeError:
+ x = x.decode('latin1')
+ try:
+ x = validator(x)
+ except ValidationError, err:
+ print red('* ' + str(err))
+ continue
+ break
+ d[key] = x
+
+
+if sys.version_info >= (3, 0):
+ # remove Unicode literal prefixes
+ def _convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
+ return rex.sub('\\1', source)
+
+ for f in ['QUICKSTART_CONF', 'EPUB_CONFIG', 'INTERSPHINX_CONFIG']:
+ globals()[f] = _convert_python_source(globals()[f])
+
+ del _convert_python_source
+
+
+def ask_user(d):
+ """Ask the user for quickstart values missing from *d*.
+
+ Values are:
+
+ * path: root path
+ * sep: separate source and build dirs (bool)
+ * dot: replacement for dot in _templates etc.
+ * project: project name
+ * author: author names
+ * version: version of project
+ * release: release of project
+ * suffix: source file suffix
+ * master: master document name
+ * epub: use epub (bool)
+ * ext_*: extensions to use (bools)
+ * makefile: make Makefile
+ * batchfile: make command file
+ """
+
+ print bold('Welcome to the Sphinx %s quickstart utility.') % __version__
+ print '''
+Please enter values for the following settings (just press Enter to
+accept a default value, if one is given in brackets).'''
+
+ if 'path' in d:
+ print bold('''
+Selected root path: %s''' % d['path'])
+ else:
+ print '''
+Enter the root path for documentation.'''
+ do_prompt(d, 'path', 'Root path for the documentation', '.', is_path)
+
+ while path.isfile(path.join(d['path'], 'conf.py')) or \
+ path.isfile(path.join(d['path'], 'source', 'conf.py')):
+ print
+ print bold('Error: an existing conf.py has been found in the '
+ 'selected root path.')
+ print 'sphinx-quickstart will not overwrite existing Sphinx projects.'
+ print
+ do_prompt(d, 'path', 'Please enter a new root path (or just Enter '
+ 'to exit)', '', is_path)
+ if not d['path']:
+ sys.exit(1)
+
+ if 'sep' not in d:
+ print '''
+You have two options for placing the build directory for Sphinx output.
+Either, you use a directory "_build" within the root path, or you separate
+"source" and "build" directories within the root path.'''
+ do_prompt(d, 'sep', 'Separate source and build directories (y/n)', 'n',
+ boolean)
+
+ if 'dot' not in d:
+ print '''
+Inside the root directory, two more directories will be created; "_templates"
+for custom HTML templates and "_static" for custom stylesheets and other static
+files. You can enter another prefix (such as ".") to replace the underscore.'''
+ do_prompt(d, 'dot', 'Name prefix for templates and static dir', '_', ok)
+
+ if 'project' not in d:
+ print '''
+The project name will occur in several places in the built documentation.'''
+ do_prompt(d, 'project', 'Project name')
+ if 'author' not in d:
+ do_prompt(d, 'author', 'Author name(s)')
+
+ if 'version' not in d:
+ print '''
+Sphinx has the notion of a "version" and a "release" for the
+software. Each version can have multiple releases. For example, for
+Python the version is something like 2.5 or 3.0, while the release is
+something like 2.5.1 or 3.0a1. If you don't need this dual structure,
+just set both to the same value.'''
+ do_prompt(d, 'version', 'Project version')
+ if 'release' not in d:
+ do_prompt(d, 'release', 'Project release', d['version'])
+
+ if 'suffix' not in d:
+ print '''
+The file name suffix for source files. Commonly, this is either ".txt"
+or ".rst". Only files with this suffix are considered documents.'''
+ do_prompt(d, 'suffix', 'Source file suffix', '.rst', suffix)
+
+ if 'master' not in d:
+ print '''
+One document is special in that it is considered the top node of the
+"contents tree", that is, it is the root of the hierarchical structure
+of the documents. Normally, this is "index", but if your "index"
+document is a custom template, you can also set this to another filename.'''
+ do_prompt(d, 'master', 'Name of your master document (without suffix)',
+ 'index')
+
+ while path.isfile(path.join(d['path'], d['master']+d['suffix'])) or \
+ path.isfile(path.join(d['path'], 'source', d['master']+d['suffix'])):
+ print
+ print bold('Error: the master file %s has already been found in the '
+ 'selected root path.' % (d['master']+d['suffix']))
+ print 'sphinx-quickstart will not overwrite the existing file.'
+ print
+ do_prompt(d, 'master', 'Please enter a new file name, or rename the '
+ 'existing file and press Enter', d['master'])
+
+ if 'epub' not in d:
+ print '''
+Sphinx can also add configuration for epub output:'''
+ do_prompt(d, 'epub', 'Do you want to use the epub builder (y/n)',
+ 'n', boolean)
+
+ if 'ext_autodoc' not in d:
+ print '''
+Please indicate if you want to use one of the following Sphinx extensions:'''
+ do_prompt(d, 'ext_autodoc', 'autodoc: automatically insert docstrings '
+ 'from modules (y/n)', 'n', boolean)
+ if 'ext_doctest' not in d:
+ do_prompt(d, 'ext_doctest', 'doctest: automatically test code snippets '
+ 'in doctest blocks (y/n)', 'n', boolean)
+ if 'ext_intersphinx' not in d:
+ do_prompt(d, 'ext_intersphinx', 'intersphinx: link between Sphinx '
+ 'documentation of different projects (y/n)', 'n', boolean)
+ if 'ext_todo' not in d:
+ do_prompt(d, 'ext_todo', 'todo: write "todo" entries '
+ 'that can be shown or hidden on build (y/n)', 'n', boolean)
+ if 'ext_coverage' not in d:
+ do_prompt(d, 'ext_coverage', 'coverage: checks for documentation '
+ 'coverage (y/n)', 'n', boolean)
+ if 'ext_pngmath' not in d:
+ do_prompt(d, 'ext_pngmath', 'pngmath: include math, rendered '
+ 'as PNG images (y/n)', 'n', boolean)
+ if 'ext_mathjax' not in d:
+ do_prompt(d, 'ext_mathjax', 'mathjax: include math, rendered in the '
+ 'browser by MathJax (y/n)', 'n', boolean)
+ if d['ext_pngmath'] and d['ext_mathjax']:
+ print '''Note: pngmath and mathjax cannot be enabled at the same time.
+pngmath has been deselected.'''
+ d['ext_pngmath'] = False
+ if 'ext_ifconfig' not in d:
+ do_prompt(d, 'ext_ifconfig', 'ifconfig: conditional inclusion of '
+ 'content based on config values (y/n)', 'n', boolean)
+ if 'ext_viewcode' not in d:
+ do_prompt(d, 'ext_viewcode', 'viewcode: include links to the source '
+ 'code of documented Python objects (y/n)', 'n', boolean)
+
+ if 'makefile' not in d:
+ print '''
+A Makefile and a Windows command file can be generated for you so that you
+only have to run e.g. `make html' instead of invoking sphinx-build
+directly.'''
+ do_prompt(d, 'makefile', 'Create Makefile? (y/n)', 'y', boolean)
+ if 'batchfile' not in d:
+ do_prompt(d, 'batchfile', 'Create Windows command file? (y/n)',
+ 'y', boolean)
+ print
+
+
+def generate(d, overwrite=True, silent=False):
+ """Generate project based on values in *d*."""
+
+ texescape.init()
+ indent = ' ' * 4
+
+ if 'mastertoctree' not in d:
+ d['mastertoctree'] = ''
+ if 'mastertocmaxdepth' not in d:
+ d['mastertocmaxdepth'] = 2
+
+ d['project_fn'] = make_filename(d['project'])
+ d['project_manpage'] = d['project_fn'].lower()
+ d['now'] = time.asctime()
+ d['project_underline'] = column_width(d['project']) * '='
+ extensions = (',\n' + indent).join(
+ repr('sphinx.ext.' + name)
+ for name in ('autodoc', 'doctest', 'intersphinx', 'todo', 'coverage',
+ 'pngmath', 'mathjax', 'ifconfig', 'viewcode')
+ if d.get('ext_' + name))
+ if extensions:
+ d['extensions'] = '\n' + indent + extensions + ',\n'
+ else:
+ d['extensions'] = extensions
+ d['copyright'] = time.strftime('%Y') + ', ' + d['author']
+ d['author_texescaped'] = unicode(d['author']).\
+ translate(texescape.tex_escape_map)
+ d['project_doc'] = d['project'] + ' Documentation'
+ d['project_doc_texescaped'] = unicode(d['project'] + ' Documentation').\
+ translate(texescape.tex_escape_map)
+
+ # escape backslashes and single quotes in strings that are put into
+ # a Python string literal
+ for key in ('project', 'project_doc', 'project_doc_texescaped',
+ 'author', 'author_texescaped', 'copyright',
+ 'version', 'release', 'master'):
+ d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'")
+
+ if not path.isdir(d['path']):
+ mkdir_p(d['path'])
+
+ srcdir = d['sep'] and path.join(d['path'], 'source') or d['path']
+
+ mkdir_p(srcdir)
+ if d['sep']:
+ builddir = path.join(d['path'], 'build')
+ d['exclude_patterns'] = ''
+ else:
+ builddir = path.join(srcdir, d['dot'] + 'build')
+ d['exclude_patterns'] = repr(d['dot'] + 'build')
+ mkdir_p(builddir)
+ mkdir_p(path.join(srcdir, d['dot'] + 'templates'))
+ mkdir_p(path.join(srcdir, d['dot'] + 'static'))
+
+ def write_file(fpath, content, newline=None):
+ if overwrite or not path.isfile(fpath):
+ print 'Creating file %s.' % fpath
+ f = open(fpath, 'wt', encoding='utf-8', newline=newline)
+ try:
+ f.write(content)
+ finally:
+ f.close()
+ else:
+ print 'File %s already exists, skipping.' % fpath
+
+ conf_text = QUICKSTART_CONF % d
+ if d['epub']:
+ conf_text += EPUB_CONFIG % d
+ if d.get('ext_intersphinx'):
+ conf_text += INTERSPHINX_CONFIG
+
+ write_file(path.join(srcdir, 'conf.py'), conf_text)
+
+ masterfile = path.join(srcdir, d['master'] + d['suffix'])
+ write_file(masterfile, MASTER_FILE % d)
+
+ if d['makefile']:
+ d['rsrcdir'] = d['sep'] and 'source' or '.'
+ d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build'
+ # use binary mode, to avoid writing \r\n on Windows
+ write_file(path.join(d['path'], 'Makefile'), MAKEFILE % d, u'\n')
+
+ if d['batchfile']:
+ d['rsrcdir'] = d['sep'] and 'source' or '.'
+ d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build'
+ write_file(path.join(d['path'], 'make.bat'), BATCHFILE % d, u'\r\n')
+
+ if silent:
+ return
+ print
+ print bold('Finished: An initial directory structure has been created.')
+ print '''
+You should now populate your master file %s and create other documentation
+source files. ''' % masterfile + ((d['makefile'] or d['batchfile']) and '''\
+Use the Makefile to build the docs, like so:
+ make builder
+''' or '''\
+Use the sphinx-build command to build the docs, like so:
+ sphinx-build -b builder %s %s
+''' % (srcdir, builddir)) + '''\
+where "builder" is one of the supported builders, e.g. html, latex or linkcheck.
+'''
+
+
+def main(argv=sys.argv):
+ if not color_terminal():
+ nocolor()
+
+ d = {}
+ if len(argv) > 3:
+ print 'Usage: sphinx-quickstart [root]'
+ sys.exit(1)
+ elif len(argv) == 2:
+ d['path'] = argv[1]
+ try:
+ ask_user(d)
+ except (KeyboardInterrupt, EOFError):
+ print
+ print '[Interrupted.]'
+ return
+ generate(d)
diff --git a/sphinx/roles.py b/sphinx/roles.py
new file mode 100644
index 0000000..c31ec05
--- /dev/null
+++ b/sphinx/roles.py
@@ -0,0 +1,317 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.roles
+ ~~~~~~~~~~~~
+
+ Handlers for additional ReST roles.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from docutils import nodes, utils
+from docutils.parsers.rst import roles
+
+from sphinx import addnodes
+from sphinx.locale import _
+from sphinx.util import ws_re
+from sphinx.util.nodes import split_explicit_title, process_index_entry, \
+ set_role_source_info
+
+
+generic_docroles = {
+ 'command' : nodes.strong,
+ 'dfn' : nodes.emphasis,
+ 'kbd' : nodes.literal,
+ 'mailheader' : addnodes.literal_emphasis,
+ 'makevar' : nodes.strong,
+ 'manpage' : addnodes.literal_emphasis,
+ 'mimetype' : addnodes.literal_emphasis,
+ 'newsgroup' : addnodes.literal_emphasis,
+ 'program' : nodes.strong, # XXX should be an x-ref
+ 'regexp' : nodes.literal,
+}
+
+for rolename, nodeclass in generic_docroles.iteritems():
+ generic = roles.GenericRole(rolename, nodeclass)
+ role = roles.CustomRole(rolename, generic, {'classes': [rolename]})
+ roles.register_local_role(rolename, role)
+
+# -- generic cross-reference role ----------------------------------------------
+
+class XRefRole(object):
+ """
+ A generic cross-referencing role. To create a callable that can be used as
+ a role function, create an instance of this class.
+
+ The general features of this role are:
+
+ * Automatic creation of a reference and a content node.
+ * Optional separation of title and target with `title <target>`.
+ * The implementation is a class rather than a function to make
+ customization easier.
+
+ Customization can be done in two ways:
+
+ * Supplying constructor parameters:
+ * `fix_parens` to normalize parentheses (strip from target, and add to
+ title if configured)
+ * `lowercase` to lowercase the target
+ * `nodeclass` and `innernodeclass` select the node classes for
+ the reference and the content node
+
+ * Subclassing and overwriting `process_link()` and/or `result_nodes()`.
+ """
+
+ nodeclass = addnodes.pending_xref
+ innernodeclass = nodes.literal
+
+ def __init__(self, fix_parens=False, lowercase=False,
+ nodeclass=None, innernodeclass=None, warn_dangling=False):
+ self.fix_parens = fix_parens
+ self.lowercase = lowercase
+ self.warn_dangling = warn_dangling
+ if nodeclass is not None:
+ self.nodeclass = nodeclass
+ if innernodeclass is not None:
+ self.innernodeclass = innernodeclass
+
+ def _fix_parens(self, env, has_explicit_title, title, target):
+ if not has_explicit_title:
+ if title.endswith('()'):
+ # remove parentheses
+ title = title[:-2]
+ if env.config.add_function_parentheses:
+ # add them back to all occurrences if configured
+ title += '()'
+ # remove parentheses from the target too
+ if target.endswith('()'):
+ target = target[:-2]
+ return title, target
+
+ def __call__(self, typ, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ env = inliner.document.settings.env
+ if not typ:
+ typ = env.config.default_role
+ else:
+ typ = typ.lower()
+ if ':' not in typ:
+ domain, role = '', typ
+ classes = ['xref', role]
+ else:
+ domain, role = typ.split(':', 1)
+ classes = ['xref', domain, '%s-%s' % (domain, role)]
+ # if the first character is a bang, don't cross-reference at all
+ if text[0:1] == '!':
+ text = utils.unescape(text)[1:]
+ if self.fix_parens:
+ text, tgt = self._fix_parens(env, False, text, "")
+ innernode = self.innernodeclass(rawtext, text, classes=classes)
+ return self.result_nodes(inliner.document, env, innernode,
+ is_ref=False)
+ # split title and target in role content
+ has_explicit_title, title, target = split_explicit_title(text)
+ title = utils.unescape(title)
+ target = utils.unescape(target)
+ # fix-up title and target
+ if self.lowercase:
+ target = target.lower()
+ if self.fix_parens:
+ title, target = self._fix_parens(
+ env, has_explicit_title, title, target)
+ # create the reference node
+ refnode = self.nodeclass(rawtext, reftype=role, refdomain=domain,
+ refexplicit=has_explicit_title)
+ # we may need the line number for warnings
+ set_role_source_info(inliner, lineno, refnode)
+ title, target = self.process_link(
+ env, refnode, has_explicit_title, title, target)
+ # now that the target and title are finally determined, set them
+ refnode['reftarget'] = target
+ refnode += self.innernodeclass(rawtext, title, classes=classes)
+ # we also need the source document
+ refnode['refdoc'] = env.docname
+ refnode['refwarn'] = self.warn_dangling
+ # result_nodes allow further modification of return values
+ return self.result_nodes(inliner.document, env, refnode, is_ref=True)
+
+ # methods that can be overwritten
+
+ def process_link(self, env, refnode, has_explicit_title, title, target):
+ """Called after parsing title and target text, and creating the
+ reference node (given in *refnode*). This method can alter the
+ reference node and must return a new (or the same) ``(title, target)``
+ tuple.
+ """
+ return title, ws_re.sub(' ', target)
+
+ def result_nodes(self, document, env, node, is_ref):
+ """Called before returning the finished nodes. *node* is the reference
+ node if one was created (*is_ref* is then true), else the content node.
+ This method can add other nodes and must return a ``(nodes, messages)``
+ tuple (the usual return value of a role function).
+ """
+ return [node], []
+
+
+def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
+ options={}, content=[]):
+ """Role for PEP/RFC references that generate an index entry."""
+ env = inliner.document.settings.env
+ if not typ:
+ typ = env.config.default_role
+ else:
+ typ = typ.lower()
+ text = utils.unescape(etext)
+ targetid = 'index-%s' % env.new_serialno('index')
+ indexnode = addnodes.index()
+ targetnode = nodes.target('', '', ids=[targetid])
+ inliner.document.note_explicit_target(targetnode)
+ if typ == 'pep':
+ indexnode['entries'] = [
+ ('single', _('Python Enhancement Proposals; PEP %s') % text,
+ targetid, '')]
+ anchor = ''
+ anchorindex = text.find('#')
+ if anchorindex > 0:
+ text, anchor = text[:anchorindex], text[anchorindex:]
+ try:
+ pepnum = int(text)
+ except ValueError:
+ msg = inliner.reporter.error('invalid PEP number %s' % text,
+ line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ ref = inliner.document.settings.pep_base_url + 'pep-%04d' % pepnum
+ sn = nodes.strong('PEP '+text, 'PEP '+text)
+ rn = nodes.reference('', '', internal=False, refuri=ref+anchor,
+ classes=[typ])
+ rn += sn
+ return [indexnode, targetnode, rn], []
+ elif typ == 'rfc':
+ indexnode['entries'] = [('single', 'RFC; RFC %s' % text, targetid, '')]
+ anchor = ''
+ anchorindex = text.find('#')
+ if anchorindex > 0:
+ text, anchor = text[:anchorindex], text[anchorindex:]
+ try:
+ rfcnum = int(text)
+ except ValueError:
+ msg = inliner.reporter.error('invalid RFC number %s' % text,
+ line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
+ sn = nodes.strong('RFC '+text, 'RFC '+text)
+ rn = nodes.reference('', '', internal=False, refuri=ref+anchor,
+ classes=[typ])
+ rn += sn
+ return [indexnode, targetnode, rn], []
+
+
+_amp_re = re.compile(r'(?<!&)&(?![&\s])')
+
+def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
+ text = utils.unescape(text)
+ if typ == 'menuselection':
+ text = text.replace('-->', u'\N{TRIANGULAR BULLET}')
+ spans = _amp_re.split(text)
+
+ node = nodes.emphasis(rawtext=rawtext)
+ for i, span in enumerate(spans):
+ span = span.replace('&&', '&')
+ if i == 0:
+ if len(span) > 0:
+ textnode = nodes.Text(span)
+ node += textnode
+ continue
+ accel_node = nodes.inline()
+ letter_node = nodes.Text(span[0])
+ accel_node += letter_node
+ accel_node['classes'].append('accelerator')
+ node += accel_node
+ textnode = nodes.Text(span[1:])
+ node += textnode
+
+ node['classes'].append(typ)
+ return [node], []
+
+_litvar_re = re.compile('{([^}]+)}')
+
+def emph_literal_role(typ, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ text = utils.unescape(text)
+ pos = 0
+ retnode = nodes.literal(role=typ.lower(), classes=[typ])
+ for m in _litvar_re.finditer(text):
+ if m.start() > pos:
+ txt = text[pos:m.start()]
+ retnode += nodes.Text(txt, txt)
+ retnode += nodes.emphasis(m.group(1), m.group(1))
+ pos = m.end()
+ if pos < len(text):
+ retnode += nodes.Text(text[pos:], text[pos:])
+ return [retnode], []
+
+
+_abbr_re = re.compile('\((.*)\)$', re.S)
+
+def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
+ text = utils.unescape(text)
+ m = _abbr_re.search(text)
+ if m is None:
+ return [addnodes.abbreviation(text, text)], []
+ abbr = text[:m.start()].strip()
+ expl = m.group(1)
+ return [addnodes.abbreviation(abbr, abbr, explanation=expl)], []
+
+
+def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
+ # create new reference target
+ env = inliner.document.settings.env
+ targetid = 'index-%s' % env.new_serialno('index')
+ targetnode = nodes.target('', '', ids=[targetid])
+ # split text and target in role content
+ has_explicit_title, title, target = split_explicit_title(text)
+ title = utils.unescape(title)
+ target = utils.unescape(target)
+ # if an explicit target is given, we can process it as a full entry
+ if has_explicit_title:
+ entries = process_index_entry(target, targetid)
+ # otherwise we just create a "single" entry
+ else:
+ # but allow giving main entry
+ main = ''
+ if target.startswith('!'):
+ target = target[1:]
+ title = title[1:]
+ main = 'main'
+ entries = [('single', target, targetid, main)]
+ indexnode = addnodes.index()
+ indexnode['entries'] = entries
+ set_role_source_info(inliner, lineno, indexnode)
+ textnode = nodes.Text(title, title)
+ return [indexnode, targetnode, textnode], []
+
+
+specific_docroles = {
+ # links to download references
+ 'download': XRefRole(nodeclass=addnodes.download_reference),
+ # links to documents
+ 'doc': XRefRole(warn_dangling=True),
+
+ 'pep': indexmarkup_role,
+ 'rfc': indexmarkup_role,
+ 'guilabel': menusel_role,
+ 'menuselection': menusel_role,
+ 'file': emph_literal_role,
+ 'samp': emph_literal_role,
+ 'abbr': abbr_role,
+ 'index': index_role,
+}
+
+for rolename, func in specific_docroles.iteritems():
+ roles.register_local_role(rolename, func)
diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py
new file mode 100644
index 0000000..bd95ecc
--- /dev/null
+++ b/sphinx/search/__init__.py
@@ -0,0 +1,333 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search
+ ~~~~~~~~~~~~~
+
+ Create a full-text search index for offline search.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from __future__ import with_statement
+import re
+import cPickle as pickle
+
+from docutils.nodes import raw, comment, title, Text, NodeVisitor, SkipNode
+
+from sphinx.util import jsdump, rpartition
+
+
+class SearchLanguage(object):
+ """
+ This class is the base class for search natural language preprocessors. If
+ you want to add support for a new language, you should override the methods
+ of this class.
+
+ You should override `lang` class property too (e.g. 'en', 'fr' and so on).
+
+ .. attribute:: stopwords
+
+ This is a set of stop words of the target language. Default `stopwords`
+ is empty. This word is used for building index and embedded in JS.
+
+ .. attribute:: js_stemmer_code
+
+ Return stemmer class of JavaScript version. This class' name should be
+ ``Stemmer`` and this class must have ``stemWord`` method. This string is
+ embedded as-is in searchtools.js.
+
+ This class is used to preprocess search word which Sphinx HTML readers
+ type, before searching index. Default implementation does nothing.
+ """
+ lang = None
+ stopwords = set()
+ js_stemmer_code = """
+/**
+ * Dummy stemmer for languages without stemming rules.
+ */
+var Stemmer = function() {
+ this.stemWord = function(w) {
+ return w;
+ }
+}
+"""
+
+ _word_re = re.compile(r'\w+(?u)')
+
+ def __init__(self, options):
+ self.options = options
+ self.init(options)
+
+ def init(self, options):
+ """
+ Initialize the class with the options the user has given.
+ """
+
+ def split(self, input):
+ """
+ This method splits a sentence into words. Default splitter splits input
+ at white spaces, which should be enough for most languages except CJK
+ languages.
+ """
+ return self._word_re.findall(input)
+
+ def stem(self, word):
+ """
+ This method implements stemming algorithm of the Python version.
+
+ Default implementation does nothing. You should implement this if the
+ language has any stemming rules.
+
+ This class is used to preprocess search words before registering them in
+ the search index. The stemming of the Python version and the JS version
+ (given in the js_stemmer_code attribute) must be compatible.
+ """
+ return word
+
+ def word_filter(self, word):
+ """
+ Return true if the target word should be registered in the search index.
+ This method is called after stemming.
+ """
+ return not (((len(word) < 3) and (12353 < ord(word[0]) < 12436)) or
+ (ord(word[0]) < 256 and (len(word) < 3 or word in self.stopwords or
+ word.isdigit())))
+
+
+from sphinx.search import en, ja
+
+languages = {
+ 'en': en.SearchEnglish,
+ 'ja': ja.SearchJapanese,
+}
+
+
+class _JavaScriptIndex(object):
+ """
+ The search index as javascript file that calls a function
+ on the documentation search object to register the index.
+ """
+
+ PREFIX = 'Search.setIndex('
+ SUFFIX = ')'
+
+ def dumps(self, data):
+ return self.PREFIX + jsdump.dumps(data) + self.SUFFIX
+
+ def loads(self, s):
+ data = s[len(self.PREFIX):-len(self.SUFFIX)]
+ if not data or not s.startswith(self.PREFIX) or not \
+ s.endswith(self.SUFFIX):
+ raise ValueError('invalid data')
+ return jsdump.loads(data)
+
+ def dump(self, data, f):
+ f.write(self.dumps(data))
+
+ def load(self, f):
+ return self.loads(f.read())
+
+
+js_index = _JavaScriptIndex()
+
+
+class WordCollector(NodeVisitor):
+ """
+ A special visitor that collects words for the `IndexBuilder`.
+ """
+
+ def __init__(self, document, lang):
+ NodeVisitor.__init__(self, document)
+ self.found_words = []
+ self.found_title_words = []
+ self.lang = lang
+
+ def dispatch_visit(self, node):
+ if node.__class__ is comment:
+ raise SkipNode
+ if node.__class__ is raw:
+ # Some people might put content in raw HTML that should be searched,
+ # so we just amateurishly strip HTML tags and index the remaining
+ # content
+ nodetext = re.sub(r'(?is)<style.*?</style>', '', node.astext())
+ nodetext = re.sub(r'(?is)<script.*?</script>', '', nodetext)
+ nodetext = re.sub(r'<[^<]+?>', '', nodetext)
+ self.found_words.extend(self.lang.split(nodetext))
+ raise SkipNode
+ if node.__class__ is Text:
+ self.found_words.extend(self.lang.split(node.astext()))
+ elif node.__class__ is title:
+ self.found_title_words.extend(self.lang.split(node.astext()))
+
+
+class IndexBuilder(object):
+ """
+ Helper class that creates a searchindex based on the doctrees
+ passed to the `feed` method.
+ """
+ formats = {
+ 'jsdump': jsdump,
+ 'pickle': pickle
+ }
+
+ def __init__(self, env, lang, options, scoring):
+ self.env = env
+ # filename -> title
+ self._titles = {}
+ # stemmed word -> set(filenames)
+ self._mapping = {}
+ # stemmed words in titles -> set(filenames)
+ self._title_mapping = {}
+ # word -> stemmed word
+ self._stem_cache = {}
+ # objtype -> index
+ self._objtypes = {}
+ # objtype index -> (domain, type, objname (localized))
+ self._objnames = {}
+ # add language-specific SearchLanguage instance
+ self.lang = languages[lang](options)
+
+ if scoring:
+ with open(scoring, 'rb') as fp:
+ self.js_scorer_code = fp.read().decode('utf-8')
+ else:
+ self.js_scorer_code = u''
+
+ def load(self, stream, format):
+ """Reconstruct from frozen data."""
+ if isinstance(format, basestring):
+ format = self.formats[format]
+ frozen = format.load(stream)
+ # if an old index is present, we treat it as not existing.
+ if not isinstance(frozen, dict) or \
+ frozen.get('envversion') != self.env.version:
+ raise ValueError('old format')
+ index2fn = frozen['filenames']
+ self._titles = dict(zip(index2fn, frozen['titles']))
+
+ def load_terms(mapping):
+ rv = {}
+ for k, v in mapping.iteritems():
+ if isinstance(v, int):
+ rv[k] = set([index2fn[v]])
+ else:
+ rv[k] = set(index2fn[i] for i in v)
+ return rv
+
+ self._mapping = load_terms(frozen['terms'])
+ self._title_mapping = load_terms(frozen['titleterms'])
+ # no need to load keywords/objtypes
+
+ def dump(self, stream, format):
+ """Dump the frozen index to a stream."""
+ if isinstance(format, basestring):
+ format = self.formats[format]
+ format.dump(self.freeze(), stream)
+
+ def get_objects(self, fn2index):
+ rv = {}
+ otypes = self._objtypes
+ onames = self._objnames
+ for domainname, domain in self.env.domains.iteritems():
+ for fullname, dispname, type, docname, anchor, prio in \
+ domain.get_objects():
+ # XXX use dispname?
+ if docname not in fn2index:
+ continue
+ if prio < 0:
+ continue
+ prefix, name = rpartition(fullname, '.')
+ pdict = rv.setdefault(prefix, {})
+ try:
+ typeindex = otypes[domainname, type]
+ except KeyError:
+ typeindex = len(otypes)
+ otypes[domainname, type] = typeindex
+ otype = domain.object_types.get(type)
+ if otype:
+ # use unicode() to fire translation proxies
+ onames[typeindex] = (domainname, type,
+ unicode(domain.get_type_name(otype)))
+ else:
+ onames[typeindex] = (domainname, type, type)
+ if anchor == fullname:
+ shortanchor = ''
+ elif anchor == type + '-' + fullname:
+ shortanchor = '-'
+ else:
+ shortanchor = anchor
+ pdict[name] = (fn2index[docname], typeindex, prio, shortanchor)
+ return rv
+
+ def get_terms(self, fn2index):
+ rvs = {}, {}
+ for rv, mapping in zip(rvs, (self._mapping, self._title_mapping)):
+ for k, v in mapping.iteritems():
+ if len(v) == 1:
+ fn, = v
+ if fn in fn2index:
+ rv[k] = fn2index[fn]
+ else:
+ rv[k] = [fn2index[fn] for fn in v if fn in fn2index]
+ return rvs
+
+ def freeze(self):
+ """Create a usable data structure for serializing."""
+ filenames = self._titles.keys()
+ titles = self._titles.values()
+ fn2index = dict((f, i) for (i, f) in enumerate(filenames))
+ terms, title_terms = self.get_terms(fn2index)
+
+ objects = self.get_objects(fn2index) # populates _objtypes
+ objtypes = dict((v, k[0] + ':' + k[1])
+ for (k, v) in self._objtypes.iteritems())
+ objnames = self._objnames
+ return dict(filenames=filenames, titles=titles, terms=terms,
+ objects=objects, objtypes=objtypes, objnames=objnames,
+ titleterms=title_terms, envversion=self.env.version)
+
+ def prune(self, filenames):
+ """Remove data for all filenames not in the list."""
+ new_titles = {}
+ for filename in filenames:
+ if filename in self._titles:
+ new_titles[filename] = self._titles[filename]
+ self._titles = new_titles
+ for wordnames in self._mapping.itervalues():
+ wordnames.intersection_update(filenames)
+ for wordnames in self._title_mapping.itervalues():
+ wordnames.intersection_update(filenames)
+
+ def feed(self, filename, title, doctree):
+ """Feed a doctree to the index."""
+ self._titles[filename] = title
+
+ visitor = WordCollector(doctree, self.lang)
+ doctree.walk(visitor)
+
+ # memoize self.lang.stem
+ def stem(word):
+ try:
+ return self._stem_cache[word]
+ except KeyError:
+ self._stem_cache[word] = self.lang.stem(word)
+ return self._stem_cache[word]
+ _filter = self.lang.word_filter
+
+ for word in visitor.found_title_words:
+ word = stem(word)
+ if _filter(word):
+ self._title_mapping.setdefault(word, set()).add(filename)
+
+ for word in visitor.found_words:
+ word = stem(word)
+ if word not in self._title_mapping and _filter(word):
+ self._mapping.setdefault(word, set()).add(filename)
+
+ def context_for_searchtool(self):
+ return dict(
+ search_language_stemming_code = self.lang.js_stemmer_code,
+ search_language_stop_words =
+ jsdump.dumps(sorted(self.lang.stopwords)),
+ search_scorer_tool = self.js_scorer_code,
+ )
diff --git a/sphinx/search/en.py b/sphinx/search/en.py
new file mode 100644
index 0000000..33e8177
--- /dev/null
+++ b/sphinx/search/en.py
@@ -0,0 +1,244 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.en
+ ~~~~~~~~~~~~~~~~
+
+ English search language: includes the JS porter stemmer.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage
+
+try:
+ # http://bitbucket.org/methane/porterstemmer/
+ from porterstemmer import Stemmer as CStemmer
+ CSTEMMER = True
+except ImportError:
+ from sphinx.util.stemmer import PorterStemmer
+ CSTEMMER = False
+
+
+english_stopwords = set("""
+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
+""".split())
+
+js_porter_stemmer = """
+/**
+ * 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;
+ }
+}
+"""
+
+
+class SearchEnglish(SearchLanguage):
+ lang = 'en'
+ js_stemmer_code = js_porter_stemmer
+ stopwords = english_stopwords
+
+ def init(self, options):
+ if CSTEMMER:
+ class Stemmer(CStemmer):
+ def stem(self, word):
+ return self(word.lower())
+ else:
+ class Stemmer(PorterStemmer):
+ """All those porter stemmer implementations look hideous;
+ make at least the stem method nicer.
+ """
+ def stem(self, word):
+ word = word.lower()
+ return PorterStemmer.stem(self, word, 0, len(word) - 1)
+
+ self.stemmer = Stemmer()
+
+ def stem(self, word):
+ return self.stemmer.stem(word)
diff --git a/sphinx/search/ja.py b/sphinx/search/ja.py
new file mode 100644
index 0000000..d5a7b4a
--- /dev/null
+++ b/sphinx/search/ja.py
@@ -0,0 +1,276 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.ja
+ ~~~~~~~~~~~~~~~~
+
+ Japanese search language: includes routine to split words.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+# Python Version of TinySegmenter
+# (http://chasen.org/~taku/software/TinySegmenter/)
+# TinySegmenter is super compact Japanese tokenizer.
+#
+# TinySegmenter was originally developed by Taku Kudo <taku(at)chasen.org>.
+# Python Version was developed by xnights <programming.magic(at)gmail.com>.
+# For details, see http://programming-magic.com/?id=170
+
+import os
+import re
+import sys
+
+try:
+ import MeCab
+ native_module = True
+except ImportError:
+ native_module = False
+
+from sphinx.search import SearchLanguage
+
+
+class MecabBinder(object):
+ def __init__(self, options):
+ self.ctypes_libmecab = None
+ self.ctypes_mecab = None
+ if not native_module:
+ self.init_ctypes(options)
+ else:
+ self.init_native(options)
+ self.dict_encode = options.get('dic_enc', 'utf-8')
+
+ def split(self, input):
+ input2 = input.encode(self.dict_encode)
+ if native_module:
+ result = self.native.parse(input2)
+ else:
+ result = self.ctypes_libmecab.mecab_sparse_tostr(
+ self.ctypes_mecab, input)
+ return result.decode(self.dict_encode).split(' ')
+
+ def init_native(self, options):
+ param = '-Owakati'
+ dict = options.get('dict')
+ if dict:
+ param += ' -d %s' % dict
+ self.native = MeCab.Tagger(param)
+
+ def init_ctypes(self, options):
+ import ctypes.util
+
+ lib = options.get('lib')
+
+ if lib is None:
+ if sys.platform.startswith('win'):
+ libname = 'libmecab.dll'
+ else:
+ libname = 'mecab'
+ libpath = ctypes.util.find_library(libname)
+ elif os.path.basename(lib) == lib:
+ libpath = ctypes.util.find_library(lib)
+ else:
+ libpath = None
+ if os.path.exists(lib):
+ libpath = lib
+ if libpath is None:
+ raise RuntimeError('MeCab dynamic library is not available')
+
+ param = 'mecab -Owakati'
+ dict = options.get('dict')
+ if dict:
+ param += ' -d %s' % dict
+
+ self.ctypes_libmecab = ctypes.CDLL(libpath)
+ self.ctypes_libmecab.mecab_sparse_tostr.restype = ctypes.c_char_p
+ self.ctypes_mecab = self.libmecab.mecab_new2(param)
+
+ def __del__(self):
+ if self.ctypes_libmecab:
+ self.ctypes_libmecab.mecab_destroy(self.ctypes_mecab)
+
+
+class TinySegmenter(object):
+ patterns_ = dict([(re.compile(pattern), value) for pattern, value in {
+ u'[一二三四五六七八九十百千万億兆]': u'M',
+ u'[一-龠々〆ヵヶ]': u'H',
+ u'[ぁ-ん]': u'I',
+ u'[ァ-ヴーア-ン゙ー]': u'K',
+ u'[a-zA-Za-zA-Z]': u'A',
+ u'[0-90-9]': u'N',
+ }.iteritems()])
+ BIAS__ = -332
+ BC1__ = {u'HH':6,u'II':2461,u'KH':406,u'OH':-1378}
+ BC2__ = {u'AA':-3267,u'AI':2744,u'AN':-878,u'HH':-4070,u'HM':-1711,u'HN':4012,u'HO':3761,u'IA':1327,u'IH':-1184,u'II':-1332,u'IK':1721,u'IO':5492,u'KI':3831,u'KK':-8741,u'MH':-3132,u'MK':3334,u'OO':-2920}
+ BC3__ = {u'HH':996,u'HI':626,u'HK':-721,u'HN':-1307,u'HO':-836,u'IH':-301,u'KK':2762,u'MK':1079,u'MM':4034,u'OA':-1652,u'OH':266}
+ BP1__ = {u'BB':295,u'OB':304,u'OO':-125,u'UB':352}
+ BP2__ = {u'BO':60,u'OO':-1762}
+ BQ1__ = {u'BHH':1150,u'BHM':1521,u'BII':-1158,u'BIM':886,u'BMH':1208,u'BNH':449,u'BOH':-91,u'BOO':-2597,u'OHI':451,u'OIH':-296,u'OKA':1851,u'OKH':-1020,u'OKK':904,u'OOO':2965}
+ BQ2__ = {u'BHH':118,u'BHI':-1159,u'BHM':466,u'BIH':-919,u'BKK':-1720,u'BKO':864,u'OHH':-1139,u'OHM':-181,u'OIH':153,u'UHI':-1146}
+ BQ3__ = {u'BHH':-792,u'BHI':2664,u'BII':-299,u'BKI':419,u'BMH':937,u'BMM':8335,u'BNN':998,u'BOH':775,u'OHH':2174,u'OHM':439,u'OII':280,u'OKH':1798,u'OKI':-793,u'OKO':-2242,u'OMH':-2402,u'OOO':11699}
+ BQ4__ = {u'BHH':-3895,u'BIH':3761,u'BII':-4654,u'BIK':1348,u'BKK':-1806,u'BMI':-3385,u'BOO':-12396,u'OAH':926,u'OHH':266,u'OHK':-2036,u'ONN':-973}
+ BW1__ = {u',と':660,u',同':727,u'B1あ':1404,u'B1同':542,u'、と':660,u'、同':727,u'」と':1682,u'あっ':1505,u'いう':1743,u'いっ':-2055,u'いる':672,u'うし':-4817,u'うん':665,u'から':3472,u'がら':600,u'こう':-790,u'こと':2083,u'こん':-1262,u'さら':-4143,u'さん':4573,u'した':2641,u'して':1104,u'すで':-3399,u'そこ':1977,u'それ':-871,u'たち':1122,u'ため':601,u'った':3463,u'つい':-802,u'てい':805,u'てき':1249,u'でき':1127,u'です':3445,u'では':844,u'とい':-4915,u'とみ':1922,u'どこ':3887,u'ない':5713,u'なっ':3015,u'など':7379,u'なん':-1113,u'にし':2468,u'には':1498,u'にも':16 [...]
+ BW2__ = {u'..':-11822,u'11':-669,u'――':-5730,u'−−':-13175,u'いう':-1609,u'うか':2490,u'かし':-1350,u'かも':-602,u'から':-7194,u'かれ':4612,u'がい':853,u'がら':-3198,u'きた':1941,u'くな':-1597,u'こと':-8392,u'この':-4193,u'させ':4533,u'され':13168,u'さん':-3977,u'しい':-1819,u'しか':-545,u'した':5078,u'して':972,u'しな':939,u'その':-3744,u'たい':-1253,u'たた':-662,u'ただ':-3857,u'たち':-786,u'たと':1224,u'たは':-939,u'った':4589,u'って':1647,u'っと':-2094,u'てい':6144,u'てき':3640,u'てく':2551,u'ては':-3110,u'ても':-3065,u'でい':2666,u'でき':-1528,u'でし':-38 [...]
+ BW3__ = {u'あた':-2194,u'あり':719,u'ある':3846,u'い.':-1185,u'い。':-1185,u'いい':5308,u'いえ':2079,u'いく':3029,u'いた':2056,u'いっ':1883,u'いる':5600,u'いわ':1527,u'うち':1117,u'うと':4798,u'えと':1454,u'か.':2857,u'か。':2857,u'かけ':-743,u'かっ':-4098,u'かに':-669,u'から':6520,u'かり':-2670,u'が,':1816,u'が、':1816,u'がき':-4855,u'がけ':-1127,u'がっ':-913,u'がら':-4977,u'がり':-2064,u'きた':1645,u'けど':1374,u'こと':7397,u'この':1542,u'ころ':-2757,u'さい':-714,u'さを':976,u'し,':1557,u'し、':1557,u'しい':-3714,u'した':3562,u'して':1449,u'しな':2608,u'しま':12 [...]
+ TC1__ = {u'AAA':1093,u'HHH':1029,u'HHM':580,u'HII':998,u'HOH':-390,u'HOM':-331,u'IHI':1169,u'IOH':-142,u'IOI':-1015,u'IOM':467,u'MMH':187,u'OOI':-1832}
+ TC2__ = {u'HHO':2088,u'HII':-1023,u'HMM':-1154,u'IHI':-1965,u'KKH':703,u'OII':-2649}
+ TC3__ = {u'AAA':-294,u'HHH':346,u'HHI':-341,u'HII':-1088,u'HIK':731,u'HOH':-1486,u'IHH':128,u'IHI':-3041,u'IHO':-1935,u'IIH':-825,u'IIM':-1035,u'IOI':-542,u'KHH':-1216,u'KKA':491,u'KKH':-1217,u'KOK':-1009,u'MHH':-2694,u'MHM':-457,u'MHO':123,u'MMH':-471,u'NNH':-1689,u'NNO':662,u'OHO':-3393}
+ TC4__ = {u'HHH':-203,u'HHI':1344,u'HHK':365,u'HHM':-122,u'HHN':182,u'HHO':669,u'HIH':804,u'HII':679,u'HOH':446,u'IHH':695,u'IHO':-2324,u'IIH':321,u'III':1497,u'IIO':656,u'IOO':54,u'KAK':4845,u'KKA':3386,u'KKK':3065,u'MHH':-405,u'MHI':201,u'MMH':-241,u'MMM':661,u'MOM':841}
+ TQ1__ = {u'BHHH':-227,u'BHHI':316,u'BHIH':-132,u'BIHH':60,u'BIII':1595,u'BNHH':-744,u'BOHH':225,u'BOOO':-908,u'OAKK':482,u'OHHH':281,u'OHIH':249,u'OIHI':200,u'OIIH':-68}
+ TQ2__ = {u'BIHH':-1401,u'BIII':-1033,u'BKAK':-543,u'BOOO':-5591}
+ TQ3__ = {u'BHHH':478,u'BHHM':-1073,u'BHIH':222,u'BHII':-504,u'BIIH':-116,u'BIII':-105,u'BMHI':-863,u'BMHM':-464,u'BOMH':620,u'OHHH':346,u'OHHI':1729,u'OHII':997,u'OHMH':481,u'OIHH':623,u'OIIH':1344,u'OKAK':2792,u'OKHH':587,u'OKKA':679,u'OOHH':110,u'OOII':-685}
+ TQ4__ = {u'BHHH':-721,u'BHHM':-3604,u'BHII':-966,u'BIIH':-607,u'BIII':-2181,u'OAAA':-2763,u'OAKK':180,u'OHHH':-294,u'OHHI':2446,u'OHHO':480,u'OHIH':-1573,u'OIHH':1935,u'OIHI':-493,u'OIIH':626,u'OIII':-4007,u'OKAK':-8156}
+ TW1__ = {u'につい':-4681,u'東京都':2026}
+ TW2__ = {u'ある程':-2049,u'いった':-1256,u'ころが':-2434,u'しょう':3873,u'その後':-4430,u'だって':-1049,u'ていた':1833,u'として':-4657,u'ともに':-4517,u'もので':1882,u'一気に':-792,u'初めて':-1512,u'同時に':-8097,u'大きな':-1255,u'対して':-2721,u'社会党':-3216}
+ TW3__ = {u'いただ':-1734,u'してい':1314,u'として':-4314,u'につい':-5483,u'にとっ':-5989,u'に当た':-6247,u'ので,':-727,u'ので、':-727,u'のもの':-600,u'れから':-3752,u'十二月':-2287}
+ TW4__ = {u'いう.':8576,u'いう。':8576,u'からな':-2348,u'してい':2958,u'たが,':1516,u'たが、':1516,u'ている':1538,u'という':1349,u'ました':5543,u'ません':1097,u'ようと':-4258,u'よると':5865}
+ UC1__ = {u'A':484,u'K':93,u'M':645,u'O':-505}
+ UC2__ = {u'A':819,u'H':1059,u'I':409,u'M':3987,u'N':5775,u'O':646}
+ UC3__ = {u'A':-1370,u'I':2311}
+ UC4__ = {u'A':-2643,u'H':1809,u'I':-1032,u'K':-3450,u'M':3565,u'N':3876,u'O':6646}
+ UC5__ = {u'H':313,u'I':-1238,u'K':-799,u'M':539,u'O':-831}
+ UC6__ = {u'H':-506,u'I':-253,u'K':87,u'M':247,u'O':-387}
+ UP1__ = {u'O':-214}
+ UP2__ = {u'B':69,u'O':935}
+ UP3__ = {u'B':189}
+ UQ1__ = {u'BH':21,u'BI':-12,u'BK':-99,u'BN':142,u'BO':-56,u'OH':-95,u'OI':477,u'OK':410,u'OO':-2422}
+ UQ2__ = {u'BH':216,u'BI':113,u'OK':1759}
+ UQ3__ = {u'BA':-479,u'BH':42,u'BI':1913,u'BK':-7198,u'BM':3160,u'BN':6427,u'BO':14761,u'OI':-827,u'ON':-3212}
+ UW1__ = {u',':156,u'、':156,u'「':-463,u'あ':-941,u'う':-127,u'が':-553,u'き':121,u'こ':505,u'で':-201,u'と':-547,u'ど':-123,u'に':-789,u'の':-185,u'は':-847,u'も':-466,u'や':-470,u'よ':182,u'ら':-292,u'り':208,u'れ':169,u'を':-446,u'ん':-137,u'・':-135,u'主':-402,u'京':-268,u'区':-912,u'午':871,u'国':-460,u'大':561,u'委':729,u'市':-411,u'日':-141,u'理':361,u'生':-408,u'県':-386,u'都':-718,u'「':-463,u'・':-135}
+ UW2__ = {u',':-829,u'、':-829,u'〇':892,u'「':-645,u'」':3145,u'あ':-538,u'い':505,u'う':134,u'お':-502,u'か':1454,u'が':-856,u'く':-412,u'こ':1141,u'さ':878,u'ざ':540,u'し':1529,u'す':-675,u'せ':300,u'そ':-1011,u'た':188,u'だ':1837,u'つ':-949,u'て':-291,u'で':-268,u'と':-981,u'ど':1273,u'な':1063,u'に':-1764,u'の':130,u'は':-409,u'ひ':-1273,u'べ':1261,u'ま':600,u'も':-1263,u'や':-402,u'よ':1639,u'り':-579,u'る':-694,u'れ':571,u'を':-2516,u'ん':2095,u'ア':-587,u'カ':306,u'キ':568,u'ッ':831,u'三':-758,u'不':-2150,u'世':-302,u'中':- [...]
+ UW3__ = {u',':4889,u'1':-800,u'−':-1723,u'、':4889,u'々':-2311,u'〇':5827,u'」':2670,u'〓':-3573,u'あ':-2696,u'い':1006,u'う':2342,u'え':1983,u'お':-4864,u'か':-1163,u'が':3271,u'く':1004,u'け':388,u'げ':401,u'こ':-3552,u'ご':-3116,u'さ':-1058,u'し':-395,u'す':584,u'せ':3685,u'そ':-5228,u'た':842,u'ち':-521,u'っ':-1444,u'つ':-1081,u'て':6167,u'で':2318,u'と':1691,u'ど':-899,u'な':-2788,u'に':2745,u'の':4056,u'は':4555,u'ひ':-2171,u'ふ':-1798,u'へ':1199,u'ほ':-5516,u'ま':-4384,u'み':-120,u'め':1205,u'も':2323,u'や':-788,u'よ':- [...]
+ UW4__ = {u',':3930,u'.':3508,u'―':-4841,u'、':3930,u'。':3508,u'〇':4999,u'「':1895,u'」':3798,u'〓':-5156,u'あ':4752,u'い':-3435,u'う':-640,u'え':-2514,u'お':2405,u'か':530,u'が':6006,u'き':-4482,u'ぎ':-3821,u'く':-3788,u'け':-4376,u'げ':-4734,u'こ':2255,u'ご':1979,u'さ':2864,u'し':-843,u'じ':-2506,u'す':-731,u'ず':1251,u'せ':181,u'そ':4091,u'た':5034,u'だ':5408,u'ち':-3654,u'っ':-5882,u'つ':-1659,u'て':3994,u'で':7410,u'と':4547,u'な':5433,u'に':6499,u'ぬ':1853,u'ね':1413,u'の':7396,u'は':8578,u'ば':1940,u'ひ':4249,u'び':-41 [...]
+ UW5__ = {u',':465,u'.':-299,u'1':-514,u'E2':-32768,u']':-2762,u'、':465,u'。':-299,u'「':363,u'あ':1655,u'い':331,u'う':-503,u'え':1199,u'お':527,u'か':647,u'が':-421,u'き':1624,u'ぎ':1971,u'く':312,u'げ':-983,u'さ':-1537,u'し':-1371,u'す':-852,u'だ':-1186,u'ち':1093,u'っ':52,u'つ':921,u'て':-18,u'で':-850,u'と':-127,u'ど':1682,u'な':-787,u'に':-1224,u'の':-635,u'は':-578,u'べ':1001,u'み':502,u'め':865,u'ゃ':3350,u'ょ':854,u'り':-208,u'る':429,u'れ':504,u'わ':419,u'を':-1264,u'ん':327,u'イ':241,u'ル':451,u'ン':-343,u'中':-871, [...]
+ UW6__ = {u',':227,u'.':808,u'1':-270,u'E1':306,u'、':227,u'。':808,u'あ':-307,u'う':189,u'か':241,u'が':-73,u'く':-121,u'こ':-200,u'じ':1782,u'す':383,u'た':-428,u'っ':573,u'て':-1014,u'で':101,u'と':-105,u'な':-253,u'に':-149,u'の':-417,u'は':-236,u'も':-206,u'り':187,u'る':-135,u'を':195,u'ル':-673,u'ン':-496,u'一':-277,u'中':201,u'件':-800,u'会':624,u'前':302,u'区':1792,u'員':-1212,u'委':798,u'学':-960,u'市':887,u'広':-695,u'後':535,u'業':-697,u'相':753,u'社':-507,u'福':974,u'空':-822,u'者':1811,u'連':463,u'郎':1082,u'1':-27 [...]
+
+ # ctype_
+ def ctype_(self, char):
+ for pattern, value in self.patterns_.iteritems():
+ if pattern.match(char):
+ return value
+ return u'O'
+ # ts_
+ def ts_(self, dict, key):
+ if key in dict:
+ return dict[key]
+ return 0
+
+ # segment
+ def split(self, input):
+ if not input:
+ return []
+
+ result = []
+ seg = [u'B3',u'B2',u'B1']
+ ctype = [u'O',u'O',u'O']
+ for t in input:
+ seg.append(t)
+ ctype.append(self.ctype_(t))
+ seg.append(u'E1')
+ seg.append(u'E2')
+ seg.append(u'E3')
+ ctype.append(u'O')
+ ctype.append(u'O')
+ ctype.append(u'O')
+ word = seg[3]
+ p1 = u'U'
+ p2 = u'U'
+ p3 = u'U'
+
+ for i in range(4, len(seg) - 3):
+ score = self.BIAS__
+ w1 = seg[i-3]
+ w2 = seg[i-2]
+ w3 = seg[i-1]
+ w4 = seg[i]
+ w5 = seg[i+1]
+ w6 = seg[i+2]
+ c1 = ctype[i-3]
+ c2 = ctype[i-2]
+ c3 = ctype[i-1]
+ c4 = ctype[i]
+ c5 = ctype[i+1]
+ c6 = ctype[i+2]
+ score += self.ts_(self.UP1__, p1)
+ score += self.ts_(self.UP2__, p2)
+ score += self.ts_(self.UP3__, p3)
+ score += self.ts_(self.BP1__, p1 + p2)
+ score += self.ts_(self.BP2__, p2 + p3)
+ score += self.ts_(self.UW1__, w1)
+ score += self.ts_(self.UW2__, w2)
+ score += self.ts_(self.UW3__, w3)
+ score += self.ts_(self.UW4__, w4)
+ score += self.ts_(self.UW5__, w5)
+ score += self.ts_(self.UW6__, w6)
+ score += self.ts_(self.BW1__, w2 + w3)
+ score += self.ts_(self.BW2__, w3 + w4)
+ score += self.ts_(self.BW3__, w4 + w5)
+ score += self.ts_(self.TW1__, w1 + w2 + w3)
+ score += self.ts_(self.TW2__, w2 + w3 + w4)
+ score += self.ts_(self.TW3__, w3 + w4 + w5)
+ score += self.ts_(self.TW4__, w4 + w5 + w6)
+ score += self.ts_(self.UC1__, c1)
+ score += self.ts_(self.UC2__, c2)
+ score += self.ts_(self.UC3__, c3)
+ score += self.ts_(self.UC4__, c4)
+ score += self.ts_(self.UC5__, c5)
+ score += self.ts_(self.UC6__, c6)
+ score += self.ts_(self.BC1__, c2 + c3)
+ score += self.ts_(self.BC2__, c3 + c4)
+ score += self.ts_(self.BC3__, c4 + c5)
+ score += self.ts_(self.TC1__, c1 + c2 + c3)
+ score += self.ts_(self.TC2__, c2 + c3 + c4)
+ score += self.ts_(self.TC3__, c3 + c4 + c5)
+ score += self.ts_(self.TC4__, c4 + c5 + c6)
+# score += self.ts_(self.TC5__, c4 + c5 + c6)
+ score += self.ts_(self.UQ1__, p1 + c1)
+ score += self.ts_(self.UQ2__, p2 + c2)
+ score += self.ts_(self.UQ1__, p3 + c3)
+ score += self.ts_(self.BQ1__, p2 + c2 + c3)
+ score += self.ts_(self.BQ2__, p2 + c3 + c4)
+ score += self.ts_(self.BQ3__, p3 + c2 + c3)
+ score += self.ts_(self.BQ4__, p3 + c3 + c4)
+ score += self.ts_(self.TQ1__, p2 + c1 + c2 + c3)
+ score += self.ts_(self.TQ2__, p2 + c2 + c3 + c4)
+ score += self.ts_(self.TQ3__, p3 + c1 + c2 + c3)
+ score += self.ts_(self.TQ4__, p3 + c2 + c3 + c4)
+ p = u'O'
+ if score > 0:
+ result.append(word.strip())
+ word = u''
+ p = u'B'
+ p1 = p2
+ p2 = p3
+ p3 = p
+ word += seg[i]
+
+ result.append(word.strip())
+ return result
+
+
+class SearchJapanese(SearchLanguage):
+ """
+ Japanese search implementation: uses no stemmer, but word splitting is quite
+ complicated.
+ """
+ lang = 'ja'
+
+ def init(self, options):
+ type = options.get('type', 'default')
+ if type not in ('mecab', 'default'):
+ raise ValueError(("Japanese tokenizer's type should be 'mecab'"
+ " or 'default'"))
+ self.libmecab = None
+ if type == 'mecab':
+ self.splitter = MecabBinder(options)
+ else:
+ self.splitter = TinySegmenter()
+
+ def split(self, input):
+ return self.splitter.split(input)
+
+ def word_filter(self, stemmed_word):
+ return len(stemmed_word) > 1
+
+ def stem(self, word):
+ return word.lower()
diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py
new file mode 100644
index 0000000..a487b2a
--- /dev/null
+++ b/sphinx/setup_command.py
@@ -0,0 +1,177 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.setup_command
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Setuptools/distutils commands to assist the building of sphinx
+ documentation.
+
+ :author: Sebastian Wiesner
+ :contact: basti.wiesner at gmx.net
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import os
+import types
+from StringIO import StringIO
+from distutils.cmd import Command
+from distutils.errors import DistutilsOptionError, DistutilsExecError
+
+from sphinx.application import Sphinx
+from sphinx.util.console import darkred, nocolor, color_terminal
+from sphinx.util.osutil import abspath
+
+
+class BuildDoc(Command):
+ """
+ Distutils command to build Sphinx documentation.
+
+ The Sphinx build can then be triggered from distutils, and some Sphinx
+ options can be set in ``setup.py`` or ``setup.cfg`` instead of Sphinx own
+ configuration file.
+
+ For instance, from `setup.py`::
+
+ # this is only necessary when not using setuptools/distribute
+ from sphinx.setup_command import BuildDoc
+ cmdclass = {'build_sphinx': BuildDoc}
+
+ name = 'My project'
+ version = '1.2'
+ release = '1.2.0'
+ setup(
+ name=name,
+ author='Bernard Montgomery',
+ version=release,
+ cmdclass=cmdclass,
+ # these are optional and override conf.py settings
+ command_options={
+ 'build_sphinx': {
+ 'project': ('setup.py', name),
+ 'version': ('setup.py', version),
+ 'release': ('setup.py', release)}},
+ )
+
+ Or add this section in ``setup.cfg``::
+
+ [build_sphinx]
+ project = 'My project'
+ version = 1.2
+ release = 1.2.0
+ """
+
+ description = 'Build Sphinx documentation'
+ user_options = [
+ ('fresh-env', 'E', 'discard saved environment'),
+ ('all-files', 'a', 'build all files'),
+ ('source-dir=', 's', 'Source directory'),
+ ('build-dir=', None, 'Build directory'),
+ ('config-dir=', 'c', 'Location of the configuration directory'),
+ ('builder=', 'b', 'The builder to use. Defaults to "html"'),
+ ('project=', None, 'The documented project\'s name'),
+ ('version=', None, 'The short X.Y version'),
+ ('release=', None, 'The full version, including alpha/beta/rc tags'),
+ ('today=', None, 'How to format the current date, used as the '
+ 'replacement for |today|'),
+ ('link-index', 'i', 'Link index.html to the master doc'),
+ ]
+ boolean_options = ['fresh-env', 'all-files', 'link-index']
+
+
+ def initialize_options(self):
+ self.fresh_env = self.all_files = False
+ self.source_dir = self.build_dir = None
+ self.builder = 'html'
+ self.project = ''
+ self.version = ''
+ self.release = ''
+ self.today = ''
+ self.config_dir = None
+ self.link_index = False
+
+ def _guess_source_dir(self):
+ for guess in ('doc', 'docs'):
+ if not os.path.isdir(guess):
+ continue
+ for root, dirnames, filenames in os.walk(guess):
+ if 'conf.py' in filenames:
+ return root
+ return None
+
+ # Overriding distutils' Command._ensure_stringlike which doesn't support
+ # unicode, causing finalize_options to fail if invoked again. Workaround
+ # for http://bugs.python.org/issue19570
+ def _ensure_stringlike(self, option, what, default=None):
+ val = getattr(self, option)
+ if val is None:
+ setattr(self, option, default)
+ return default
+ elif not isinstance(val, types.StringTypes):
+ raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
+ % (option, what, val))
+ return val
+
+ def finalize_options(self):
+ if self.source_dir is None:
+ self.source_dir = self._guess_source_dir()
+ self.announce('Using source directory %s' % self.source_dir)
+ self.ensure_dirname('source_dir')
+ if self.source_dir is None:
+ self.source_dir = os.curdir
+ self.source_dir = abspath(self.source_dir)
+ if self.config_dir is None:
+ self.config_dir = self.source_dir
+ self.config_dir = abspath(self.config_dir)
+
+ if self.build_dir is None:
+ build = self.get_finalized_command('build')
+ self.build_dir = os.path.join(abspath(build.build_base), 'sphinx')
+ self.mkpath(self.build_dir)
+ self.build_dir = abspath(self.build_dir)
+ self.doctree_dir = os.path.join(self.build_dir, 'doctrees')
+ self.mkpath(self.doctree_dir)
+ self.builder_target_dir = os.path.join(self.build_dir, self.builder)
+ self.mkpath(self.builder_target_dir)
+
+ def run(self):
+ if not color_terminal():
+ # Windows' poor cmd box doesn't understand ANSI sequences
+ nocolor()
+ if not self.verbose:
+ status_stream = StringIO()
+ else:
+ status_stream = sys.stdout
+ confoverrides = {}
+ if self.project:
+ confoverrides['project'] = self.project
+ if self.version:
+ confoverrides['version'] = self.version
+ if self.release:
+ confoverrides['release'] = self.release
+ if self.today:
+ confoverrides['today'] = self.today
+ app = Sphinx(self.source_dir, self.config_dir,
+ self.builder_target_dir, self.doctree_dir,
+ self.builder, confoverrides, status_stream,
+ freshenv=self.fresh_env)
+
+ try:
+ app.build(force_all=self.all_files)
+ if app.statuscode:
+ raise DistutilsExecError(
+ 'caused by %s builder.' % app.builder.name)
+ except Exception, err:
+ from docutils.utils import SystemMessage
+ if isinstance(err, SystemMessage):
+ print >>sys.stderr, darkred('reST markup error:')
+ print >>sys.stderr, err.args[0].encode('ascii',
+ 'backslashreplace')
+ else:
+ raise
+
+ if self.link_index:
+ src = app.config.master_doc + app.builder.out_suffix
+ dst = app.builder.get_outfilename('index')
+ os.symlink(src, dst)
diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile
new file mode 100644
index 0000000..6b87ad8
--- /dev/null
+++ b/sphinx/texinputs/Makefile
@@ -0,0 +1,66 @@
+# Makefile for Sphinx LaTeX output
+
+ALLDOCS = $(basename $(wildcard *.tex))
+ALLPDF = $(addsuffix .pdf,$(ALLDOCS))
+ALLDVI = $(addsuffix .dvi,$(ALLDOCS))
+
+# Prefix for archive names
+ARCHIVEPRREFIX =
+# Additional LaTeX options
+LATEXOPTS =
+
+all: $(ALLPDF)
+all-pdf: $(ALLPDF)
+all-dvi: $(ALLDVI)
+all-ps: all-dvi
+ for f in *.dvi; do dvips $$f; done
+
+all-pdf-ja:
+ for f in *.pdf *.png *.gif *.jpg *.jpeg; do extractbb $$f; done
+ for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done
+ for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done
+ for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done
+ -for f in *.idx; do mendex -U -f -d "`basename $$f .idx`.dic" -s python.ist $$f; done
+ for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done
+ for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done
+ for f in *.dvi; do dvipdfmx $$f; done
+
+zip: all-$(FMT)
+ mkdir $(ARCHIVEPREFIX)docs-$(FMT)
+ cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT)
+ zip -q -r -9 $(ARCHIVEPREFIX)docs-$(FMT).zip $(ARCHIVEPREFIX)docs-$(FMT)
+ rm -r $(ARCHIVEPREFIX)docs-$(FMT)
+
+tar: all-$(FMT)
+ mkdir $(ARCHIVEPREFIX)docs-$(FMT)
+ cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT)
+ tar cf $(ARCHIVEPREFIX)docs-$(FMT).tar $(ARCHIVEPREFIX)docs-$(FMT)
+ rm -r $(ARCHIVEPREFIX)docs-$(FMT)
+
+bz2: tar
+ bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar
+
+# The number of LaTeX runs is quite conservative, but I don't expect it
+# to get run often, so the little extra time won't hurt.
+%.dvi: %.tex
+ latex $(LATEXOPTS) '$<'
+ latex $(LATEXOPTS) '$<'
+ latex $(LATEXOPTS) '$<'
+ -makeindex -s python.ist '$(basename $<).idx'
+ latex $(LATEXOPTS) '$<'
+ latex $(LATEXOPTS) '$<'
+
+%.pdf: %.tex
+ pdflatex $(LATEXOPTS) '$<'
+ pdflatex $(LATEXOPTS) '$<'
+ pdflatex $(LATEXOPTS) '$<'
+ -makeindex -s python.ist '$(basename $<).idx'
+ pdflatex $(LATEXOPTS) '$<'
+ pdflatex $(LATEXOPTS) '$<'
+
+clean:
+ rm -f *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla
+
+.PHONY: all all-pdf all-dvi all-ps clean
+.PHONY: all-pdf-ja
+
diff --git a/sphinx/texinputs/fncychap.sty b/sphinx/texinputs/fncychap.sty
new file mode 100644
index 0000000..9a56c04
--- /dev/null
+++ b/sphinx/texinputs/fncychap.sty
@@ -0,0 +1,683 @@
+%%% Copyright Ulf A. Lindgren
+%%%
+%%% Note Premission is granted to modify this file under
+%%% the condition that it is saved using another
+%%% file and package name.
+%%%
+%%% Revision 1.1 (1997)
+%%%
+%%% Jan. 8th Modified package name base date option
+%%% Jan. 22th Modified FmN and FmTi for error in book.cls
+%%% \MakeUppercase{#}->{\MakeUppercase#}
+%%% Apr. 6th Modified Lenny option to prevent undesired
+%%% skip of line.
+%%% Nov. 8th Fixed \@chapapp for AMS
+%%%
+%%% Revision 1.2 (1998)
+%%%
+%%% Feb. 11th Fixed appendix problem related to Bjarne
+%%% Aug. 11th Fixed problem related to 11pt and 12pt
+%%% suggested by Tomas Lundberg. THANKS!
+%%%
+%%% Revision 1.3 (2004)
+%%% Sep. 20th problem with frontmatter, mainmatter and
+%%% backmatter, pointed out by Lapo Mori
+%%%
+%%% Revision 1.31 (2004)
+%%% Sep. 21th problem with the Rejne definition streched text
+%%% caused ugly gaps in the vrule aligned with the title
+%%% text. Kindly pointed out to me by Hendri Adriaens
+%%%
+%%% Revision 1.32 (2005)
+%%% Jun. 23th compatibility problem with the KOMA class 'scrbook.cls'
+%%% a remedy is a redefinition of '\@schapter' in
+%%% line with that used in KOMA. The problem was pointed
+%%% out to me by Mikkel Holm Olsen
+%%%
+%%% Revision 1.33 (2005)
+%%% Aug. 9th misspelled ``TWELV'' corrected, the error was pointed
+%%% out to me by George Pearson
+%%%
+%%% Revision 1.34 (2007)
+%%% Added an alternative to Lenny provided by Peter
+%%% Osborne (2005-11-28)
+%%% Corrected front, main and back matter, based on input
+%%% from Bas van Gils (2006-04-24)
+%%% Jul. 30th Added Bjornstrup option provided by Jean-Marc
+%%% Francois (2007-01-05).
+%%% Reverted to \MakeUppercase{#} see rev 1.1, solved
+%%% problem with MakeUppercase and MakeLowercase pointed
+%%% out by Marco Feuerstein (2007-06-06)
+
+
+%%% Last modified Jul. 2007
+
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesPackage{fncychap}
+ [2007/07/30 v1.34
+ LaTeX package (Revised chapters)]
+
+%%%% For conditional inclusion of color
+\newif\ifusecolor
+\usecolorfalse
+
+
+
+%%%% DEFINITION OF Chapapp variables
+\newcommand{\CNV}{\huge\bfseries}
+\newcommand{\ChNameVar}[1]{\renewcommand{\CNV}{#1}}
+
+
+%%%% DEFINITION OF TheChapter variables
+\newcommand{\CNoV}{\huge\bfseries}
+\newcommand{\ChNumVar}[1]{\renewcommand{\CNoV}{#1}}
+
+\newif\ifUCN
+\UCNfalse
+\newif\ifLCN
+\LCNfalse
+\def\ChNameLowerCase{\LCNtrue\UCNfalse}
+\def\ChNameUpperCase{\UCNtrue\LCNfalse}
+\def\ChNameAsIs{\UCNfalse\LCNfalse}
+
+%%%%% Fix for AMSBook 971008
+
+\@ifundefined{@chapapp}{\let\@chapapp\chaptername}{}
+
+
+%%%%% Fix for Bjarne and appendix 980211
+
+\newif\ifinapp
+\inappfalse
+\renewcommand\appendix{\par
+ \setcounter{chapter}{0}%
+ \setcounter{section}{0}%
+ \inapptrue%
+ \renewcommand\@chapapp{\appendixname}%
+ \renewcommand\thechapter{\@Alph\c at chapter}}
+
+%%%%% Fix for frontmatter, mainmatter, and backmatter 040920
+
+\@ifundefined{@mainmatter}{\newif\if at mainmatter \@mainmattertrue}{}
+
+%%%%%
+
+
+
+\newcommand{\FmN}[1]{%
+\ifUCN
+ {\MakeUppercase{#1}}\LCNfalse
+\else
+ \ifLCN
+ {\MakeLowercase{#1}}\UCNfalse
+ \else #1
+ \fi
+\fi}
+
+
+%%%% DEFINITION OF Title variables
+\newcommand{\CTV}{\Huge\bfseries}
+\newcommand{\ChTitleVar}[1]{\renewcommand{\CTV}{#1}}
+
+%%%% DEFINITION OF the basic rule width
+\newlength{\RW}
+\setlength{\RW}{1pt}
+\newcommand{\ChRuleWidth}[1]{\setlength{\RW}{#1}}
+
+\newif\ifUCT
+\UCTfalse
+\newif\ifLCT
+\LCTfalse
+\def\ChTitleLowerCase{\LCTtrue\UCTfalse}
+\def\ChTitleUpperCase{\UCTtrue\LCTfalse}
+\def\ChTitleAsIs{\UCTfalse\LCTfalse}
+\newcommand{\FmTi}[1]{%
+\ifUCT
+ {\MakeUppercase{#1}}\LCTfalse
+\else
+ \ifLCT
+ {\MakeLowercase{#1}}\UCTfalse
+ \else {#1}
+ \fi
+\fi}
+
+
+
+\newlength{\mylen}
+\newlength{\myhi}
+\newlength{\px}
+\newlength{\py}
+\newlength{\pyy}
+\newlength{\pxx}
+
+
+\def\mghrulefill#1{\leavevmode\leaders\hrule\@height #1\hfill\kern\z@}
+
+\newcommand{\DOCH}{%
+ \CNV\FmN{\@chapapp}\space \CNoV\thechapter
+ \par\nobreak
+ \vskip 20\p@
+ }
+\newcommand{\DOTI}[1]{%
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 40\p@
+ }
+\newcommand{\DOTIS}[1]{%
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 40\p@
+ }
+
+%%%%%% SONNY DEF
+
+\DeclareOption{Sonny}{%
+ \ChNameVar{\Large\sf}
+ \ChNumVar{\Huge}
+ \ChTitleVar{\Large\sf}
+ \ChRuleWidth{0.5pt}
+ \ChNameUpperCase
+ \renewcommand{\DOCH}{%
+ \raggedleft
+ \CNV\FmN{\@chapapp}\space \CNoV\thechapter
+ \par\nobreak
+ \vskip 40\p@}
+ \renewcommand{\DOTI}[1]{%
+ \CTV\raggedleft\mghrulefill{\RW}\par\nobreak
+ \vskip 5\p@
+ \CTV\FmTi{#1}\par\nobreak
+ \mghrulefill{\RW}\par\nobreak
+ \vskip 40\p@}
+ \renewcommand{\DOTIS}[1]{%
+ \CTV\raggedleft\mghrulefill{\RW}\par\nobreak
+ \vskip 5\p@
+ \CTV\FmTi{#1}\par\nobreak
+ \mghrulefill{\RW}\par\nobreak
+ \vskip 40\p@}
+}
+
+%%%%%% LENNY DEF
+
+\DeclareOption{Lenny}{%
+
+ \ChNameVar{\fontsize{14}{16}\usefont{OT1}{phv}{m}{n}\selectfont}
+ \ChNumVar{\fontsize{60}{62}\usefont{OT1}{ptm}{m}{n}\selectfont}
+ \ChTitleVar{\Huge\bfseries\rm}
+ \ChRuleWidth{1pt}
+ \renewcommand{\DOCH}{%
+ \settowidth{\px}{\CNV\FmN{\@chapapp}}
+ \addtolength{\px}{2pt}
+ \settoheight{\py}{\CNV\FmN{\@chapapp}}
+ \addtolength{\py}{1pt}
+
+ \settowidth{\mylen}{\CNV\FmN{\@chapapp}\space\CNoV\thechapter}
+ \addtolength{\mylen}{1pt}
+ \settowidth{\pxx}{\CNoV\thechapter}
+ \addtolength{\pxx}{-1pt}
+
+ \settoheight{\pyy}{\CNoV\thechapter}
+ \addtolength{\pyy}{-2pt}
+ \setlength{\myhi}{\pyy}
+ \addtolength{\myhi}{-1\py}
+ \par
+ \parbox[b]{\textwidth}{%
+ \rule[\py]{\RW}{\myhi}%
+ \hskip -\RW%
+ \rule[\pyy]{\px}{\RW}%
+ \hskip -\px%
+ \raggedright%
+ \CNV\FmN{\@chapapp}\space\CNoV\thechapter%
+ \hskip1pt%
+ \mghrulefill{\RW}%
+ \rule{\RW}{\pyy}\par\nobreak%
+ \vskip -\baselineskip%
+ \vskip -\pyy%
+ \hskip \mylen%
+ \mghrulefill{\RW}\par\nobreak%
+ \vskip \pyy}%
+ \vskip 20\p@}
+
+
+ \renewcommand{\DOTI}[1]{%
+ \raggedright
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 40\p@}
+
+ \renewcommand{\DOTIS}[1]{%
+ \raggedright
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 40\p@}
+ }
+
+%%%%%% Peter Osbornes' version of LENNY DEF
+
+\DeclareOption{PetersLenny}{%
+
+% five new lengths
+\newlength{\bl} % bottom left : orig \space
+\setlength{\bl}{6pt}
+\newcommand{\BL}[1]{\setlength{\bl}{#1}}
+\newlength{\br} % bottom right : orig 1pt
+\setlength{\br}{1pt}
+\newcommand{\BR}[1]{\setlength{\br}{#1}}
+\newlength{\tl} % top left : orig 2pt
+\setlength{\tl}{2pt}
+\newcommand{\TL}[1]{\setlength{\tl}{#1}}
+\newlength{\trr} % top right :orig 1pt
+\setlength{\trr}{1pt}
+\newcommand{\TR}[1]{\setlength{\trr}{#1}}
+\newlength{\blrule} % top right :orig 1pt
+\setlength{\trr}{0pt}
+\newcommand{\BLrule}[1]{\setlength{\blrule}{#1}}
+
+
+ \ChNameVar{\fontsize{14}{16}\usefont{OT1}{phv}{m}{n}\selectfont}
+ \ChNumVar{\fontsize{60}{62}\usefont{OT1}{ptm}{m}{n}\selectfont}
+ \ChTitleVar{\Huge\bfseries\rm}
+ \ChRuleWidth{1pt}
+\renewcommand{\DOCH}{%
+
+
+%%%%%%% tweaks for 1--9 and A--Z
+\ifcase\c at chapter\relax%
+\or\BL{-3pt}\TL{-4pt}\BR{0pt}\TR{-6pt}%1
+\or\BL{0pt}\TL{-4pt}\BR{2pt}\TR{-4pt}%2
+\or\BL{0pt}\TL{-4pt}\BR{2pt}\TR{-4pt}%3
+\or\BL{0pt}\TL{5pt}\BR{2pt}\TR{-4pt}%4
+\or\BL{0pt}\TL{3pt}\BR{2pt}\TR{-4pt}%5
+\or\BL{-1pt}\TL{0pt}\BR{2pt}\TR{-2pt}%6
+\or\BL{0pt}\TL{-3pt}\BR{2pt}\TR{-2pt}%7
+\or\BL{0pt}\TL{-3pt}\BR{2pt}\TR{-2pt}%8
+\or\BL{0pt}\TL{-3pt}\BR{-4pt}\TR{-2pt}%9
+\or\BL{-3pt}\TL{-3pt}\BR{2pt}\TR{-7pt}%10
+\or\BL{-6pt}\TL{-6pt}\BR{0pt}\TR{-9pt}%11
+\or\BL{-6pt}\TL{-6pt}\BR{2pt}\TR{-7pt}%12
+\or\BL{-5pt}\TL{-5pt}\BR{0pt}\TR{-9pt}%13
+\or\BL{-6pt}\TL{-6pt}\BR{0pt}\TR{-9pt}%14
+\or\BL{-3pt}\TL{-3pt}\BR{3pt}\TR{-6pt}%15
+\or\BL{-3pt}\TL{-3pt}\BR{3pt}\TR{-6pt}%16
+\or\BL{-5pt}\TL{-3pt}\BR{-8pt}\TR{-6pt}%17
+\or\BL{-5pt}\TL{-5pt}\BR{0pt}\TR{-9pt}%18
+\or\BL{-3pt}\TL{-3pt}\BR{-6pt}\TR{-9pt}%19
+\or\BL{0pt}\TL{0pt}\BR{0pt}\TR{-5pt}%20
+\fi
+
+\ifinapp\ifcase\c at chapter\relax%
+\or\BL{0pt}\TL{14pt}\BR{5pt}\TR{-19pt}%A
+\or\BL{0pt}\TL{-5pt}\BR{-3pt}\TR{-8pt}%B
+\or\BL{-3pt}\TL{-2pt}\BR{1pt}\TR{-6pt}\BLrule{0pt}%C
+\or\BL{0pt}\TL{-5pt}\BR{-3pt}\TR{-8pt}\BLrule{0pt}%D
+\or\BL{0pt}\TL{-5pt}\BR{2pt}\TR{-3pt}%E
+\or\BL{0pt}\TL{-5pt}\BR{-10pt}\TR{-1pt}%F
+\or\BL{-3pt}\TL{0pt}\BR{0pt}\TR{-7pt}%G
+\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}%H
+\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}%I
+\or\BL{2pt}\TL{0pt}\BR{-3pt}\TR{1pt}%J
+\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}%K
+\or\BL{0pt}\TL{-5pt}\BR{2pt}\TR{-19pt}%L
+\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}%M
+\or\BL{0pt}\TL{-5pt}\BR{-2pt}\TR{-1pt}%N
+\or\BL{-3pt}\TL{-2pt}\BR{-3pt}\TR{-11pt}%O
+\or\BL{0pt}\TL{-5pt}\BR{-9pt}\TR{-3pt}%P
+\or\BL{-3pt}\TL{-2pt}\BR{-3pt}\TR{-11pt}%Q
+\or\BL{0pt}\TL{-5pt}\BR{4pt}\TR{-8pt}%R
+\or\BL{-2pt}\TL{-2pt}\BR{-2pt}\TR{-7pt}%S
+\or\BL{-3pt}\TL{0pt}\BR{-5pt}\TR{4pt}\BLrule{8pt}%T
+\or\BL{-7pt}\TL{-11pt}\BR{-5pt}\TR{-7pt}\BLrule{0pt}%U
+\or\BL{-14pt}\TL{-5pt}\BR{-14pt}\TR{-1pt}\BLrule{14pt}%V
+\or\BL{-10pt}\TL{-9pt}\BR{-13pt}\TR{-3pt}\BLrule{7pt}%W
+\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}\BLrule{0pt}%X
+\or\BL{-6pt}\TL{-4pt}\BR{-7pt}\TR{1pt}\BLrule{7pt}%Y
+\or\BL{0pt}\TL{-5pt}\BR{3pt}\TR{-1pt}\BLrule{0pt}%Z
+\fi\fi
+%%%%%%%
+ \settowidth{\px}{\CNV\FmN{\@chapapp}}
+ \addtolength{\px}{\tl} %MOD change 2pt to \tl
+ \settoheight{\py}{\CNV\FmN{\@chapapp}}
+ \addtolength{\py}{1pt}
+
+ \settowidth{\mylen}{\CNV\FmN{\@chapapp}\space\CNoV\thechapter}
+ \addtolength{\mylen}{\trr}% MOD change 1pt to \tr
+ \settowidth{\pxx}{\CNoV\thechapter}
+ \addtolength{\pxx}{-1pt}
+
+ \settoheight{\pyy}{\CNoV\thechapter}
+ \addtolength{\pyy}{-2pt}
+ \setlength{\myhi}{\pyy}
+ \addtolength{\myhi}{-1\py}
+ \par
+ \parbox[b]{\textwidth}{%
+ \rule[\py]{\RW}{\myhi}%
+ \hskip -\RW%
+ \rule[\pyy]{\px}{\RW}%
+ \hskip -\px%
+ \raggedright%
+ \CNV\FmN{\@chapapp}\rule{\blrule}{\RW}\hskip\bl\CNoV\thechapter%MOD
+% \CNV\FmN{\@chapapp}\space\CNoV\thechapter %ORIGINAL
+ \hskip\br% %MOD 1pt to \br
+ \mghrulefill{\RW}%
+ \rule{\RW}{\pyy}\par\nobreak%
+ \vskip -\baselineskip%
+ \vskip -\pyy%
+ \hskip \mylen%
+ \mghrulefill{\RW}\par\nobreak%
+ \vskip \pyy}%
+ \vskip 20\p@}
+
+
+ \renewcommand{\DOTI}[1]{%
+ \raggedright
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 40\p@}
+
+ \renewcommand{\DOTIS}[1]{%
+ \raggedright
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 40\p@}
+ }
+
+
+%
+
+
+%%%%%% BJORNSTRUP DEF
+
+\DeclareOption{Bjornstrup}{%
+ \usecolortrue
+ % pzc (Zapf Chancelery) is nice. ppl (Palatino) is cool too.
+ \ChNumVar{\fontsize{76}{80}\usefont{OT1}{pzc}{m}{n}\selectfont}
+ \ChTitleVar{\raggedleft\Large\sffamily\bfseries}
+
+ \setlength{\myhi}{10pt} % Space between grey box border and text
+ \setlength{\mylen}{\textwidth}
+ \addtolength{\mylen}{-2\myhi}
+ \renewcommand{\DOCH}{%
+ \settowidth{\py}{\CNoV\thechapter}
+ \addtolength{\py}{-10pt} % Amount of space by which the
+% % number is shifted right
+ \fboxsep=0pt%
+ \colorbox[gray]{.85}{\rule{0pt}{40pt}\parbox[b]{\textwidth}{\hfill}}%
+ \kern-\py\raise20pt%
+ \hbox{\color[gray]{.5}\CNoV\thechapter}\\%
+ }
+
+ \renewcommand{\DOTI}[1]{%
+ \nointerlineskip\raggedright%
+ \fboxsep=\myhi%
+ \vskip-1ex%
+ \colorbox[gray]{.85}{\parbox[t]{\mylen}{\CTV\FmTi{#1}}}\par\nobreak%
+ \vskip 40\p@%
+ }
+
+ \renewcommand{\DOTIS}[1]{%
+ \fboxsep=0pt
+ \colorbox[gray]{.85}{\rule{0pt}{40pt}\parbox[b]{\textwidth}{\hfill}}\\%
+ \nointerlineskip\raggedright%
+ \fboxsep=\myhi%
+ \colorbox[gray]{.85}{\parbox[t]{\mylen}{\CTV\FmTi{#1}}}\par\nobreak%
+ \vskip 40\p@%
+ }
+}
+
+
+%%%%%%% GLENN DEF
+
+
+\DeclareOption{Glenn}{%
+ \ChNameVar{\bfseries\Large\sf}
+ \ChNumVar{\Huge}
+ \ChTitleVar{\bfseries\Large\rm}
+ \ChRuleWidth{1pt}
+ \ChNameUpperCase
+ \ChTitleUpperCase
+ \renewcommand{\DOCH}{%
+ \settoheight{\myhi}{\CTV\FmTi{Test}}
+ \setlength{\py}{\baselineskip}
+ \addtolength{\py}{\RW}
+ \addtolength{\py}{\myhi}
+ \setlength{\pyy}{\py}
+ \addtolength{\pyy}{-1\RW}
+
+ \raggedright
+ \CNV\FmN{\@chapapp}\space\CNoV\thechapter
+ \hskip 3pt\mghrulefill{\RW}\rule[-1\pyy]{2\RW}{\py}\par\nobreak}
+
+ \renewcommand{\DOTI}[1]{%
+ \addtolength{\pyy}{-4pt}
+ \settoheight{\myhi}{\CTV\FmTi{#1}}
+ \addtolength{\myhi}{\py}
+ \addtolength{\myhi}{-1\RW}
+ \vskip -1\pyy
+ \rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt
+ \raggedleft\CTV\FmTi{#1}\par\nobreak
+ \vskip 80\p@}
+
+\newlength{\backskip}
+ \renewcommand{\DOTIS}[1]{%
+% \setlength{\py}{10pt}
+% \setlength{\pyy}{\py}
+% \addtolength{\pyy}{\RW}
+% \setlength{\myhi}{\baselineskip}
+% \addtolength{\myhi}{\pyy}
+% \mghrulefill{\RW}\rule[-1\py]{2\RW}{\pyy}\par\nobreak
+% \addtolength{}{}
+%\vskip -1\baselineskip
+% \rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt
+% \raggedleft\CTV\FmTi{#1}\par\nobreak
+% \vskip 60\p@}
+%% Fix suggested by Tomas Lundberg
+ \setlength{\py}{25pt} % eller vad man vill
+ \setlength{\pyy}{\py}
+ \setlength{\backskip}{\py}
+ \addtolength{\backskip}{2pt}
+ \addtolength{\pyy}{\RW}
+ \setlength{\myhi}{\baselineskip}
+ \addtolength{\myhi}{\pyy}
+ \mghrulefill{\RW}\rule[-1\py]{2\RW}{\pyy}\par\nobreak
+ \vskip -1\backskip
+ \rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 3pt %
+ \raggedleft\CTV\FmTi{#1}\par\nobreak
+ \vskip 40\p@}
+ }
+
+%%%%%%% CONNY DEF
+
+\DeclareOption{Conny}{%
+ \ChNameUpperCase
+ \ChTitleUpperCase
+ \ChNameVar{\centering\Huge\rm\bfseries}
+ \ChNumVar{\Huge}
+ \ChTitleVar{\centering\Huge\rm}
+ \ChRuleWidth{2pt}
+
+ \renewcommand{\DOCH}{%
+ \mghrulefill{3\RW}\par\nobreak
+ \vskip -0.5\baselineskip
+ \mghrulefill{\RW}\par\nobreak
+ \CNV\FmN{\@chapapp}\space \CNoV\thechapter
+ \par\nobreak
+ \vskip -0.5\baselineskip
+ }
+ \renewcommand{\DOTI}[1]{%
+ \mghrulefill{\RW}\par\nobreak
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 60\p@
+ }
+ \renewcommand{\DOTIS}[1]{%
+ \mghrulefill{\RW}\par\nobreak
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 60\p@
+ }
+ }
+
+%%%%%%% REJNE DEF
+
+\DeclareOption{Rejne}{%
+
+ \ChNameUpperCase
+ \ChTitleUpperCase
+ \ChNameVar{\centering\Large\rm}
+ \ChNumVar{\Huge}
+ \ChTitleVar{\centering\Huge\rm}
+ \ChRuleWidth{1pt}
+ \renewcommand{\DOCH}{%
+ \settoheight{\py}{\CNoV\thechapter}
+ \parskip=0pt plus 1pt % Set parskip to default, just in case v1.31
+ \addtolength{\py}{-1pt}
+ \CNV\FmN{\@chapapp}\par\nobreak
+ \vskip 20\p@
+ \setlength{\myhi}{2\baselineskip}
+ \setlength{\px}{\myhi}
+ \addtolength{\px}{-1\RW}
+ \rule[-1\px]{\RW}{\myhi}\mghrulefill{\RW}\hskip
+ 10pt\raisebox{-0.5\py}{\CNoV\thechapter}\hskip 10pt\mghrulefill{\RW}\rule[-1\px]{\RW}{\myhi}\par\nobreak
+ \vskip -3\p@% Added -2pt vskip to correct for streched text v1.31
+ }
+ \renewcommand{\DOTI}[1]{%
+ \setlength{\mylen}{\textwidth}
+ \parskip=0pt plus 1pt % Set parskip to default, just in case v1.31
+ \addtolength{\mylen}{-2\RW}
+ {\vrule width\RW}\parbox{\mylen}{\CTV\FmTi{#1}}{\vrule width\RW}\par\nobreak%
+ \vskip -3pt\rule{\RW}{2\baselineskip}\mghrulefill{\RW}\rule{\RW}{2\baselineskip}%
+ \vskip 60\p@% Added -2pt in vskip to correct for streched text v1.31
+ }
+ \renewcommand{\DOTIS}[1]{%
+ \setlength{\py}{\fboxrule}
+ \setlength{\fboxrule}{\RW}
+ \setlength{\mylen}{\textwidth}
+ \addtolength{\mylen}{-2\RW}
+ \fbox{\parbox{\mylen}{\vskip 2\baselineskip\CTV\FmTi{#1}\par\nobreak\vskip \baselineskip}}
+ \setlength{\fboxrule}{\py}
+ \vskip 60\p@
+ }
+ }
+
+
+%%%%%%% BJARNE DEF
+
+\DeclareOption{Bjarne}{%
+ \ChNameUpperCase
+ \ChTitleUpperCase
+ \ChNameVar{\raggedleft\normalsize\rm}
+ \ChNumVar{\raggedleft \bfseries\Large}
+ \ChTitleVar{\raggedleft \Large\rm}
+ \ChRuleWidth{1pt}
+
+
+%% Note thechapter -> c at chapter fix appendix bug
+%% Fixed misspelled 12
+
+ \newcounter{AlphaCnt}
+ \newcounter{AlphaDecCnt}
+ \newcommand{\AlphaNo}{%
+ \ifcase\number\theAlphaCnt
+ \ifnum\c at chapter=0
+ ZERO\else{}\fi
+ \or ONE\or TWO\or THREE\or FOUR\or FIVE
+ \or SIX\or SEVEN\or EIGHT\or NINE\or TEN
+ \or ELEVEN\or TWELVE\or THIRTEEN\or FOURTEEN\or FIFTEEN
+ \or SIXTEEN\or SEVENTEEN\or EIGHTEEN\or NINETEEN\fi
+}
+
+ \newcommand{\AlphaDecNo}{%
+ \setcounter{AlphaDecCnt}{0}
+ \@whilenum\number\theAlphaCnt>0\do
+ {\addtocounter{AlphaCnt}{-10}
+ \addtocounter{AlphaDecCnt}{1}}
+ \ifnum\number\theAlphaCnt=0
+ \else
+ \addtocounter{AlphaDecCnt}{-1}
+ \addtocounter{AlphaCnt}{10}
+ \fi
+
+
+ \ifcase\number\theAlphaDecCnt\or TEN\or TWENTY\or THIRTY\or
+ FORTY\or FIFTY\or SIXTY\or SEVENTY\or EIGHTY\or NINETY\fi
+ }
+ \newcommand{\TheAlphaChapter}{%
+
+ \ifinapp
+ \thechapter
+ \else
+ \setcounter{AlphaCnt}{\c at chapter}
+ \ifnum\c at chapter<20
+ \AlphaNo
+ \else
+ \AlphaDecNo\AlphaNo
+ \fi
+ \fi
+ }
+ \renewcommand{\DOCH}{%
+ \mghrulefill{\RW}\par\nobreak
+ \CNV\FmN{\@chapapp}\par\nobreak
+ \CNoV\TheAlphaChapter\par\nobreak
+ \vskip -1\baselineskip\vskip 5pt\mghrulefill{\RW}\par\nobreak
+ \vskip 20\p@
+ }
+ \renewcommand{\DOTI}[1]{%
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 40\p@
+ }
+ \renewcommand{\DOTIS}[1]{%
+ \CTV\FmTi{#1}\par\nobreak
+ \vskip 40\p@
+ }
+}
+
+\DeclareOption*{%
+ \PackageWarning{fancychapter}{unknown style option}
+ }
+
+\ProcessOptions* \relax
+
+\ifusecolor
+ \RequirePackage{color}
+\fi
+\def\@makechapterhead#1{%
+ \vspace*{50\p@}%
+ {\parindent \z@ \raggedright \normalfont
+ \ifnum \c at secnumdepth >\m at ne
+ \if at mainmatter%%%%% Fix for frontmatter, mainmatter, and backmatter 040920
+ \DOCH
+ \fi
+ \fi
+ \interlinepenalty\@M
+ \if at mainmatter%%%%% Fix for frontmatter, mainmatter, and backmatter 060424
+ \DOTI{#1}%
+ \else%
+ \DOTIS{#1}%
+ \fi
+ }}
+
+
+%%% Begin: To avoid problem with scrbook.cls (fncychap version 1.32)
+
+%%OUT:
+%\def\@schapter#1{\if at twocolumn
+% \@topnewpage[\@makeschapterhead{#1}]%
+% \else
+% \@makeschapterhead{#1}%
+% \@afterheading
+% \fi}
+
+%%IN:
+\def\@schapter#1{%
+\if at twocolumn%
+ \@makeschapterhead{#1}%
+\else%
+ \@makeschapterhead{#1}%
+ \@afterheading%
+\fi}
+
+%%% End: To avoid problem with scrbook.cls (fncychap version 1.32)
+
+\def\@makeschapterhead#1{%
+ \vspace*{50\p@}%
+ {\parindent \z@ \raggedright
+ \normalfont
+ \interlinepenalty\@M
+ \DOTIS{#1}
+ \vskip 40\p@
+ }}
+
+\endinput
+
+
diff --git a/sphinx/texinputs/python.ist b/sphinx/texinputs/python.ist
new file mode 100644
index 0000000..9ffa0f9
--- /dev/null
+++ b/sphinx/texinputs/python.ist
@@ -0,0 +1,11 @@
+line_max 100
+headings_flag 1
+heading_prefix " \\bigletter "
+
+preamble "\\begin{theindex}
+\\def\\bigletter#1{{\\Large\\sffamily#1}\\nopagebreak\\vspace{1mm}}
+
+"
+
+symhead_positive "{Symbols}"
+numhead_positive "{Numbers}"
diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty
new file mode 100644
index 0000000..ee0a923
--- /dev/null
+++ b/sphinx/texinputs/sphinx.sty
@@ -0,0 +1,524 @@
+%
+% sphinx.sty
+%
+% Adapted from the old python.sty, mostly written by Fred Drake,
+% by Georg Brandl.
+%
+
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesPackage{sphinx}[2010/01/15 LaTeX package (Sphinx markup)]
+
+\@ifclassloaded{memoir}{}{\RequirePackage{fancyhdr}}
+
+\RequirePackage{textcomp}
+\RequirePackage{fancybox}
+\RequirePackage{titlesec}
+\RequirePackage{tabulary}
+\RequirePackage{amsmath} % for \text
+\RequirePackage{makeidx}
+\RequirePackage{framed}
+\RequirePackage{ifthen}
+\RequirePackage{color}
+% For highlighted code.
+\RequirePackage{fancyvrb}
+% For table captions.
+\RequirePackage{threeparttable}
+% Handle footnotes in tables.
+\RequirePackage{footnote}
+\makesavenoteenv{tabulary}
+% For floating figures in the text.
+\RequirePackage{wrapfig}
+% Separate paragraphs by space by default.
+\RequirePackage{parskip}
+% For parsed-literal blocks.
+\RequirePackage{alltt}
+% Display "real" single quotes in literal blocks.
+\RequirePackage{upquote}
+
+% Redefine these colors to your liking in the preamble.
+\definecolor{TitleColor}{rgb}{0.126,0.263,0.361}
+\definecolor{InnerLinkColor}{rgb}{0.208,0.374,0.486}
+\definecolor{OuterLinkColor}{rgb}{0.216,0.439,0.388}
+% Redefine these colors to something not white if you want to have colored
+% background and border for code examples.
+\definecolor{VerbatimColor}{rgb}{1,1,1}
+\definecolor{VerbatimBorderColor}{rgb}{1,1,1}
+
+% Uncomment these two lines to ignore the paper size and make the page
+% size more like a typical published manual.
+%\renewcommand{\paperheight}{9in}
+%\renewcommand{\paperwidth}{8.5in} % typical squarish manual
+%\renewcommand{\paperwidth}{7in} % O'Reilly ``Programmming Python''
+
+% use pdfoutput for pTeX and dvipdfmx
+\ifx\kanjiskip\undefined\else
+ \ifx\Gin at driver{dvipdfmx.def}\undefined\else
+ \newcount\pdfoutput\pdfoutput=0
+ \fi
+\fi
+
+% For graphicx, check if we are compiling under latex or pdflatex.
+\ifx\pdftexversion\undefined
+ \usepackage{graphicx}
+\else
+ \usepackage[pdftex]{graphicx}
+\fi
+
+% for PDF output, use colors and maximal compression
+\newif\ifsphinxpdfoutput\sphinxpdfoutputfalse
+\ifx\pdfoutput\undefined\else\ifcase\pdfoutput
+ \let\py at NormalColor\relax
+ \let\py at TitleColor\relax
+\else
+ \sphinxpdfoutputtrue
+ \input{pdfcolor}
+ \def\py at NormalColor{\color[rgb]{0.0,0.0,0.0}}
+ \def\py at TitleColor{\color{TitleColor}}
+ \pdfcompresslevel=9
+\fi\fi
+
+% XeLaTeX can do colors, too
+\ifx\XeTeXrevision\undefined\else
+ \def\py at NormalColor{\color[rgb]{0.0,0.0,0.0}}
+ \def\py at TitleColor{\color{TitleColor}}
+\fi
+
+% Increase printable page size (copied from fullpage.sty)
+\topmargin 0pt
+\advance \topmargin by -\headheight
+\advance \topmargin by -\headsep
+
+% attempt to work a little better for A4 users
+\textheight \paperheight
+\advance\textheight by -2in
+
+\oddsidemargin 0pt
+\evensidemargin 0pt
+%\evensidemargin -.25in % for ``manual size'' documents
+\marginparwidth 0.5in
+
+\textwidth \paperwidth
+\advance\textwidth by -2in
+
+
+% Style parameters and macros used by most documents here
+\raggedbottom
+\sloppy
+\hbadness = 5000 % don't print trivial gripes
+
+\pagestyle{empty} % start this way
+
+% Use this to set the font family for headers and other decor:
+\newcommand{\py at HeaderFamily}{\sffamily\bfseries}
+
+% Redefine the 'normal' header/footer style when using "fancyhdr" package:
+\@ifundefined{fancyhf}{}{
+ % Use \pagestyle{normal} as the primary pagestyle for text.
+ \fancypagestyle{normal}{
+ \fancyhf{}
+ \fancyfoot[LE,RO]{{\py at HeaderFamily\thepage}}
+ \fancyfoot[LO]{{\py at HeaderFamily\nouppercase{\rightmark}}}
+ \fancyfoot[RE]{{\py at HeaderFamily\nouppercase{\leftmark}}}
+ \fancyhead[LE,RO]{{\py at HeaderFamily \@title, \py at release}}
+ \renewcommand{\headrulewidth}{0.4pt}
+ \renewcommand{\footrulewidth}{0.4pt}
+ % define chaptermark with \@chappos when \@chappos is available for Japanese
+ \ifx\@chappos\undefined\else
+ \def\chaptermark##1{\markboth{\@chapapp\space\thechapter\space\@chappos\space ##1}{}}
+ \fi
+ }
+ % Update the plain style so we get the page number & footer line,
+ % but not a chapter or section title. This is to keep the first
+ % page of a chapter and the blank page between chapters `clean.'
+ \fancypagestyle{plain}{
+ \fancyhf{}
+ \fancyfoot[LE,RO]{{\py at HeaderFamily\thepage}}
+ \renewcommand{\headrulewidth}{0pt}
+ \renewcommand{\footrulewidth}{0.4pt}
+ }
+}
+
+% Some custom font markup commands.
+%
+\newcommand{\strong}[1]{{\textbf{#1}}}
+\newcommand{\code}[1]{\texttt{#1}}
+\newcommand{\bfcode}[1]{\code{\bfseries#1}}
+\newcommand{\email}[1]{\textsf{#1}}
+
+% Redefine the Verbatim environment to allow border and background colors.
+% The original environment is still used for verbatims within tables.
+\let\OriginalVerbatim=\Verbatim
+\let\endOriginalVerbatim=\endVerbatim
+
+% Play with vspace to be able to keep the indentation.
+\newlength\distancetoright
+\def\mycolorbox#1{%
+ \setlength\distancetoright{\linewidth}%
+ \advance\distancetoright -\@totalleftmargin %
+ \fcolorbox{VerbatimBorderColor}{VerbatimColor}{%
+ \begin{minipage}{\distancetoright}%
+ #1
+ \end{minipage}%
+ }%
+}
+\def\FrameCommand{\mycolorbox}
+
+\renewcommand{\Verbatim}[1][1]{%
+ % list starts new par, but we don't want it to be set apart vertically
+ \bgroup\parskip=0pt%
+ \smallskip%
+ % The list environement is needed to control perfectly the vertical
+ % space.
+ \list{}{%
+ \setlength\parskip{0pt}%
+ \setlength\itemsep{0ex}%
+ \setlength\topsep{0ex}%
+ \setlength\partopsep{0pt}%
+ \setlength\leftmargin{0pt}%
+ }%
+ \item\MakeFramed {\FrameRestore}%
+ \small%
+ \OriginalVerbatim[#1]%
+}
+\renewcommand{\endVerbatim}{%
+ \endOriginalVerbatim%
+ \endMakeFramed%
+ \endlist%
+ % close group to restore \parskip
+ \egroup%
+}
+
+
+% \moduleauthor{name}{email}
+\newcommand{\moduleauthor}[2]{}
+
+% \sectionauthor{name}{email}
+\newcommand{\sectionauthor}[2]{}
+
+% Augment the sectioning commands used to get our own font family in place,
+% and reset some internal data items:
+\titleformat{\section}{\Large\py at HeaderFamily}%
+ {\py at TitleColor\thesection}{0.5em}{\py at TitleColor}{\py at NormalColor}
+\titleformat{\subsection}{\large\py at HeaderFamily}%
+ {\py at TitleColor\thesubsection}{0.5em}{\py at TitleColor}{\py at NormalColor}
+\titleformat{\subsubsection}{\py at HeaderFamily}%
+ {\py at TitleColor\thesubsubsection}{0.5em}{\py at TitleColor}{\py at NormalColor}
+\titleformat{\paragraph}{\small\py at HeaderFamily}%
+ {\py at TitleColor}{0em}{\py at TitleColor}{\py at NormalColor}
+
+% {fulllineitems} is the main environment for object descriptions.
+%
+\newcommand{\py at itemnewline}[1]{%
+ \@tempdima\linewidth%
+ \advance\@tempdima \leftmargin\makebox[\@tempdima][l]{#1}%
+}
+
+\newenvironment{fulllineitems}{
+ \begin{list}{}{\labelwidth \leftmargin \labelsep 0pt
+ \rightmargin 0pt \topsep -\parskip \partopsep \parskip
+ \itemsep -\parsep
+ \let\makelabel=\py at itemnewline}
+}{\end{list}}
+
+% \optional is used for ``[, arg]``, i.e. desc_optional nodes.
+\newcommand{\optional}[1]{%
+ {\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}}
+
+\newlength{\py at argswidth}
+\newcommand{\py at sigparams}[2]{%
+ \parbox[t]{\py at argswidth}{#1\code{)}#2}}
+\newcommand{\pysigline}[1]{\item[#1]\nopagebreak}
+\newcommand{\pysiglinewithargsret}[3]{%
+ \settowidth{\py at argswidth}{#1\code{(}}%
+ \addtolength{\py at argswidth}{-2\py at argswidth}%
+ \addtolength{\py at argswidth}{\linewidth}%
+ \item[#1\code{(}\py at sigparams{#2}{#3}]}
+
+% Production lists
+%
+\newenvironment{productionlist}{
+% \def\optional##1{{\Large[}##1{\Large]}}
+ \def\production##1##2{\\\code{##1}&::=&\code{##2}}
+ \def\productioncont##1{\\& &\code{##1}}
+ \parindent=2em
+ \indent
+ \setlength{\LTpre}{0pt}
+ \setlength{\LTpost}{0pt}
+ \begin{longtable}[l]{lcl}
+}{%
+ \end{longtable}
+}
+
+% Notices / Admonitions
+%
+\newlength{\py at noticelength}
+
+\newcommand{\py at heavybox}{
+ \setlength{\fboxrule}{1pt}
+ \setlength{\fboxsep}{6pt}
+ \setlength{\py at noticelength}{\linewidth}
+ \addtolength{\py at noticelength}{-2\fboxsep}
+ \addtolength{\py at noticelength}{-2\fboxrule}
+ %\setlength{\shadowsize}{3pt}
+ \noindent\Sbox
+ \minipage{\py at noticelength}
+}
+\newcommand{\py at endheavybox}{
+ \endminipage
+ \endSbox
+ \fbox{\TheSbox}
+}
+
+\newcommand{\py at lightbox}{{%
+ \setlength\parskip{0pt}\par
+ \noindent\rule[0ex]{\linewidth}{0.5pt}%
+ \par\noindent\vspace{-0.5ex}%
+ }}
+\newcommand{\py at endlightbox}{{%
+ \setlength{\parskip}{0pt}%
+ \par\noindent\rule[0.5ex]{\linewidth}{0.5pt}%
+ \par\vspace{-0.5ex}%
+ }}
+
+% Some are quite plain:
+\newcommand{\py at noticestart@note}{\py at lightbox}
+\newcommand{\py at noticeend@note}{\py at endlightbox}
+\newcommand{\py at noticestart@hint}{\py at lightbox}
+\newcommand{\py at noticeend@hint}{\py at endlightbox}
+\newcommand{\py at noticestart@important}{\py at lightbox}
+\newcommand{\py at noticeend@important}{\py at endlightbox}
+\newcommand{\py at noticestart@tip}{\py at lightbox}
+\newcommand{\py at noticeend@tip}{\py at endlightbox}
+
+% Others gets more visible distinction:
+\newcommand{\py at noticestart@warning}{\py at heavybox}
+\newcommand{\py at noticeend@warning}{\py at endheavybox}
+\newcommand{\py at noticestart@caution}{\py at heavybox}
+\newcommand{\py at noticeend@caution}{\py at endheavybox}
+\newcommand{\py at noticestart@attention}{\py at heavybox}
+\newcommand{\py at noticeend@attention}{\py at endheavybox}
+\newcommand{\py at noticestart@danger}{\py at heavybox}
+\newcommand{\py at noticeend@danger}{\py at endheavybox}
+\newcommand{\py at noticestart@error}{\py at heavybox}
+\newcommand{\py at noticeend@error}{\py at endheavybox}
+
+\newenvironment{notice}[2]{
+ \def\py at noticetype{#1}
+ \csname py at noticestart@#1\endcsname
+ \strong{#2}
+}{\csname py at noticeend@\py at noticetype\endcsname}
+
+% Allow the release number to be specified independently of the
+% \date{}. This allows the date to reflect the document's date and
+% release to specify the release that is documented.
+%
+\newcommand{\py at release}{}
+\newcommand{\version}{}
+\newcommand{\shortversion}{}
+\newcommand{\releaseinfo}{}
+\newcommand{\releasename}{Release}
+\newcommand{\release}[1]{%
+ \renewcommand{\py at release}{\releasename\space\version}%
+ \renewcommand{\version}{#1}}
+\newcommand{\setshortversion}[1]{%
+ \renewcommand{\shortversion}{#1}}
+\newcommand{\setreleaseinfo}[1]{%
+ \renewcommand{\releaseinfo}{#1}}
+
+% Allow specification of the author's address separately from the
+% author's name. This can be used to format them differently, which
+% is a good thing.
+%
+\newcommand{\py at authoraddress}{}
+\newcommand{\authoraddress}[1]{\renewcommand{\py at authoraddress}{#1}}
+
+% This sets up the fancy chapter headings that make the documents look
+% at least a little better than the usual LaTeX output.
+%
+\@ifundefined{ChTitleVar}{}{
+ \ChNameVar{\raggedleft\normalsize\py at HeaderFamily}
+ \ChNumVar{\raggedleft \bfseries\Large\py at HeaderFamily}
+ \ChTitleVar{\raggedleft \textrm{\Huge\py at HeaderFamily}}
+ % This creates chapter heads without the leading \vspace*{}:
+ \def\@makechapterhead#1{%
+ {\parindent \z@ \raggedright \normalfont
+ \ifnum \c at secnumdepth >\m at ne
+ \DOCH
+ \fi
+ \interlinepenalty\@M
+ \DOTI{#1}
+ }
+ }
+}
+
+% Redefine description environment so that it is usable inside fulllineitems.
+%
+\renewcommand{\description}{%
+ \list{}{\labelwidth\z@%
+ \itemindent-\leftmargin%
+ \labelsep5pt%
+ \let\makelabel=\descriptionlabel}}
+
+% Definition lists; requested by AMK for HOWTO documents. Probably useful
+% elsewhere as well, so keep in in the general style support.
+%
+\newenvironment{definitions}{%
+ \begin{description}%
+ \def\term##1{\item[##1]\mbox{}\\*[0mm]}
+}{%
+ \end{description}%
+}
+
+% Tell TeX about pathological hyphenation cases:
+\hyphenation{Base-HTTP-Re-quest-Hand-ler}
+
+
+% The following is stuff copied from docutils' latex writer.
+%
+\newcommand{\optionlistlabel}[1]{\bf #1 \hfill}
+\newenvironment{optionlist}[1]
+{\begin{list}{}
+ {\setlength{\labelwidth}{#1}
+ \setlength{\rightmargin}{1cm}
+ \setlength{\leftmargin}{\rightmargin}
+ \addtolength{\leftmargin}{\labelwidth}
+ \addtolength{\leftmargin}{\labelsep}
+ \renewcommand{\makelabel}{\optionlistlabel}}
+}{\end{list}}
+
+\newlength{\lineblockindentation}
+\setlength{\lineblockindentation}{2.5em}
+\newenvironment{lineblock}[1]
+{\begin{list}{}
+ {\setlength{\partopsep}{\parskip}
+ \addtolength{\partopsep}{\baselineskip}
+ \topsep0pt\itemsep0.15\baselineskip\parsep0pt
+ \leftmargin#1}
+ \raggedright}
+{\end{list}}
+
+% Redefine includgraphics for avoiding images larger than the screen size
+% If the size is not specified.
+\let\py at Oldincludegraphics\includegraphics
+
+\newbox\image at box%
+\newdimen\image at width%
+\renewcommand\includegraphics[2][\@empty]{%
+ \ifx#1\@empty%
+ \setbox\image at box=\hbox{\py at Oldincludegraphics{#2}}%
+ \image at width\wd\image at box%
+ \ifdim \image at width>\linewidth%
+ \setbox\image at box=\hbox{\py at Oldincludegraphics[width=\linewidth]{#2}}%
+ \box\image at box%
+ \else%
+ \py at Oldincludegraphics{#2}%
+ \fi%
+ \else%
+ \py at Oldincludegraphics[#1]{#2}%
+ \fi%
+}
+
+% to make pdf with correct encoded bookmarks in Japanese
+% this should precede the hyperref package
+\ifx\kanjiskip\undefined\else
+ \usepackage{atbegshi}
+ \ifx\ucs\undefined
+ \ifnum 42146=\euc"A4A2
+ \AtBeginShipoutFirst{\special{pdf:tounicode EUC-UCS2}}
+ \else
+ \AtBeginShipoutFirst{\special{pdf:tounicode 90ms-RKSJ-UCS2}}
+ \fi
+ \else
+ \AtBeginShipoutFirst{\special{pdf:tounicode UTF8-UCS2}}
+ \fi
+\fi
+
+% Include hyperref last.
+\RequirePackage[colorlinks,breaklinks,
+ linkcolor=InnerLinkColor,filecolor=OuterLinkColor,
+ menucolor=OuterLinkColor,urlcolor=OuterLinkColor,
+ citecolor=InnerLinkColor]{hyperref}
+% Fix anchor placement for figures with captions.
+% (Note: we don't use a package option here; instead, we give an explicit
+% \capstart for figures that actually have a caption.)
+\RequirePackage{hypcap}
+
+% From docutils.writers.latex2e
+\providecommand{\DUspan}[2]{%
+ {% group ("span") to limit the scope of styling commands
+ \@for\node at class@name:=#1\do{%
+ \ifcsname docutilsrole\node at class@name\endcsname%
+ \csname docutilsrole\node at class@name\endcsname%
+ \fi%
+ }%
+ {#2}% node content
+ }% close "span"
+}
+
+\providecommand*{\DUprovidelength}[2]{
+ \ifthenelse{\isundefined{#1}}{\newlength{#1}\setlength{#1}{#2}}{}
+}
+
+\DUprovidelength{\DUlineblockindent}{2.5em}
+\ifthenelse{\isundefined{\DUlineblock}}{
+ \newenvironment{DUlineblock}[1]{%
+ \list{}{\setlength{\partopsep}{\parskip}
+ \addtolength{\partopsep}{\baselineskip}
+ \setlength{\topsep}{0pt}
+ \setlength{\itemsep}{0.15\baselineskip}
+ \setlength{\parsep}{0pt}
+ \setlength{\leftmargin}{#1}}
+ \raggedright
+ }
+ {\endlist}
+}{}
+
+
+% From footmisc.sty: allows footnotes in titles
+\let\FN at sf@@footnote\footnote
+\def\footnote{\ifx\protect\@typeset at protect
+ \expandafter\FN at sf@@footnote
+ \else
+ \expandafter\FN at sf@gobble at opt
+ \fi
+}
+\edef\FN at sf@gobble at opt{\noexpand\protect
+ \expandafter\noexpand\csname FN at sf@gobble at opt \endcsname}
+\expandafter\def\csname FN at sf@gobble at opt \endcsname{%
+ \@ifnextchar[%]
+ \FN at sf@gobble at twobracket
+ \@gobble
+}
+\def\FN at sf@gobble at twobracket[#1]#2{}
+
+% adjust the margins for footer,
+% this works with the jsclasses only (Japanese standard document classes)
+\ifx\@jsc at uplatextrue\undefined\else
+ \hypersetup{setpagesize=false}
+ \setlength\footskip{2\baselineskip}
+ \addtolength{\textheight}{-2\baselineskip}
+\fi
+
+% fix the double index and bibliography on the table of contents
+% in jsclasses (Japanese standard document classes)
+\ifx\@jsc at uplatextrue\undefined\else
+ \renewcommand{\theindex}{
+ \cleardoublepage
+ \phantomsection
+ \py at OldTheindex
+ }
+ \renewcommand{\thebibliography}[1]{
+ \cleardoublepage
+ \phantomsection
+ \py at OldThebibliography{1}
+ }
+\fi
+
+% disable \@chappos in Appendix in pTeX
+\ifx\kanjiskip\undefined\else
+ \let\py at OldAppendix=\appendix
+ \renewcommand{\appendix}{
+ \py at OldAppendix
+ \gdef\@chappos{}
+ }
+\fi
diff --git a/sphinx/texinputs/sphinxhowto.cls b/sphinx/texinputs/sphinxhowto.cls
new file mode 100644
index 0000000..26e63a7
--- /dev/null
+++ b/sphinx/texinputs/sphinxhowto.cls
@@ -0,0 +1,104 @@
+%
+% sphinxhowto.cls for Sphinx (http://sphinx-doc.org/)
+%
+
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesClass{sphinxhowto}[2009/06/02 Document class (Sphinx HOWTO)]
+
+% 'oneside' option overriding the 'twoside' default
+\newif\if at oneside
+\DeclareOption{oneside}{\@onesidetrue}
+% Pass remaining document options to the parent class.
+\DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}}
+\ProcessOptions\relax
+
+% Default to two-side document
+\if at oneside
+% nothing to do (oneside is the default)
+\else
+\PassOptionsToClass{twoside}{\sphinxdocclass}
+\fi
+
+\LoadClass{\sphinxdocclass}
+
+% Set some sane defaults for section numbering depth and TOC depth. You can
+% reset these counters in your preamble.
+%
+\setcounter{secnumdepth}{2}
+
+% Change the title page to look a bit better, and fit in with the fncychap
+% ``Bjarne'' style a bit better.
+%
+\renewcommand{\maketitle}{
+ \rule{\textwidth}{1pt}
+ \ifsphinxpdfoutput
+ \begingroup
+ % These \defs are required to deal with multi-line authors; it
+ % changes \\ to ', ' (comma-space), making it pass muster for
+ % generating document info in the PDF file.
+ \def\\{, }
+ \def\and{and }
+ \pdfinfo{
+ /Author (\@author)
+ /Title (\@title)
+ }
+ \endgroup
+ \fi
+ \begin{flushright}
+ \sphinxlogo%
+ {\rm\Huge\py at HeaderFamily \@title} \par
+ {\em\large\py at HeaderFamily \py at release\releaseinfo} \par
+ \vspace{25pt}
+ {\Large\py at HeaderFamily
+ \begin{tabular}[t]{c}
+ \@author
+ \end{tabular}} \par
+ \vspace{25pt}
+ \@date \par
+ \py at authoraddress \par
+ \end{flushright}
+ \@thanks
+ \setcounter{footnote}{0}
+ \let\thanks\relax\let\maketitle\relax
+ %\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
+}
+
+\let\py at OldTableofcontents=\tableofcontents
+\renewcommand{\tableofcontents}{
+ \begingroup
+ \parskip = 0mm
+ \py at OldTableofcontents
+ \endgroup
+ \rule{\textwidth}{1pt}
+ \vspace{12pt}
+}
+
+\@ifundefined{fancyhf}{
+ \pagestyle{plain}}{
+ \pagestyle{normal}} % start this way; change for
+\pagenumbering{arabic} % ToC & chapters
+
+\thispagestyle{empty}
+
+% Fix the bibliography environment to add an entry to the Table of
+% Contents.
+% For an article document class this environment is a section,
+% so no page break before it.
+\let\py at OldThebibliography=\thebibliography
+\renewcommand{\thebibliography}[1]{
+ \phantomsection
+ \py at OldThebibliography{1}
+ \addcontentsline{toc}{section}{\bibname}
+}
+
+% Same for the indices.
+% The memoir class already does this, so we don't duplicate it in that case.
+%
+\@ifclassloaded{memoir}{}{
+ \let\py at OldTheindex=\theindex
+ \renewcommand{\theindex}{
+ \phantomsection
+ \py at OldTheindex
+ \addcontentsline{toc}{section}{\indexname}
+ }
+}
diff --git a/sphinx/texinputs/sphinxmanual.cls b/sphinx/texinputs/sphinxmanual.cls
new file mode 100644
index 0000000..a6b9b39
--- /dev/null
+++ b/sphinx/texinputs/sphinxmanual.cls
@@ -0,0 +1,148 @@
+%
+% sphinxmanual.cls for Sphinx (http://sphinx-doc.org/)
+%
+
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesClass{sphinxmanual}[2009/06/02 Document class (Sphinx manual)]
+
+% chapters starting at odd pages (overridden by 'openany' document option)
+\PassOptionsToClass{openright}{\sphinxdocclass}
+
+% 'oneside' option overriding the 'twoside' default
+\newif\if at oneside
+\DeclareOption{oneside}{\@onesidetrue}
+% Pass remaining document options to the parent class.
+\DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}}
+\ProcessOptions\relax
+
+% Defaults two-side document
+\if at oneside
+% nothing to do (oneside is the default)
+\else
+\PassOptionsToClass{twoside}{\sphinxdocclass}
+\fi
+
+\LoadClass{\sphinxdocclass}
+
+% Set some sane defaults for section numbering depth and TOC depth. You can
+% reset these counters in your preamble.
+%
+\setcounter{secnumdepth}{2}
+\setcounter{tocdepth}{1}
+
+% Change the title page to look a bit better, and fit in with the fncychap
+% ``Bjarne'' style a bit better.
+%
+\renewcommand{\maketitle}{%
+ \begin{titlepage}%
+ \let\footnotesize\small
+ \let\footnoterule\relax
+ \rule{\textwidth}{1pt}%
+ \ifsphinxpdfoutput
+ \begingroup
+ % These \defs are required to deal with multi-line authors; it
+ % changes \\ to ', ' (comma-space), making it pass muster for
+ % generating document info in the PDF file.
+ \def\\{, }
+ \def\and{and }
+ \pdfinfo{
+ /Author (\@author)
+ /Title (\@title)
+ }
+ \endgroup
+ \fi
+ \begin{flushright}%
+ \sphinxlogo%
+ {\rm\Huge\py at HeaderFamily \@title \par}%
+ {\em\LARGE\py at HeaderFamily \py at release\releaseinfo \par}
+ \vfill
+ {\LARGE\py at HeaderFamily
+ \begin{tabular}[t]{c}
+ \@author
+ \end{tabular}
+ \par}
+ \vfill\vfill
+ {\large
+ \@date \par
+ \vfill
+ \py at authoraddress \par
+ }%
+ \end{flushright}%\par
+ \@thanks
+ \end{titlepage}%
+ \cleardoublepage%
+ \setcounter{footnote}{0}%
+ \let\thanks\relax\let\maketitle\relax
+ %\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
+}
+
+
+% Catch the end of the {abstract} environment, but here make sure the abstract
+% is followed by a blank page if the 'openright' option is used.
+%
+\let\py at OldEndAbstract=\endabstract
+\renewcommand{\endabstract}{
+ \if at openright
+ \ifodd\value{page}
+ \typeout{Adding blank page after the abstract.}
+ \vfil\pagebreak
+ \fi
+ \fi
+ \py at OldEndAbstract
+}
+
+% This wraps the \tableofcontents macro with all the magic to get the spacing
+% right and have the right number of pages if the 'openright' option has been
+% used. This eliminates a fair amount of crud in the individual document files.
+%
+\let\py at OldTableofcontents=\tableofcontents
+\renewcommand{\tableofcontents}{%
+ \pagenumbering{roman}%
+ \setcounter{page}{1}%
+ \pagebreak%
+ \pagestyle{plain}%
+ {%
+ \parskip = 0mm%
+ \py at OldTableofcontents%
+ \if at openright%
+ \ifodd\value{page}%
+ \typeout{Adding blank page after the table of contents.}%
+ \pagebreak\hspace{0pt}%
+ \fi%
+ \fi%
+ \cleardoublepage%
+ }%
+ \pagenumbering{arabic}%
+ \@ifundefined{fancyhf}{}{\pagestyle{normal}}%
+}
+\pagenumbering{alph}
+
+% This is needed to get the width of the section # area wide enough in the
+% library reference. Doing it here keeps it the same for all the manuals.
+%
+\renewcommand*\l at section{\@dottedtocline{1}{1.5em}{2.6em}}
+\renewcommand*\l at subsection{\@dottedtocline{2}{4.1em}{3.5em}}
+
+% Fix the bibliography environment to add an entry to the Table of
+% Contents.
+% For a report document class this environment is a chapter.
+\let\py at OldThebibliography=\thebibliography
+\renewcommand{\thebibliography}[1]{
+ \cleardoublepage
+ \phantomsection
+ \py at OldThebibliography{1}
+ \addcontentsline{toc}{chapter}{\bibname}
+}
+
+% Same for the indices.
+% The memoir class already does this, so we don't duplicate it in that case.
+%
+\@ifclassloaded{memoir}{}{
+ \let\py at OldTheindex=\theindex
+ \renewcommand{\theindex}{
+ \cleardoublepage
+ \phantomsection
+ \py at OldTheindex
+ \addcontentsline{toc}{chapter}{\indexname}
+ }
+}
diff --git a/sphinx/texinputs/tabulary.sty b/sphinx/texinputs/tabulary.sty
new file mode 100644
index 0000000..11fdf74
--- /dev/null
+++ b/sphinx/texinputs/tabulary.sty
@@ -0,0 +1,452 @@
+%%
+%% This is file `tabulary.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% tabulary.dtx (with options: `package')
+%% DRAFT VERSION
+%%
+%% File `tabulary.dtx'.
+%% Copyright (C) 1995 1996 2003 2008 David Carlisle
+%% This file may be distributed under the terms of the LPPL.
+%% See 00readme.txt for details.
+%%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{tabulary}
+ [2008/12/01 v0.9 tabulary package (DPC)]
+\RequirePackage{array}
+\catcode`\Z=14
+\DeclareOption{debugshow}{\catcode`\Z=9\relax}
+\ProcessOptions
+\def\arraybackslash{\let\\=\@arraycr}
+\def\@finalstrut#1{%
+ \unskip\ifhmode\nobreak\fi\vrule\@width\z@\@height\z@\@depth\dp#1}
+\newcount\TY at count
+\def\tabulary{%
+ \let\TY at final\tabular
+ \let\endTY at final\endtabular
+ \TY at tabular}
+\def\TY at tabular#1{%
+ \edef\TY@{\@currenvir}%
+ {\ifnum0=`}\fi
+ \@ovxx\TY at linewidth
+ \@ovyy\TY at tablewidth
+ \count@\z@
+ \@tempswatrue
+ \@whilesw\if at tempswa\fi{%
+ \advance\count@\@ne
+ \expandafter\ifx\csname TY at F\the\count@\endcsname\relax
+ \@tempswafalse
+ \else
+ \expandafter\let\csname TY at SF\the\count@\expandafter\endcsname
+ \csname TY at F\the\count@\endcsname
+ \global\expandafter\let\csname TY at F\the\count@\endcsname\relax
+ \expandafter\let\csname TY at S\the\count@\expandafter\endcsname
+ \csname TY@\the\count@\endcsname
+ \fi}%
+ \global\TY at count\@ne
+ \TY at width\xdef{0pt}%
+ \global\TY at tablewidth\z@
+ \global\TY at linewidth#1\relax
+Z\message{^^J^^JTable^^J%
+Z Target Width: \the\TY at linewidth^^J%
+Z \string\tabcolsep: \the\tabcolsep\space
+Z \string\arrayrulewidth: \the\arrayrulewidth\space
+Z \string\doublerulesep: \the\doublerulesep^^J%
+Z \string\tymin: \the\tymin\space
+Z \string\tymax: \the\tymax^^J}%
+ \let\@classz\TY at classz
+ \let\verb\TX at verb
+ \toks@{}\TY at get@body}
+\let\TY@@mkpream\@mkpream
+\def\TY at mkpream{%
+ \def\@addamp{%
+ \if at firstamp \@firstampfalse \else
+ \global\advance\TY at count\@ne
+ \edef\@preamble{\@preamble &}\fi
+ \TY at width\xdef{0pt}}%
+ \def\@acol{%
+ \TY at subwidth\col at sep
+ \@addtopreamble{\hskip\col at sep}}%
+ \let\@arrayrule\TY at arrayrule
+ \let\@classvi\TY at classvi
+ \def\@classv{\save at decl
+ \expandafter\NC at ecs\@nextchar\extracolsep{}\extracolsep\@@@
+ \sbox\z@{\d at llarbegin\@nextchar\d at llarend}%
+ \TY at subwidth{\wd\z@}%
+ \@addtopreamble{\d at llarbegin\the at toks\the\count@\relax\d at llarend}%
+ \prepnext at tok}%
+ \global\let\@mkpream\TY@@mkpream
+ \TY@@mkpream}
+\def\TY at arrayrule{%
+ \TY at subwidth\arrayrulewidth
+ \@addtopreamble \vline}
+\def\TY at classvi{\ifcase \@lastchclass
+ \@acol \or
+ \TY at subwidth\doublerulesep
+ \@addtopreamble{\hskip \doublerulesep}\or
+ \@acol \or
+ \@classvii
+ \fi}
+\def\TY at tab{%
+ \setbox\z@\hbox\bgroup
+ \let\[$\let\]$%
+ \let\equation$\let\endequation$%
+ \col at sep\tabcolsep
+ \let\d at llarbegin\begingroup\let\d at llarend\endgroup
+ \let\@mkpream\TY at mkpream
+ \def\multicolumn##1##2##3{\multispan##1\relax}%
+ \CT at start\TY at tabarray}
+\def\TY at tabarray{\@ifnextchar[{\TY at array}{\@array[t]}}
+\def\TY at array[#1]{\@array[t]}
+\def\TY at width#1{%
+ \expandafter#1\csname TY@\the\TY at count\endcsname}
+\def\TY at subwidth#1{%
+ \TY at width\dimen@
+ \advance\dimen at -#1\relax
+ \TY at width\xdef{\the\dimen@}%
+ \global\advance\TY at linewidth-#1\relax}
+\def\endtabulary{%
+ \gdef\@halignto{}%
+ \let\TY at footnote\footnote%
+ \def\footnote{}% prevent footnotes from doing anything
+ \expandafter\TY at tab\the\toks@
+ \crcr\omit
+ {\xdef\TY at save@row{}%
+ \loop
+ \advance\TY at count\m at ne
+ \ifnum\TY at count>\z@
+ \xdef\TY at save@row{\TY at save@row&\omit}%
+ \repeat}\TY at save@row
+ \endarray\global\setbox1=\lastbox\setbox0=\vbox{\unvbox1
+ \unskip\global\setbox1=\lastbox}\egroup
+ \dimen@\TY at linewidth
+ \divide\dimen@\TY at count
+ \ifdim\dimen@<\tymin
+ \TY at warn{tymin too large (\the\tymin), resetting to \the\dimen@}%
+ \tymin\dimen@
+ \fi
+ \setbox\tw@=\hbox{\unhbox\@ne
+ \loop
+\@tempdima=\lastskip
+\ifdim\@tempdima>\z@
+Z \message{ecs=\the\@tempdima^^J}%
+ \global\advance\TY at linewidth-\@tempdima
+\fi
+ \unskip
+ \setbox\tw@=\lastbox
+ \ifhbox\tw@
+Z \message{Col \the\TY at count: Initial=\the\wd\tw@\space}%
+ \ifdim\wd\tw@>\tymax
+ \wd\tw@\tymax
+Z \message{> max\space}%
+Z \else
+Z \message{ \@spaces\space}%
+ \fi
+ \TY at width\dimen@
+Z \message{\the\dimen@\space}%
+ \advance\dimen@\wd\tw@
+Z \message{Final=\the\dimen@\space}%
+ \TY at width\xdef{\the\dimen@}%
+ \ifdim\dimen@<\tymin
+Z \message{< tymin}%
+ \global\advance\TY at linewidth-\dimen@
+ \expandafter\xdef\csname TY at F\the\TY at count\endcsname
+ {\the\dimen@}%
+ \else
+ \expandafter\ifx\csname TY at F\the\TY at count\endcsname\z@
+Z \message{***}%
+ \global\advance\TY at linewidth-\dimen@
+ \expandafter\xdef\csname TY at F\the\TY at count\endcsname
+ {\the\dimen@}%
+ \else
+Z \message{> tymin}%
+ \global\advance\TY at tablewidth\dimen@
+ \global\expandafter\let\csname TY at F\the\TY at count\endcsname
+ \maxdimen
+ \fi\fi
+ \advance\TY at count\m at ne
+ \repeat}%
+ \TY at checkmin
+ \TY at checkmin
+ \TY at checkmin
+ \TY at checkmin
+ \TY at count\z@
+ \let\TY at box\TY at box@v
+ \let\footnote\TY at footnote % restore footnotes
+ {\expandafter\TY at final\the\toks@\endTY at final}%
+ \count@\z@
+ \@tempswatrue
+ \@whilesw\if at tempswa\fi{%
+ \advance\count@\@ne
+ \expandafter\ifx\csname TY at SF\the\count@\endcsname\relax
+ \@tempswafalse
+ \else
+ \global\expandafter\let\csname TY at F\the\count@\expandafter\endcsname
+ \csname TY at SF\the\count@\endcsname
+ \global\expandafter\let\csname TY@\the\count@\expandafter\endcsname
+ \csname TY at S\the\count@\endcsname
+ \fi}%
+ \TY at linewidth\@ovxx
+ \TY at tablewidth\@ovyy
+ \ifnum0=`{\fi}}
+\def\TY at checkmin{%
+ \let\TY at checkmin\relax
+\ifdim\TY at tablewidth>\z@
+ \Gscale at div\TY at ratio\TY at linewidth\TY at tablewidth
+ \ifdim\TY at tablewidth <\TY at linewidth
+ \def\TY at ratio{1}%
+ \fi
+\else
+ \TY at warn{No suitable columns!}%
+ \def\TY at ratio{1}%
+\fi
+\count@\z@
+Z \message{^^JLine Width: \the\TY at linewidth,
+Z Natural Width: \the\TY at tablewidth,
+Z Ratio: \TY at ratio^^J}%
+\@tempdima\z@
+\loop
+\ifnum\count@<\TY at count
+\advance\count@\@ne
+ \ifdim\csname TY at F\the\count@\endcsname>\tymin
+ \dimen@\csname TY@\the\count@\endcsname
+ \dimen@\TY at ratio\dimen@
+ \ifdim\dimen@<\tymin
+Z \message{Column \the\count@\space ->}%
+ \global\expandafter\let\csname TY at F\the\count@\endcsname\tymin
+ \global\advance\TY at linewidth-\tymin
+ \global\advance\TY at tablewidth-\csname TY@\the\count@\endcsname
+ \let\TY at checkmin\TY@@checkmin
+ \else
+ \expandafter\xdef\csname TY at F\the\count@\endcsname{\the\dimen@}%
+ \advance\@tempdima\csname TY at F\the\count@\endcsname
+ \fi
+ \fi
+Z \dimen@\csname TY at F\the\count@\endcsname\message{\the\dimen@, }%
+\repeat
+Z \message{^^JTotal:\the\@tempdima^^J}%
+}
+\let\TY@@checkmin\TY at checkmin
+\newdimen\TY at linewidth
+\def\tyformat{\everypar{{\nobreak\hskip\z at skip}}}
+\newdimen\tymin
+\tymin=10pt
+\newdimen\tymax
+\tymax=2\textwidth
+\def\@testpach{\@chclass
+ \ifnum \@lastchclass=6 \@ne \@chnum \@ne \else
+ \ifnum \@lastchclass=7 5 \else
+ \ifnum \@lastchclass=8 \tw@ \else
+ \ifnum \@lastchclass=9 \thr@@
+ \else \z@
+ \ifnum \@lastchclass = 10 \else
+ \edef\@nextchar{\expandafter\string\@nextchar}%
+ \@chnum
+ \if \@nextchar c\z@ \else
+ \if \@nextchar l\@ne \else
+ \if \@nextchar r\tw@ \else
+ \if \@nextchar C7 \else
+ \if \@nextchar L8 \else
+ \if \@nextchar R9 \else
+ \if \@nextchar J10 \else
+ \z@ \@chclass
+ \if\@nextchar |\@ne \else
+ \if \@nextchar !6 \else
+ \if \@nextchar @7 \else
+ \if \@nextchar <8 \else
+ \if \@nextchar >9 \else
+ 10
+ \@chnum
+ \if \@nextchar m\thr@@\else
+ \if \@nextchar p4 \else
+ \if \@nextchar b5 \else
+ \z@ \@chclass \z@ \@preamerr \z@ \fi \fi \fi \fi\fi \fi \fi\fi \fi
+ \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi}
+\def\TY at classz{%
+ \@classx
+ \@tempcnta\count@
+ \ifx\TY at box\TY at box@v
+ \global\advance\TY at count\@ne
+ \fi
+ \let\centering c%
+ \let\raggedright\noindent
+ \let\raggedleft\indent
+ \let\arraybackslash\relax
+ \prepnext at tok
+ \ifnum\@chnum<4
+ \global\expandafter\let\csname TY at F\the\TY at count\endcsname\z@
+ \fi
+ \ifnum\@chnum=6
+ \global\expandafter\let\csname TY at F\the\TY at count\endcsname\z@
+ \fi
+ \@addtopreamble{%
+ \ifcase\@chnum
+ \hfil \d at llarbegin\insert at column\d at llarend \hfil \or
+ \kern\z@
+ \d at llarbegin \insert at column \d at llarend \hfil \or
+ \hfil\kern\z@ \d at llarbegin \insert at column \d at llarend \or
+ $\vcenter\@startpbox{\@nextchar}\insert at column \@endpbox $\or
+ \vtop \@startpbox{\@nextchar}\insert at column \@endpbox \or
+ \vbox \@startpbox{\@nextchar}\insert at column \@endpbox \or
+ \d at llarbegin \insert at column \d at llarend \or% dubious "s" case
+ \TY at box\centering\or
+ \TY at box\raggedright\or
+ \TY at box\raggedleft\or
+ \TY at box\relax
+ \fi}\prepnext at tok}
+\def\TY at box#1{%
+ \ifx\centering#1%
+ \hfil \d at llarbegin\insert at column\d at llarend \hfil \else
+ \ifx\raggedright#1%
+ \kern\z@%<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ \d at llarbegin \insert at column \d at llarend \hfil \else
+ \ifx\raggedleft#1%
+ \hfil\kern\z@ \d at llarbegin \insert at column \d at llarend \else
+ \ifx\relax#1%
+ \d at llarbegin \insert at column \d at llarend
+ \fi \fi \fi \fi}
+\def\TY at box@v#1{%
+ \vtop \@startpbox{\csname TY at F\the\TY at count\endcsname}%
+ #1\arraybackslash\tyformat
+ \insert at column\@endpbox}
+\newdimen\TY at tablewidth
+\def\Gscale at div#1#2#3{%
+ \setlength\dimen@{#3}%
+ \ifdim\dimen@=\z@
+ \PackageError{graphics}{Division by 0}\@eha
+ \dimen@#2%
+ \fi
+ \edef\@tempd{\the\dimen@}%
+ \setlength\dimen@{#2}%
+ \count at 65536\relax
+ \ifdim\dimen@<\z@
+ \dimen at -\dimen@
+ \count at -\count@
+ \fi
+ \loop
+ \ifdim\dimen@<8192\p@
+ \dimen@\tw@\dimen@
+ \divide\count@\tw@
+ \repeat
+ \dimen at ii=\@tempd\relax
+ \divide\dimen at ii\count@
+ \divide\dimen@\dimen at ii
+ \edef#1{\strip at pt\dimen@}}
+\long\def\TY at get@body#1\end
+ {\toks@\expandafter{\the\toks@#1}\TY at find@end}
+\def\TY at find@end#1{%
+ \def\@tempa{#1}%
+ \ifx\@tempa\TY@\def\@tempa{\end{#1}}\expandafter\@tempa
+ \else\toks@\expandafter
+ {\the\toks@\end{#1}}\expandafter\TY at get@body\fi}
+\def\TY at warn{%
+ \PackageWarning{tabulary}}
+\catcode`\Z=11
+\AtBeginDocument{
+\@ifpackageloaded{colortbl}{%
+\expandafter\def\expandafter\@mkpream\expandafter#\expandafter1%
+ \expandafter{%
+ \expandafter\let\expandafter\CT at setup\expandafter\relax
+ \expandafter\let\expandafter\CT at color\expandafter\relax
+ \expandafter\let\expandafter\CT at do@color\expandafter\relax
+ \expandafter\let\expandafter\color\expandafter\relax
+ \expandafter\let\expandafter\CT at column@color\expandafter\relax
+ \expandafter\let\expandafter\CT at row@color\expandafter\relax
+ \@mkpream{#1}}
+\let\TY@@mkpream\@mkpream
+\def\TY at classz{%
+ \@classx
+ \@tempcnta\count@
+ \ifx\TY at box\TY at box@v
+ \global\advance\TY at count\@ne
+ \fi
+ \let\centering c%
+ \let\raggedright\noindent
+ \let\raggedleft\indent
+ \let\arraybackslash\relax
+ \prepnext at tok
+\expandafter\CT at extract\the\toks\@tempcnta\columncolor!\@nil
+ \ifnum\@chnum<4
+ \global\expandafter\let\csname TY at F\the\TY at count\endcsname\z@
+ \fi
+ \ifnum\@chnum=6
+ \global\expandafter\let\csname TY at F\the\TY at count\endcsname\z@
+ \fi
+ \@addtopreamble{%
+ \setbox\z@\hbox\bgroup\bgroup
+ \ifcase\@chnum
+ \hskip\stretch{.5}\kern\z@
+ \d at llarbegin\insert at column\d at llarend\hskip\stretch{.5}\or
+ \kern\z@%<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ \d at llarbegin \insert at column \d at llarend \hfill \or
+ \hfill\kern\z@ \d at llarbegin \insert at column \d at llarend \or
+ $\vcenter\@startpbox{\@nextchar}\insert at column \@endpbox $\or
+ \vtop \@startpbox{\@nextchar}\insert at column \@endpbox \or
+ \vbox \@startpbox{\@nextchar}\insert at column \@endpbox \or
+ \d at llarbegin \insert at column \d at llarend \or% dubious s case
+ \TY at box\centering\or
+ \TY at box\raggedright\or
+ \TY at box\raggedleft\or
+ \TY at box\relax
+ \fi
+ \egroup\egroup
+\begingroup
+ \CT at setup
+ \CT at column@color
+ \CT at row@color
+ \CT at do@color
+\endgroup
+ \@tempdima\ht\z@
+ \advance\@tempdima\minrowclearance
+ \vrule\@height\@tempdima\@width\z@
+\unhbox\z@
+}\prepnext at tok}%
+ \def\TY at arrayrule{%
+ \TY at subwidth\arrayrulewidth
+ \@addtopreamble{{\CT at arc@\vline}}}%
+ \def\TY at classvi{\ifcase \@lastchclass
+ \@acol \or
+ \TY at subwidth\doublerulesep
+ \ifx\CT at drsc@\relax
+ \@addtopreamble{\hskip\doublerulesep}%
+ \else
+ \@addtopreamble{{\CT at drsc@\vrule\@width\doublerulesep}}%
+ \fi\or
+ \@acol \or
+ \@classvii
+ \fi}%
+}{%
+\let\CT at start\relax
+}
+}
+{\uccode`\*=`\ %
+\uppercase{\gdef\TX at verb{%
+ \leavevmode\null\TX at vwarn
+ {\ifnum0=`}\fi\ttfamily\let\\\ignorespaces
+ \@ifstar{\let~*\TX at vb}{\TX at vb}}}}
+\def\TX at vb#1{\def\@tempa##1#1{\toks@{##1}\edef\@tempa{\the\toks@}%
+ \expandafter\TX at v\meaning\@tempa\\ \\\ifnum0=`{\fi}}\@tempa!}
+\def\TX at v#1!{\afterassignment\TX at vfirst\let\@tempa= }
+\begingroup
+\catcode`\*=\catcode`\#
+\catcode`\#=12
+\gdef\TX at vfirst{%
+ \if\@tempa#%
+ \def\@tempb{\TX at v@#}%
+ \else
+ \let\@tempb\TX at v@
+ \if\@tempa\space~\else\@tempa\fi
+ \fi
+ \@tempb}
+\gdef\TX at v@*1 *2{%
+ \TX at v@hash*1##\relax\if*2\\\else~\expandafter\TX at v@\fi*2}
+\gdef\TX at v@hash*1##*2{*1\ifx*2\relax\else#\expandafter\TX at v@hash\fi*2}
+\endgroup
+\def\TX at vwarn{%
+ \@warning{\noexpand\verb may be unreliable inside tabularx/y}%
+ \global\let\TX at vwarn\@empty}
+\endinput
+%%
+%% End of file `tabulary.sty'.
diff --git a/sphinx/themes/agogo/layout.html b/sphinx/themes/agogo/layout.html
new file mode 100644
index 0000000..c6960fb
--- /dev/null
+++ b/sphinx/themes/agogo/layout.html
@@ -0,0 +1,92 @@
+{#
+ agogo/layout.html
+ ~~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the agogo theme, originally written
+ by Andi Albrecht.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "basic/layout.html" %}
+
+{% block header %}
+ <div class="header-wrapper">
+ <div class="header">
+ {%- if logo %}
+ <p class="logo"><a href="{{ pathto(master_doc) }}">
+ <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
+ </a></p>
+ {%- endif %}
+ {%- block headertitle %}
+ <div class="headertitle"><a
+ href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a></div>
+ {%- endblock %}
+ <div class="rel">
+ {%- for rellink in rellinks|reverse %}
+ <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
+ {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
+ {%- if not loop.last %}{{ reldelim2 }}{% endif %}
+ {%- endfor %}
+ </div>
+ </div>
+ </div>
+{% endblock %}
+
+{% block content %}
+ <div class="content-wrapper">
+ <div class="content">
+ <div class="document">
+ {%- block document %}
+ {{ super() }}
+ {%- endblock %}
+ </div>
+ <div class="sidebar">
+ {%- block sidebartoc %}
+ <h3>{{ _('Table Of Contents') }}</h3>
+ {{ toctree() }}
+ {%- endblock %}
+ {%- block sidebarsearch %}
+ <h3 style="margin-top: 1.5em;">{{ _('Search') }}</h3>
+ <form class="search" action="{{ pathto('search') }}" method="get">
+ <input type="text" name="q" />
+ <input type="submit" value="{{ _('Go') }}" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+ <p class="searchtip" style="font-size: 90%">
+ {{ _('Enter search terms or a module, class or function name.') }}
+ </p>
+ {%- endblock %}
+ </div>
+ <div class="clearer"></div>
+ </div>
+ </div>
+{% endblock %}
+
+{% block footer %}
+ <div class="footer-wrapper">
+ <div class="footer">
+ <div class="left">
+ {%- for rellink in rellinks|reverse %}
+ <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
+ {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
+ {%- if not loop.last %}{{ reldelim2 }}{% endif %}
+ {%- endfor %}
+ {%- if show_source and has_source and sourcename %}
+ <br/>
+ <a href="{{ pathto('_sources/' + sourcename, true)|e }}"
+ rel="nofollow">{{ _('Show Source') }}</a>
+ {%- endif %}
+ </div>
+
+ <div class="right">
+ {{ super() }}
+ </div>
+ <div class="clearer"></div>
+ </div>
+ </div>
+{% endblock %}
+
+{% block relbar1 %}{% endblock %}
+{% block relbar2 %}{% endblock %}
diff --git a/sphinx/themes/agogo/static/agogo.css_t b/sphinx/themes/agogo/static/agogo.css_t
new file mode 100644
index 0000000..1ec2147
--- /dev/null
+++ b/sphinx/themes/agogo/static/agogo.css_t
@@ -0,0 +1,464 @@
+/*
+ * agogo.css_t
+ * ~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- agogo theme.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+* {
+ margin: 0px;
+ padding: 0px;
+}
+
+body {
+ font-family: {{ theme_bodyfont }};
+ line-height: 1.4em;
+ color: black;
+ background-color: {{ theme_bgcolor }};
+}
+
+
+/* Page layout */
+
+div.header, div.content, div.footer {
+ width: {{ theme_pagewidth }};
+ margin-left: auto;
+ margin-right: auto;
+}
+
+div.header-wrapper {
+ background: {{ theme_headerbg }};
+ border-bottom: 3px solid #2e3436;
+}
+
+
+/* Default body styles */
+a {
+ color: {{ theme_linkcolor }};
+}
+
+div.bodywrapper a, div.footer a {
+ text-decoration: underline;
+}
+
+.clearer {
+ clear: both;
+}
+
+.left {
+ float: left;
+}
+
+.right {
+ float: right;
+}
+
+.line-block {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.line-block .line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 1.5em;
+}
+
+h1, h2, h3, h4 {
+ font-family: {{ theme_headerfont }};
+ font-weight: normal;
+ color: {{ theme_headercolor2 }};
+ margin-bottom: .8em;
+}
+
+h1 {
+ color: {{ theme_headercolor1 }};
+}
+
+h2 {
+ padding-bottom: .5em;
+ border-bottom: 1px solid {{ theme_headercolor2 }};
+}
+
+a.headerlink {
+ visibility: hidden;
+ color: #dddddd;
+ padding-left: .3em;
+}
+
+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 {
+ visibility: visible;
+}
+
+img {
+ border: 0;
+}
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 2px 7px 1px 7px;
+ border-left: 0.2em solid black;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+}
+
+dt:target, .highlighted {
+ background-color: #fbe54e;
+}
+
+/* Header */
+
+div.header {
+ padding-top: 10px;
+ padding-bottom: 10px;
+}
+
+div.header .headertitle {
+ font-family: {{ theme_headerfont }};
+ font-weight: normal;
+ font-size: 180%;
+ letter-spacing: .08em;
+ margin-bottom: .8em;
+}
+
+div.header .headertitle a {
+ color: white;
+}
+
+div.header div.rel {
+ margin-top: 1em;
+}
+
+div.header div.rel a {
+ color: {{ theme_headerlinkcolor }};
+ letter-spacing: .1em;
+ text-transform: uppercase;
+}
+
+p.logo {
+ float: right;
+}
+
+img.logo {
+ border: 0;
+}
+
+
+/* Content */
+div.content-wrapper {
+ background-color: white;
+ padding-top: 20px;
+ padding-bottom: 20px;
+}
+
+div.document {
+ width: {{ theme_documentwidth }};
+ float: left;
+}
+
+div.body {
+ padding-right: 2em;
+ text-align: {{ theme_textalign }};
+}
+
+div.document h1 {
+ line-height: 120%;
+}
+
+div.document ul {
+ margin: 1.5em;
+ list-style-type: square;
+}
+
+div.document dd {
+ margin-left: 1.2em;
+ margin-top: .4em;
+ margin-bottom: 1em;
+}
+
+div.document .section {
+ margin-top: 1.7em;
+}
+div.document .section:first-child {
+ margin-top: 0px;
+}
+
+div.document div.highlight {
+ padding: 3px;
+ background-color: #eeeeec;
+ border-top: 2px solid #dddddd;
+ border-bottom: 2px solid #dddddd;
+ margin-top: .8em;
+ margin-bottom: .8em;
+}
+
+div.document h2 {
+ margin-top: .7em;
+}
+
+div.document p {
+ margin-bottom: .5em;
+}
+
+div.document li.toctree-l1 {
+ margin-bottom: 1em;
+}
+
+div.document .descname {
+ font-weight: bold;
+}
+
+div.document .docutils.literal {
+ background-color: #eeeeec;
+ padding: 1px;
+}
+
+div.document .docutils.xref.literal {
+ background-color: transparent;
+ padding: 0px;
+}
+
+div.document blockquote {
+ margin: 1em;
+}
+
+div.document ol {
+ margin: 1.5em;
+}
+
+
+/* Sidebar */
+
+div.sidebar {
+ width: {{ theme_sidebarwidth }};
+ float: right;
+ font-size: .9em;
+}
+
+div.sidebar a, div.header a {
+ text-decoration: none;
+}
+
+div.sidebar a:hover, div.header a:hover {
+ text-decoration: underline;
+}
+
+div.sidebar h3 {
+ color: #2e3436;
+ text-transform: uppercase;
+ font-size: 130%;
+ letter-spacing: .1em;
+}
+
+div.sidebar ul {
+ list-style-type: none;
+}
+
+div.sidebar li.toctree-l1 a {
+ display: block;
+ padding: 1px;
+ border: 1px solid #dddddd;
+ background-color: #eeeeec;
+ margin-bottom: .4em;
+ padding-left: 3px;
+ color: #2e3436;
+}
+
+div.sidebar li.toctree-l2 a {
+ background-color: transparent;
+ border: none;
+ margin-left: 1em;
+ border-bottom: 1px solid #dddddd;
+}
+
+div.sidebar li.toctree-l3 a {
+ background-color: transparent;
+ border: none;
+ margin-left: 2em;
+ border-bottom: 1px solid #dddddd;
+}
+
+div.sidebar li.toctree-l2:last-child a {
+ border-bottom: none;
+}
+
+div.sidebar li.toctree-l1.current a {
+ border-right: 5px solid {{ theme_headerlinkcolor }};
+}
+
+div.sidebar li.toctree-l1.current li.toctree-l2 a {
+ border-right: none;
+}
+
+div.sidebar input[type="text"] {
+ width: 170px;
+}
+
+div.sidebar input[type="submit"] {
+ width: 30px;
+}
+
+
+/* Footer */
+
+div.footer-wrapper {
+ background: {{ theme_footerbg }};
+ border-top: 4px solid #babdb6;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ min-height: 80px;
+}
+
+div.footer, div.footer a {
+ color: #888a85;
+}
+
+div.footer .right {
+ text-align: right;
+}
+
+div.footer .left {
+ text-transform: uppercase;
+}
+
+
+/* Styles copied from basic theme */
+
+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;
+}
+
+/* -- 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%;
+}
+
+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 td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+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;
+}
+
+/* -- viewcode extension ---------------------------------------------------- */
+
+.viewcode-link {
+ float: right;
+}
+
+.viewcode-back {
+ float: right;
+ font-family:: {{ theme_bodyfont }};
+}
+
+div.viewcode-block:target {
+ margin: -1px -3px;
+ padding: 0 3px;
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+}
diff --git a/sphinx/themes/agogo/static/bgfooter.png b/sphinx/themes/agogo/static/bgfooter.png
new file mode 100644
index 0000000..9ce5bdd
Binary files /dev/null and b/sphinx/themes/agogo/static/bgfooter.png differ
diff --git a/sphinx/themes/agogo/static/bgtop.png b/sphinx/themes/agogo/static/bgtop.png
new file mode 100644
index 0000000..a0d4709
Binary files /dev/null and b/sphinx/themes/agogo/static/bgtop.png differ
diff --git a/sphinx/themes/agogo/theme.conf b/sphinx/themes/agogo/theme.conf
new file mode 100644
index 0000000..3052aca
--- /dev/null
+++ b/sphinx/themes/agogo/theme.conf
@@ -0,0 +1,19 @@
+[theme]
+inherit = basic
+stylesheet = agogo.css
+pygments_style = tango
+
+[options]
+bodyfont = "Verdana", Arial, sans-serif
+headerfont = "Georgia", "Times New Roman", serif
+pagewidth = 70em
+documentwidth = 50em
+sidebarwidth = 20em
+bgcolor = #eeeeec
+headerbg = #555573 url(bgtop.png) top left repeat-x
+footerbg = url(bgfooter.png) top left repeat-x
+linkcolor = #ce5c00
+headercolor1 = #204a87
+headercolor2 = #3465a4
+headerlinkcolor = #fcaf3e
+textalign = justify
\ No newline at end of file
diff --git a/sphinx/themes/basic/changes/frameset.html b/sphinx/themes/basic/changes/frameset.html
new file mode 100644
index 0000000..9d9af9e
--- /dev/null
+++ b/sphinx/themes/basic/changes/frameset.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
+ "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+ <head>
+ <title>{% trans version=version|e, docstitle=docstitle|e %}Changes in Version {{ version }} — {{ docstitle }}{% endtrans %}</title>
+ </head>
+ <frameset cols="45%,*">
+ <frame name="main" src="changes.html">
+ <frame name="src" src="about:blank">
+ </frameset>
+</html>
diff --git a/sphinx/themes/basic/changes/rstsource.html b/sphinx/themes/basic/changes/rstsource.html
new file mode 100644
index 0000000..abd12c1
--- /dev/null
+++ b/sphinx/themes/basic/changes/rstsource.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>{% trans filename=filename, docstitle=docstitle|e %}{{ filename }} — {{ docstitle }}{% endtrans %}</title>
+ <style type="text/css">
+ .hl { background-color: yellow }
+ </style>
+ </head>
+ <body style="font-size: 90%">
+ <pre>
+ {{ text }}
+ </pre>
+ </body>
+</html>
diff --git a/sphinx/themes/basic/changes/versionchanges.html b/sphinx/themes/basic/changes/versionchanges.html
new file mode 100644
index 0000000..09651bf
--- /dev/null
+++ b/sphinx/themes/basic/changes/versionchanges.html
@@ -0,0 +1,33 @@
+{% macro entries(changes) %}
+<ul>{% for entry, docname, lineno in changes %}
+<li><a href="rst/{{ docname }}.html#L{{ lineno-10 }}" target="src">{{ entry }}</a></li>
+{% endfor %}</ul>
+{% endmacro -%}
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <link rel="stylesheet" href="default.css">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>{% trans version=version|e, docstitle=docstitle|e %}Changes in Version {{ version }} — {{ docstitle }}{% endtrans %}</title>
+ </head>
+ <body>
+ <div class="document">
+ <div class="body">
+ <h1>{% trans version=version|e %}Automatically generated list of changes in version {{ version }}{% endtrans %}</h1>
+ <h2>{{ _('Library changes') }}</h2>
+ {% for modname, changes in libchanges %}
+ <h4>{{ modname }}</h4>
+ {{ entries(changes) }}
+ {% endfor %}
+ <h2>{{ _('C API changes') }}</h2>
+ {{ entries(apichanges) }}
+ <h2>{{ _('Other changes') }}</h2>
+ {% for (fn, title), changes in otherchanges %}
+ <h4>{{ title }} <span style="font-size: 50%">({{ fn }})</span></h4>
+ {{ entries(changes) }}
+ {% endfor %}
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/sphinx/themes/basic/defindex.html b/sphinx/themes/basic/defindex.html
new file mode 100644
index 0000000..9316cfd
--- /dev/null
+++ b/sphinx/themes/basic/defindex.html
@@ -0,0 +1,35 @@
+{#
+ basic/defindex.html
+ ~~~~~~~~~~~~~~~~~~~
+
+ Default template for the "index" page.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "layout.html" %}
+{% set title = _('Overview') %}
+{% block body %}
+ <h1>{{ docstitle|e }}</h1>
+ <p>
+ {{ _('Welcome! This is') }}
+ {% block description %}{{ _('the documentation for') }} {{ project|e }}
+ {{ release|e }}{% if last_updated %}, {{ _('last updated') }} {{ last_updated|e }}{% endif %}{% endblock %}.
+ </p>
+ {% block tables %}
+ <p><strong>{{ _('Indices and tables:') }}</strong></p>
+ <table class="contentstable" align="center"><tr>
+ <td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">{{ _('Complete Table of Contents') }}</a><br>
+ <span class="linkdescr">{{ _('lists all sections and subsections') }}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">{{ _('Search Page') }}</a><br>
+ <span class="linkdescr">{{ _('search this documentation') }}</span></p>
+ </td><td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("modindex") }}">{{ _('Global Module Index') }}</a><br>
+ <span class="linkdescr">{{ _('quick access to all modules') }}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">{{ _('General Index') }}</a><br>
+ <span class="linkdescr">{{ _('all functions, classes, terms') }}</span></p>
+ </td></tr>
+ </table>
+ {% endblock %}
+{% endblock %}
diff --git a/sphinx/themes/basic/domainindex.html b/sphinx/themes/basic/domainindex.html
new file mode 100644
index 0000000..ac5aed9
--- /dev/null
+++ b/sphinx/themes/basic/domainindex.html
@@ -0,0 +1,56 @@
+{#
+ basic/domainindex.html
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Template for domain indices (module index, ...).
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "layout.html" %}
+{% set title = indextitle %}
+{% block extrahead %}
+{{ super() }}
+{% if not embedded and collapse_index %}
+ <script type="text/javascript">
+ DOCUMENTATION_OPTIONS.COLLAPSE_INDEX = true;
+ </script>
+{% endif %}
+{% endblock %}
+{% block body %}
+
+ {%- set groupid = idgen() %}
+
+ <h1>{{ indextitle }}</h1>
+
+ <div class="modindex-jumpbox">
+ {%- for (letter, entries) in content %}
+ <a href="#cap-{{ letter }}"><strong>{{ letter }}</strong></a>
+ {%- if not loop.last %} | {% endif %}
+ {%- endfor %}
+ </div>
+
+ <table class="indextable modindextable" cellspacing="0" cellpadding="2">
+ {%- for letter, entries in content %}
+ <tr class="pcap"><td></td><td> </td><td></td></tr>
+ <tr class="cap" id="cap-{{ letter }}"><td></td><td>
+ <strong>{{ letter }}</strong></td><td></td></tr>
+ {%- for (name, grouptype, page, anchor, extra, qualifier, description)
+ in entries %}
+ <tr{% if grouptype == 2 %} class="cg-{{ groupid.current() }}"{% endif %}>
+ <td>{% if grouptype == 1 -%}
+ <img src="{{ pathto('_static/minus.png', 1) }}" class="toggler"
+ id="toggle-{{ groupid.next() }}" style="display: none" alt="-" />
+ {%- endif %}</td>
+ <td>{% if grouptype == 2 %} {% endif %}
+ {% if page %}<a href="{{ pathto(page) }}#{{ anchor }}">{% endif -%}
+ <tt class="xref">{{ name|e }}</tt>
+ {%- if page %}</a>{% endif %}
+ {%- if extra %} <em>({{ extra|e }})</em>{% endif -%}
+ </td><td>{% if qualifier %}<strong>{{ qualifier|e }}:</strong>{% endif %}
+ <em>{{ description|e }}</em></td></tr>
+ {%- endfor %}
+ {%- endfor %}
+ </table>
+
+{% endblock %}
diff --git a/sphinx/themes/basic/genindex-single.html b/sphinx/themes/basic/genindex-single.html
new file mode 100644
index 0000000..ec57a7b
--- /dev/null
+++ b/sphinx/themes/basic/genindex-single.html
@@ -0,0 +1,65 @@
+{#
+ basic/genindex-single.html
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Template for a "single" page of a split index.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{% macro indexentries(firstname, links) %}
+ <dt>
+ {%- if links -%}
+ <a href="{{ links[0][1] }}">
+ {%- if links[0][0] %}<strong>{% endif -%}
+ {{ firstname|e }}
+ {%- if links[0][0] %}</strong>{% endif -%}
+ </a>
+
+ {%- for ismain, link in links[1:] -%}
+ , <a href="{{ link }}">{% if ismain %}<strong>{% endif -%}
+ [{{ loop.index }}]
+ {%- if ismain %}</strong>{% endif -%}
+ </a>
+ {%- endfor %}
+ {%- else %}
+ {{ firstname|e }}
+ {%- endif %}
+ </dt>
+{% endmacro %}
+
+{%- extends "layout.html" %}
+{% set title = _('Index') %}
+{% block body %}
+
+<h1 id="index">{% trans key=key %}Index – {{ key }}{% endtrans %}</h1>
+
+<table style="width: 100%" class="indextable"><tr>
+ {%- for column in entries|slice(2) if column %}
+ <td style="width: 33%" valign="top"><dl>
+ {%- for entryname, (links, subitems) in column %}
+ {{ indexentries(entryname, links) }}
+ {%- if subitems %}
+ <dd><dl>
+ {%- for subentryname, subentrylinks in subitems %}
+ {{ indexentries(subentryname, subentrylinks) }}
+ {%- endfor %}
+ </dl></dd>
+ {%- endif -%}
+ {%- endfor %}
+ </dl></td>
+ {%- endfor %}
+</tr></table>
+
+{% endblock %}
+
+{% block sidebarrel %}
+ <h4>{{ _('Index') }}</h4>
+ <p>{% for key, dummy in genindexentries -%}
+ <a href="{{ pathto('genindex-' + key) }}"><strong>{{ key }}</strong></a>
+ {% if not loop.last %}| {% endif %}
+ {%- endfor %}</p>
+
+ <p><a href="{{ pathto('genindex-all') }}"><strong>{{ _('Full index on one page') }}</strong></a></p>
+ {{ super() }}
+{% endblock %}
diff --git a/sphinx/themes/basic/genindex-split.html b/sphinx/themes/basic/genindex-split.html
new file mode 100644
index 0000000..aca8647
--- /dev/null
+++ b/sphinx/themes/basic/genindex-split.html
@@ -0,0 +1,41 @@
+{#
+ basic/genindex-split.html
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Template for a "split" index overview page.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "layout.html" %}
+{% set title = _('Index') %}
+{% block body %}
+
+ <h1 id="index">{{ _('Index') }}</h1>
+
+ <p>{{ _('Index pages by letter') }}:</p>
+
+ <div class="genindex-jumpbox">
+ <p>{% for key, dummy in genindexentries -%}
+ <a href="{{ pathto('genindex-' + key) }}"><strong>{{ key }}</strong></a>
+ {% if not loop.last %}| {% endif %}
+ {%- endfor %}</p>
+
+ <p><a href="{{ pathto('genindex-all') }}"><strong>{{ _('Full index on one page') }}</strong>
+ ({{ _('can be huge') }})</a></p>
+ </div>
+
+{% endblock %}
+
+{% block sidebarrel %}
+{% if split_index %}
+ <h4>Index</h4>
+ <p>{% for key, dummy in genindexentries -%}
+ <a href="{{ pathto('genindex-' + key) }}"><strong>{{ key }}</strong></a>
+ {% if not loop.last %}| {% endif %}
+ {%- endfor %}</p>
+
+ <p><a href="{{ pathto('genindex-all') }}"><strong>{{ _('Full index on one page') }}</strong></a></p>
+{% endif %}
+ {{ super() }}
+{% endblock %}
diff --git a/sphinx/themes/basic/genindex.html b/sphinx/themes/basic/genindex.html
new file mode 100644
index 0000000..836d784
--- /dev/null
+++ b/sphinx/themes/basic/genindex.html
@@ -0,0 +1,77 @@
+{#
+ basic/genindex.html
+ ~~~~~~~~~~~~~~~~~~~
+
+ Template for an "all-in-one" index.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{% macro indexentries(firstname, links) %}
+ <dt>
+ {%- if links -%}
+ <a href="{{ links[0][1] }}">
+ {%- if links[0][0] %}<strong>{% endif -%}
+ {{ firstname|e }}
+ {%- if links[0][0] %}</strong>{% endif -%}
+ </a>
+
+ {%- for ismain, link in links[1:] -%}
+ , <a href="{{ link }}">{% if ismain %}<strong>{% endif -%}
+ [{{ loop.index }}]
+ {%- if ismain %}</strong>{% endif -%}
+ </a>
+ {%- endfor %}
+ {%- else %}
+ {{ firstname|e }}
+ {%- endif %}
+ </dt>
+{% endmacro %}
+
+{%- extends "layout.html" %}
+{% set title = _('Index') %}
+{% block body %}
+
+<h1 id="index">{{ _('Index') }}</h1>
+
+<div class="genindex-jumpbox">
+ {% for key, dummy in genindexentries -%}
+ <a href="#{{ key }}"><strong>{{ key }}</strong></a>
+ {% if not loop.last %}| {% endif %}
+ {%- endfor %}
+</div>
+
+{%- for key, entries in genindexentries %}
+<h2 id="{{ key }}">{{ key }}</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+ {%- for column in entries|slice(2) if column %}
+ <td style="width: 33%" valign="top"><dl>
+ {%- for entryname, (links, subitems) in column %}
+ {{ indexentries(entryname, links) }}
+ {%- if subitems %}
+ <dd><dl>
+ {%- for subentryname, subentrylinks in subitems %}
+ {{ indexentries(subentryname, subentrylinks) }}
+ {%- endfor %}
+ </dl></dd>
+ {%- endif -%}
+ {%- endfor %}
+ </dl></td>
+ {%- endfor %}
+</tr></table>
+{% endfor %}
+
+{% endblock %}
+
+{% block sidebarrel %}
+{% if split_index %}
+ <h4>{{ _('Index') }}</h4>
+ <p>{% for key, dummy in genindexentries -%}
+ <a href="{{ pathto('genindex-' + key) }}"><strong>{{ key }}</strong></a>
+ {% if not loop.last %}| {% endif %}
+ {%- endfor %}</p>
+
+ <p><a href="{{ pathto('genindex-all') }}"><strong>{{ _('Full index on one page') }}</strong></a></p>
+{% endif %}
+ {{ super() }}
+{% endblock %}
diff --git a/sphinx/themes/basic/globaltoc.html b/sphinx/themes/basic/globaltoc.html
new file mode 100644
index 0000000..60ed28a
--- /dev/null
+++ b/sphinx/themes/basic/globaltoc.html
@@ -0,0 +1,11 @@
+{#
+ basic/globaltoc.html
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx sidebar template: global table of contents.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
+{{ toctree() }}
diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html
new file mode 100644
index 0000000..f01c3aa
--- /dev/null
+++ b/sphinx/themes/basic/layout.html
@@ -0,0 +1,203 @@
+{#
+ basic/layout.html
+ ~~~~~~~~~~~~~~~~~
+
+ Master layout template for Sphinx themes.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- block doctype -%}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+{%- endblock %}
+{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %}
+{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
+{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
+ (sidebars != []) %}
+{%- set url_root = pathto('', 1) %}
+{# XXX necessary? #}
+{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
+{%- if not embedded and docstitle %}
+ {%- set titlesuffix = " — "|safe + docstitle|e %}
+{%- else %}
+ {%- set titlesuffix = "" %}
+{%- endif %}
+
+{%- macro relbar() %}
+ <div class="related">
+ <h3>{{ _('Navigation') }}</h3>
+ <ul>
+ {%- for rellink in rellinks %}
+ <li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
+ <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
+ {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
+ {%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
+ {%- endfor %}
+ {%- block rootrellink %}
+ <li><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}</li>
+ {%- endblock %}
+ {%- for parent in parents %}
+ <li><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
+ {%- endfor %}
+ {%- block relbaritems %} {% endblock %}
+ </ul>
+ </div>
+{%- endmacro %}
+
+{%- macro sidebar() %}
+ {%- if render_sidebar %}
+ <div class="sphinxsidebar">
+ <div class="sphinxsidebarwrapper">
+ {%- block sidebarlogo %}
+ {%- if logo %}
+ <p class="logo"><a href="{{ pathto(master_doc) }}">
+ <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
+ </a></p>
+ {%- endif %}
+ {%- endblock %}
+ {%- if sidebars != None %}
+ {#- new style sidebar: explicitly include/exclude templates #}
+ {%- for sidebartemplate in sidebars %}
+ {%- include sidebartemplate %}
+ {%- endfor %}
+ {%- else %}
+ {#- old style sidebars: using blocks -- should be deprecated #}
+ {%- block sidebartoc %}
+ {%- include "localtoc.html" %}
+ {%- endblock %}
+ {%- block sidebarrel %}
+ {%- include "relations.html" %}
+ {%- endblock %}
+ {%- block sidebarsourcelink %}
+ {%- include "sourcelink.html" %}
+ {%- endblock %}
+ {%- if customsidebar %}
+ {%- include customsidebar %}
+ {%- endif %}
+ {%- block sidebarsearch %}
+ {%- include "searchbox.html" %}
+ {%- endblock %}
+ {%- endif %}
+ </div>
+ </div>
+ {%- endif %}
+{%- endmacro %}
+
+{%- macro script() %}
+ <script type="text/javascript">
+ var DOCUMENTATION_OPTIONS = {
+ URL_ROOT: '{{ url_root }}',
+ VERSION: '{{ release|e }}',
+ COLLAPSE_INDEX: false,
+ FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
+ HAS_SOURCE: {{ has_source|lower }}
+ };
+ </script>
+ {%- for scriptfile in script_files %}
+ <script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
+ {%- endfor %}
+{%- endmacro %}
+
+{%- macro css() %}
+ <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
+ <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
+ {%- for cssfile in css_files %}
+ <link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
+ {%- endfor %}
+{%- endmacro %}
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" />
+ {{ metatags }}
+ {%- block htmltitle %}
+ <title>{{ title|striptags|e }}{{ titlesuffix }}</title>
+ {%- endblock %}
+ {{ css() }}
+ {%- if not embedded %}
+ {{ script() }}
+ {%- if use_opensearch %}
+ <link rel="search" type="application/opensearchdescription+xml"
+ title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
+ href="{{ pathto('_static/opensearch.xml', 1) }}"/>
+ {%- endif %}
+ {%- if favicon %}
+ <link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
+ {%- endif %}
+ {%- endif %}
+{%- block linktags %}
+ {%- if hasdoc('about') %}
+ <link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
+ {%- endif %}
+ {%- if hasdoc('genindex') %}
+ <link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
+ {%- endif %}
+ {%- if hasdoc('search') %}
+ <link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
+ {%- endif %}
+ {%- if hasdoc('copyright') %}
+ <link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
+ {%- endif %}
+ <link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
+ {%- if parents %}
+ <link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
+ {%- endif %}
+ {%- if next %}
+ <link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
+ {%- endif %}
+ {%- if prev %}
+ <link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
+ {%- endif %}
+{%- endblock %}
+{%- block extrahead %} {% endblock %}
+ </head>
+ <body>
+{%- block header %}{% endblock %}
+
+{%- block relbar1 %}{{ relbar() }}{% endblock %}
+
+{%- block content %}
+ {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}
+
+ <div class="document">
+ {%- block document %}
+ <div class="documentwrapper">
+ {%- if render_sidebar %}
+ <div class="bodywrapper">
+ {%- endif %}
+ <div class="body">
+ {% block body %} {% endblock %}
+ </div>
+ {%- if render_sidebar %}
+ </div>
+ {%- endif %}
+ </div>
+ {%- endblock %}
+
+ {%- block sidebar2 %}{{ sidebar() }}{% endblock %}
+ <div class="clearer"></div>
+ </div>
+{%- endblock %}
+
+{%- block relbar2 %}{{ relbar() }}{% endblock %}
+
+{%- block footer %}
+ <div class="footer">
+ {%- if show_copyright %}
+ {%- if hasdoc('copyright') %}
+ {% trans path=pathto('copyright'), copyright=copyright|e %}© <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
+ {%- else %}
+ {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
+ {%- endif %}
+ {%- endif %}
+ {%- if last_updated %}
+ {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
+ {%- endif %}
+ {%- if show_sphinx %}
+ {% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
+ {%- endif %}
+ </div>
+{%- endblock %}
+ </body>
+</html>
diff --git a/sphinx/themes/basic/localtoc.html b/sphinx/themes/basic/localtoc.html
new file mode 100644
index 0000000..70afb6a
--- /dev/null
+++ b/sphinx/themes/basic/localtoc.html
@@ -0,0 +1,13 @@
+{#
+ basic/localtoc.html
+ ~~~~~~~~~~~~~~~~~~~
+
+ Sphinx sidebar template: local table of contents.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- if display_toc %}
+ <h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
+ {{ toc }}
+{%- endif %}
diff --git a/sphinx/themes/basic/opensearch.xml b/sphinx/themes/basic/opensearch.xml
new file mode 100644
index 0000000..03875be
--- /dev/null
+++ b/sphinx/themes/basic/opensearch.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>{{ project|e }}</ShortName>
+ <Description>{% trans docstitle=docstitle|e %}Search {{ docstitle }}{% endtrans %}</Description>
+ <InputEncoding>utf-8</InputEncoding>
+ <Url type="text/html" method="get"
+ template="{{ use_opensearch }}/{{ pathto('search') }}?q={searchTerms}&check_keywords=yes&area=default"/>
+ <LongName>{{ docstitle|e }}</LongName>
+{% block extra %} {# Put e.g. an <Image> element here. #} {% endblock %}
+</OpenSearchDescription>
diff --git a/sphinx/themes/basic/page.html b/sphinx/themes/basic/page.html
new file mode 100644
index 0000000..b4544a2
--- /dev/null
+++ b/sphinx/themes/basic/page.html
@@ -0,0 +1,13 @@
+{#
+ basic/page.html
+ ~~~~~~~~~~~~~~~
+
+ Master template for simple pages.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "layout.html" %}
+{% block body %}
+ {{ body }}
+{% endblock %}
diff --git a/sphinx/themes/basic/relations.html b/sphinx/themes/basic/relations.html
new file mode 100644
index 0000000..c82bbee
--- /dev/null
+++ b/sphinx/themes/basic/relations.html
@@ -0,0 +1,19 @@
+{#
+ basic/relations.html
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx sidebar template: relation links.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- if prev %}
+ <h4>{{ _('Previous topic') }}</h4>
+ <p class="topless"><a href="{{ prev.link|e }}"
+ title="{{ _('previous chapter') }}">{{ prev.title }}</a></p>
+{%- endif %}
+{%- if next %}
+ <h4>{{ _('Next topic') }}</h4>
+ <p class="topless"><a href="{{ next.link|e }}"
+ title="{{ _('next chapter') }}">{{ next.title }}</a></p>
+{%- endif %}
diff --git a/sphinx/themes/basic/search.html b/sphinx/themes/basic/search.html
new file mode 100644
index 0000000..4a79ace
--- /dev/null
+++ b/sphinx/themes/basic/search.html
@@ -0,0 +1,59 @@
+{#
+ basic/search.html
+ ~~~~~~~~~~~~~~~~~
+
+ Template for the search page.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "layout.html" %}
+{% set title = _('Search') %}
+{% set script_files = script_files + ['_static/searchtools.js'] %}
+{% block extrahead %}
+ <script type="text/javascript">
+ jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
+ </script>
+ {# this is used when loading the search index using $.ajax fails,
+ such as on Chrome for documents on localhost #}
+ <script type="text/javascript" id="searchindexloader"></script>
+ {{ super() }}
+{% endblock %}
+{% block body %}
+ <h1 id="search-documentation">{{ _('Search') }}</h1>
+ <div id="fallback" class="admonition warning">
+ <script type="text/javascript">$('#fallback').hide();</script>
+ <p>
+ {% trans %}Please activate JavaScript to enable the search
+ functionality.{% endtrans %}
+ </p>
+ </div>
+ <p>
+ {% trans %}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.{% endtrans %}
+ </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>
+ {% if search_performed %}
+ <h2>{{ _('Search Results') }}</h2>
+ {% if not search_results %}
+ <p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
+ {% endif %}
+ {% endif %}
+ <div id="search-results">
+ {% if search_results %}
+ <ul>
+ {% for href, caption, context in search_results %}
+ <li><a href="{{ pathto(item.href) }}">{{ caption }}</a>
+ <div class="context">{{ context|e }}</div>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+{% endblock %}
diff --git a/sphinx/themes/basic/searchbox.html b/sphinx/themes/basic/searchbox.html
new file mode 100644
index 0000000..0a746f5
--- /dev/null
+++ b/sphinx/themes/basic/searchbox.html
@@ -0,0 +1,24 @@
+{#
+ basic/searchbox.html
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx sidebar template: quick search box.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- if pagename != "search" and builder != "singlehtml" %}
+<div id="searchbox" style="display: none">
+ <h3>{{ _('Quick search') }}</h3>
+ <form class="search" action="{{ pathto('search') }}" method="get">
+ <input type="text" name="q" />
+ <input type="submit" value="{{ _('Go') }}" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+ <p class="searchtip" style="font-size: 90%">
+ {{ _('Enter search terms or a module, class or function name.') }}
+ </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+{%- endif %}
diff --git a/sphinx/themes/basic/searchresults.html b/sphinx/themes/basic/searchresults.html
new file mode 100644
index 0000000..b3d372c
--- /dev/null
+++ b/sphinx/themes/basic/searchresults.html
@@ -0,0 +1,36 @@
+{#
+ basic/searchresults.html
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Template for the body of the search results page.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+<h1 id="search-documentation">{{ _('Search') }}</h1>
+<p>
+ From here you can search these documents. Enter your search
+ words into the box below and click "search".
+</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>
+{%- if search_performed %}
+ <h2>{{ _('Search Results') }}</h2>
+ {%- if not search_results %}
+ <p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
+ {%- endif %}
+{%- endif %}
+<div id="search-results">
+ {%- if search_results %}
+ <ul class="search">
+ {% for href, caption, context in search_results %}
+ <li><a href="{{ docroot }}{{ href }}/?highlight={{ q }}">{{ caption }}</a>
+ <div class="context">{{ context|e }}</div>
+ </li>
+ {% endfor %}
+ </ul>
+ {%- endif %}
+</div>
diff --git a/sphinx/themes/basic/sourcelink.html b/sphinx/themes/basic/sourcelink.html
new file mode 100644
index 0000000..f3cb71f
--- /dev/null
+++ b/sphinx/themes/basic/sourcelink.html
@@ -0,0 +1,16 @@
+{#
+ basic/sourcelink.html
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx sidebar template: "show source" link.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- if show_source and has_source and sourcename %}
+ <h3>{{ _('This Page') }}</h3>
+ <ul class="this-page-menu">
+ <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
+ rel="nofollow">{{ _('Show Source') }}</a></li>
+ </ul>
+{%- endif %}
diff --git a/sphinx/themes/basic/static/ajax-loader.gif b/sphinx/themes/basic/static/ajax-loader.gif
new file mode 100644
index 0000000..61faf8c
Binary files /dev/null and b/sphinx/themes/basic/static/ajax-loader.gif differ
diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t
new file mode 100644
index 0000000..7ffa466
--- /dev/null
+++ b/sphinx/themes/basic/static/basic.css_t
@@ -0,0 +1,537 @@
+/*
+ * basic.css
+ * ~~~~~~~~~
+ *
+ * Sphinx stylesheet -- basic theme.
+ *
+ * :copyright: Copyright 2007-2014 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: {{ theme_sidebarwidth|toint }}px;
+ margin-left: -100%;
+ font-size: 90%;
+}
+
+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 input[type="text"] {
+ width: 170px;
+}
+
+div.sphinxsidebar #searchbox input[type="submit"] {
+ width: 30px;
+}
+
+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%;
+}
+
+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 dl, table.indextable dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+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;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+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 {
+ visibility: visible;
+}
+
+div.body p.caption {
+ text-align: inherit;
+}
+
+div.body td {
+ text-align: left;
+}
+
+.field-list ul {
+ padding-left: 1em;
+}
+
+.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.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.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+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;
+}
+
+/* -- 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, .highlighted {
+ background-color: #fbe54e;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
+.optional {
+ font-size: 1.3em;
+}
+
+.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 */
+}
+
+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;
+}
+
+tt.descname {
+ background-color: transparent;
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+tt.descclassname {
+ background-color: transparent;
+}
+
+tt.xref, a tt {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+ 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;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+ at media print {
+ div.document,
+ div.documentwrapper,
+ div.bodywrapper {
+ margin: 0 !important;
+ width: 100%;
+ }
+
+ div.sphinxsidebar,
+ div.related,
+ div.footer,
+ #top-link {
+ display: none;
+ }
+}
diff --git a/sphinx/themes/basic/static/comment-bright.png b/sphinx/themes/basic/static/comment-bright.png
new file mode 100644
index 0000000..551517b
Binary files /dev/null and b/sphinx/themes/basic/static/comment-bright.png differ
diff --git a/sphinx/themes/basic/static/comment-close.png b/sphinx/themes/basic/static/comment-close.png
new file mode 100644
index 0000000..09b54be
Binary files /dev/null and b/sphinx/themes/basic/static/comment-close.png differ
diff --git a/sphinx/themes/basic/static/comment.png b/sphinx/themes/basic/static/comment.png
new file mode 100644
index 0000000..92feb52
Binary files /dev/null and b/sphinx/themes/basic/static/comment.png differ
diff --git a/sphinx/themes/basic/static/doctools.js b/sphinx/themes/basic/static/doctools.js
new file mode 100644
index 0000000..c5455c9
--- /dev/null
+++ b/sphinx/themes/basic/static/doctools.js
@@ -0,0 +1,238 @@
+/*
+ * doctools.js
+ * ~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilities for all documentation.
+ *
+ * :copyright: Copyright 2007-2014 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) {
+ if (node.nodeType == 3) {
+ var val = node.nodeValue;
+ var pos = val.toLowerCase().indexOf(text);
+ if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
+ var 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);
+ }
+ }
+ else if (!jQuery(node).is("button, select, textarea")) {
+ jQuery.each(node.childNodes, function() {
+ highlight(this);
+ });
+ }
+ }
+ return this.each(function() {
+ highlight(this);
+ });
+};
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+var Documentation = {
+
+ init : function() {
+ this.fixFirefoxAnchorBug();
+ this.highlightSearchWords();
+ this.initIndexTable();
+ },
+
+ /**
+ * 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
+ */
+ 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);
+ }
+};
+
+// quick alias for translations
+_ = Documentation.gettext;
+
+$(document).ready(function() {
+ Documentation.init();
+});
diff --git a/sphinx/themes/basic/static/down-pressed.png b/sphinx/themes/basic/static/down-pressed.png
new file mode 100644
index 0000000..6f7ad78
Binary files /dev/null and b/sphinx/themes/basic/static/down-pressed.png differ
diff --git a/sphinx/themes/basic/static/down.png b/sphinx/themes/basic/static/down.png
new file mode 100644
index 0000000..3003a88
Binary files /dev/null and b/sphinx/themes/basic/static/down.png differ
diff --git a/sphinx/themes/basic/static/file.png b/sphinx/themes/basic/static/file.png
new file mode 100644
index 0000000..d18082e
Binary files /dev/null and b/sphinx/themes/basic/static/file.png differ
diff --git a/sphinx/themes/basic/static/minus.png b/sphinx/themes/basic/static/minus.png
new file mode 100644
index 0000000..da1c562
Binary files /dev/null and b/sphinx/themes/basic/static/minus.png differ
diff --git a/sphinx/themes/basic/static/plus.png b/sphinx/themes/basic/static/plus.png
new file mode 100644
index 0000000..b3cb374
Binary files /dev/null and b/sphinx/themes/basic/static/plus.png differ
diff --git a/sphinx/themes/basic/static/searchtools.js_t b/sphinx/themes/basic/static/searchtools.js_t
new file mode 100644
index 0000000..047636c
--- /dev/null
+++ b/sphinx/themes/basic/static/searchtools.js_t
@@ -0,0 +1,442 @@
+/*
+ * searchtools.js_t
+ * ~~~~~~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilties for the full-text search.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+{{ search_language_stemming_code|safe }}
+
+{% if search_scorer_tool %}
+{{ search_scorer_tool|safe }}
+{% else %}
+/**
+ * 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
+};
+{% endif %}
+
+/**
+ * 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;
+ var stopwords = {{ search_language_stop_words }};
+
+ // stem the searchterms and add them to the correct list
+ var stemmer = new Stemmer();
+ var searchterms = [];
+ var excluded = [];
+ var hlterms = [];
+ var tmp = query.split(/\s+/);
+ 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());
+ 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, Scorer.term))
+ .concat(this.performTermsSearch(searchterms, excluded, titleterms, Scorer.title));
+
+ // 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) {
+ $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
+ dataType: "text",
+ complete: function(jqxhr, textstatus) {
+ var data = jqxhr.responseText;
+ if (data !== '') {
+ 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 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([filenames[match[0]], fullname, '#'+anchor, descr, score]);
+ }
+ }
+ }
+
+ return results;
+ },
+
+ /**
+ * search for full-text terms in the index
+ */
+ performTermsSearch : function(searchterms, excluded, terms, score) {
+ var filenames = this._index.filenames;
+ var titles = this._index.titles;
+
+ var i, j, file, files;
+ var fileMap = {};
+ var results = [];
+
+ // perform the search on the required terms
+ for (i = 0; i < searchterms.length; i++) {
+ var word = searchterms[i];
+ // no match but word was a required one
+ if ((files = terms[word]) === undefined)
+ break;
+ if (files.length === undefined) {
+ files = [files];
+ }
+ // 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 ||
+ $u.contains(terms[excluded[i]] || [], file)) {
+ valid = false;
+ break;
+ }
+ }
+
+ // if we have still a valid result we can add it to the result list
+ if (valid) {
+ results.push([filenames[file], titles[file], '', null, score]);
+ }
+ }
+ 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 occurance, 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();
+});
diff --git a/sphinx/themes/basic/static/up-pressed.png b/sphinx/themes/basic/static/up-pressed.png
new file mode 100644
index 0000000..8bd587a
Binary files /dev/null and b/sphinx/themes/basic/static/up-pressed.png differ
diff --git a/sphinx/themes/basic/static/up.png b/sphinx/themes/basic/static/up.png
new file mode 100644
index 0000000..b946256
Binary files /dev/null and b/sphinx/themes/basic/static/up.png differ
diff --git a/sphinx/themes/basic/static/websupport.js b/sphinx/themes/basic/static/websupport.js
new file mode 100644
index 0000000..71c0a13
--- /dev/null
+++ b/sphinx/themes/basic/static/websupport.js
@@ -0,0 +1,808 @@
+/*
+ * websupport.js
+ * ~~~~~~~~~~~~~
+ *
+ * sphinx.websupport utilties for all documentation.
+ *
+ * :copyright: Copyright 2007-2014 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() {
+ $('a.comment-close').live("click", function(event) {
+ event.preventDefault();
+ hide($(this).attr('id').substring(2));
+ });
+ $('a.vote').live("click", function(event) {
+ event.preventDefault();
+ handleVote($(this));
+ });
+ $('a.reply').live("click", function(event) {
+ event.preventDefault();
+ openReply($(this).attr('id').substring(2));
+ });
+ $('a.close-reply').live("click", function(event) {
+ event.preventDefault();
+ closeReply($(this).attr('id').substring(2));
+ });
+ $('a.sort-option').live("click", function(event) {
+ event.preventDefault();
+ handleReSort($(this));
+ });
+ $('a.show-proposal').live("click", function(event) {
+ event.preventDefault();
+ showProposal($(this).attr('id').substring(2));
+ });
+ $('a.hide-proposal').live("click", function(event) {
+ event.preventDefault();
+ hideProposal($(this).attr('id').substring(2));
+ });
+ $('a.show-propose-change').live("click", function(event) {
+ event.preventDefault();
+ showProposeChange($(this).attr('id').substring(2));
+ });
+ $('a.hide-propose-change').live("click", function(event) {
+ event.preventDefault();
+ hideProposeChange($(this).attr('id').substring(2));
+ });
+ $('a.accept-comment').live("click", function(event) {
+ event.preventDefault();
+ acceptComment($(this).attr('id').substring(2));
+ });
+ $('a.delete-comment').live("click", function(event) {
+ event.preventDefault();
+ deleteComment($(this).attr('id').substring(2));
+ });
+ $('a.comment-markup').live("click", 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(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>, \
+ <tt>``code``</tt>, \
+ code blocks: <tt>::</tt> 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);
+ }
+});
diff --git a/sphinx/themes/basic/theme.conf b/sphinx/themes/basic/theme.conf
new file mode 100644
index 0000000..f728373
--- /dev/null
+++ b/sphinx/themes/basic/theme.conf
@@ -0,0 +1,8 @@
+[theme]
+inherit = none
+stylesheet = basic.css
+pygments_style = none
+
+[options]
+nosidebar = false
+sidebarwidth = 230
\ No newline at end of file
diff --git a/sphinx/themes/default/layout.html b/sphinx/themes/default/layout.html
new file mode 100644
index 0000000..6231905
--- /dev/null
+++ b/sphinx/themes/default/layout.html
@@ -0,0 +1,14 @@
+{#
+ default/layout.html
+ ~~~~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the default theme.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "basic/layout.html" %}
+
+{% if theme_collapsiblesidebar|tobool %}
+{% set script_files = script_files + ['_static/sidebar.js'] %}
+{% endif %}
diff --git a/sphinx/themes/default/static/default.css_t b/sphinx/themes/default/static/default.css_t
new file mode 100644
index 0000000..cbdc7fb
--- /dev/null
+++ b/sphinx/themes/default/static/default.css_t
@@ -0,0 +1,310 @@
+/*
+ * default.css_t
+ * ~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- default theme.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+ at import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: {{ theme_bodyfont }};
+ font-size: 100%;
+ background-color: {{ theme_footerbgcolor }};
+ color: #000;
+ margin: 0;
+ padding: 0;
+}
+
+div.document {
+ background-color: {{ theme_sidebarbgcolor }};
+}
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 {{ theme_sidebarwidth|toint }}px;
+}
+
+div.body {
+ background-color: {{ theme_bgcolor }};
+ color: {{ theme_textcolor }};
+ padding: 0 20px 30px 20px;
+}
+
+{%- if theme_rightsidebar|tobool %}
+div.bodywrapper {
+ margin: 0 {{ theme_sidebarwidth|toint }}px 0 0;
+}
+{%- endif %}
+
+div.footer {
+ color: {{ theme_footertextcolor }};
+ width: 100%;
+ padding: 9px 0 9px 0;
+ text-align: center;
+ font-size: 75%;
+}
+
+div.footer a {
+ color: {{ theme_footertextcolor }};
+ text-decoration: underline;
+}
+
+div.related {
+ background-color: {{ theme_relbarbgcolor }};
+ line-height: 30px;
+ color: {{ theme_relbartextcolor }};
+}
+
+div.related a {
+ color: {{ theme_relbarlinkcolor }};
+}
+
+div.sphinxsidebar {
+ {%- if theme_stickysidebar|tobool %}
+ top: 30px;
+ bottom: 0;
+ margin: 0;
+ position: fixed;
+ overflow: auto;
+ height: auto;
+ {%- endif %}
+ {%- if theme_rightsidebar|tobool %}
+ float: right;
+ {%- if theme_stickysidebar|tobool %}
+ right: 0;
+ {%- endif %}
+ {%- endif %}
+}
+
+{%- if theme_stickysidebar|tobool %}
+/* this is nice, but it it leads to hidden headings when jumping
+ to an anchor */
+/*
+div.related {
+ position: fixed;
+}
+
+div.documentwrapper {
+ margin-top: 30px;
+}
+*/
+{%- endif %}
+
+div.sphinxsidebar h3 {
+ font-family: {{ theme_headfont }};
+ color: {{ theme_sidebartextcolor }};
+ font-size: 1.4em;
+ font-weight: normal;
+ margin: 0;
+ padding: 0;
+}
+
+div.sphinxsidebar h3 a {
+ color: {{ theme_sidebartextcolor }};
+}
+
+div.sphinxsidebar h4 {
+ font-family: {{ theme_headfont }};
+ color: {{ theme_sidebartextcolor }};
+ font-size: 1.3em;
+ font-weight: normal;
+ margin: 5px 0 0 0;
+ padding: 0;
+}
+
+div.sphinxsidebar p {
+ color: {{ theme_sidebartextcolor }};
+}
+
+div.sphinxsidebar p.topless {
+ margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+ margin: 10px;
+ padding: 0;
+ color: {{ theme_sidebartextcolor }};
+}
+
+div.sphinxsidebar a {
+ color: {{ theme_sidebarlinkcolor }};
+}
+
+div.sphinxsidebar input {
+ border: 1px solid {{ theme_sidebarlinkcolor }};
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+{% if theme_collapsiblesidebar|tobool %}
+/* for collapsible sidebar */
+div#sidebarbutton {
+ background-color: {{ theme_sidebarbtncolor }};
+}
+{% endif %}
+
+/* -- hyperlink styles ------------------------------------------------------ */
+
+a {
+ color: {{ theme_linkcolor }};
+ text-decoration: none;
+}
+
+a:visited {
+ color: {{ theme_visitedlinkcolor }};
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+{% if theme_externalrefs|tobool %}
+a.external {
+ text-decoration: none;
+ border-bottom: 1px dashed {{ theme_linkcolor }};
+}
+
+a.external:hover {
+ text-decoration: none;
+ border-bottom: none;
+}
+
+a.external:visited {
+ text-decoration: none;
+ border-bottom: 1px dashed {{ theme_visitedlinkcolor }};
+}
+{% endif %}
+
+/* -- body styles ----------------------------------------------------------- */
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: {{ theme_headfont }};
+ background-color: {{ theme_headbgcolor }};
+ font-weight: normal;
+ color: {{ theme_headtextcolor }};
+ border-bottom: 1px solid #ccc;
+ margin: 20px -20px 10px -20px;
+ padding: 3px 0 3px 10px;
+}
+
+div.body h1 { margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 160%; }
+div.body h3 { font-size: 140%; }
+div.body h4 { font-size: 120%; }
+div.body h5 { font-size: 110%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+ color: {{ theme_headlinkcolor }};
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+}
+
+a.headerlink:hover {
+ background-color: {{ theme_headlinkcolor }};
+ color: white;
+}
+
+div.body p, div.body dd, div.body li {
+ text-align: justify;
+ line-height: 130%;
+}
+
+div.admonition p.admonition-title + p {
+ display: inline;
+}
+
+div.admonition p {
+ margin-bottom: 5px;
+}
+
+div.admonition pre {
+ margin-bottom: 5px;
+}
+
+div.admonition ul, div.admonition ol {
+ margin-bottom: 5px;
+}
+
+div.note {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
+
+div.seealso {
+ background-color: #ffc;
+ border: 1px solid #ff6;
+}
+
+div.topic {
+ background-color: #eee;
+}
+
+div.warning {
+ background-color: #ffe4e4;
+ border: 1px solid #f66;
+}
+
+p.admonition-title {
+ display: inline;
+}
+
+p.admonition-title:after {
+ content: ":";
+}
+
+pre {
+ padding: 5px;
+ background-color: {{ theme_codebgcolor }};
+ color: {{ theme_codetextcolor }};
+ line-height: 120%;
+ border: 1px solid #ac9;
+ border-left: none;
+ border-right: none;
+}
+
+tt {
+ background-color: #ecf0f3;
+ padding: 0 1px 0 1px;
+ font-size: 0.95em;
+}
+
+th {
+ background-color: #ede;
+}
+
+.warning tt {
+ background: #efc2c2;
+}
+
+.note tt {
+ background: #d6d6d6;
+}
+
+.viewcode-back {
+ font-family: {{ theme_bodyfont }};
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+}
diff --git a/sphinx/themes/default/static/sidebar.js_t b/sphinx/themes/default/static/sidebar.js_t
new file mode 100644
index 0000000..8731569
--- /dev/null
+++ b/sphinx/themes/default/static/sidebar.js_t
@@ -0,0 +1,165 @@
+/*
+ * sidebar.js
+ * ~~~~~~~~~~
+ *
+ * This script makes the Sphinx sidebar collapsible.
+ *
+ * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds
+ * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
+ * used to collapse and expand the sidebar.
+ *
+ * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
+ * and the width of the sidebar and the margin-left of the document
+ * are decreased. When the sidebar is expanded the opposite happens.
+ * This script saves a per-browser/per-session cookie used to
+ * remember the position of the sidebar among the pages.
+ * Once the browser is closed the cookie is deleted and the position
+ * reset to the default (expanded).
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+$(function() {
+ {% if theme_rightsidebar|tobool %}
+ {% set side = 'right' %}
+ {% set opposite = 'left' %}
+ {% set initial_label = '»' %}
+ {% set expand_label = '«' %}
+ {% set collapse_label = '»' %}
+ {% else %}
+ {% set side = 'left' %}
+ {% set opposite = 'right' %}
+ {% set initial_label = '«' %}
+ {% set expand_label = '»' %}
+ {% set collapse_label = '«' %}
+ {% endif %}
+
+ // global elements used by the functions.
+ // the 'sidebarbutton' element is defined as global after its
+ // creation, in the add_sidebar_button function
+ var bodywrapper = $('.bodywrapper');
+ var sidebar = $('.sphinxsidebar');
+ var sidebarwrapper = $('.sphinxsidebarwrapper');
+
+ // for some reason, the document has no sidebar; do not run into errors
+ if (!sidebar.length) return;
+
+ // original margin-left of the bodywrapper and width of the sidebar
+ // with the sidebar expanded
+ var bw_margin_expanded = bodywrapper.css('margin-{{side}}');
+ var ssb_width_expanded = sidebar.width();
+
+ // margin-left of the bodywrapper and width of the sidebar
+ // with the sidebar collapsed
+ var bw_margin_collapsed = '.8em';
+ var ssb_width_collapsed = '.8em';
+
+ // colors used by the current theme
+ var dark_color = $('.related').css('background-color');
+ var light_color = $('.document').css('background-color');
+
+ function sidebar_is_collapsed() {
+ return sidebarwrapper.is(':not(:visible)');
+ }
+
+ function toggle_sidebar() {
+ if (sidebar_is_collapsed())
+ expand_sidebar();
+ else
+ collapse_sidebar();
+ }
+
+ function collapse_sidebar() {
+ sidebarwrapper.hide();
+ sidebar.css('width', ssb_width_collapsed);
+ bodywrapper.css('margin-{{side}}', bw_margin_collapsed);
+ sidebarbutton.css({
+ 'margin-{{side}}': '0',
+ 'height': bodywrapper.height()
+ });
+ sidebarbutton.find('span').text('{{expand_label}}');
+ sidebarbutton.attr('title', _('Expand sidebar'));
+ document.cookie = 'sidebar=collapsed';
+ }
+
+ function expand_sidebar() {
+ bodywrapper.css('margin-{{side}}', bw_margin_expanded);
+ sidebar.css('width', ssb_width_expanded);
+ sidebarwrapper.show();
+ sidebarbutton.css({
+ 'margin-{{side}}': ssb_width_expanded-12,
+ 'height': bodywrapper.height()
+ });
+ sidebarbutton.find('span').text('{{collapse_label}}');
+ sidebarbutton.attr('title', _('Collapse sidebar'));
+ document.cookie = 'sidebar=expanded';
+ }
+
+ function add_sidebar_button() {
+ sidebarwrapper.css({
+ 'float': '{{side}}',
+ 'margin-{{opposite}}': '0',
+ 'width': ssb_width_expanded - 28
+ });
+ // create the button
+ sidebar.append(
+ '<div id="sidebarbutton"><span>{{initial_label}}</span></div>'
+ );
+ var sidebarbutton = $('#sidebarbutton');
+ light_color = sidebarbutton.css('background-color');
+ // find the height of the viewport to center the '<<' in the page
+ var viewport_height;
+ if (window.innerHeight)
+ viewport_height = window.innerHeight;
+ else
+ viewport_height = $(window).height();
+ sidebarbutton.find('span').css({
+ 'display': 'block',
+ 'margin-top': (viewport_height - sidebar.position().top - 20) / 2
+ });
+
+ sidebarbutton.click(toggle_sidebar);
+ sidebarbutton.attr('title', _('Collapse sidebar'));
+ sidebarbutton.css({
+ 'color': '#FFFFFF',
+ 'border-{{side}}': '1px solid ' + dark_color,
+ 'font-size': '1.2em',
+ 'cursor': 'pointer',
+ 'height': bodywrapper.height(),
+ 'padding-top': '1px',
+ 'margin-{{side}}': ssb_width_expanded - 12
+ });
+
+ sidebarbutton.hover(
+ function () {
+ $(this).css('background-color', dark_color);
+ },
+ function () {
+ $(this).css('background-color', light_color);
+ }
+ );
+ }
+
+ function set_position_from_cookie() {
+ if (!document.cookie)
+ return;
+ var items = document.cookie.split(';');
+ for(var k=0; k<items.length; k++) {
+ var key_val = items[k].split('=');
+ var key = key_val[0].replace(/ /, ""); // strip leading spaces
+ if (key == 'sidebar') {
+ var value = key_val[1];
+ if ((value == 'collapsed') && (!sidebar_is_collapsed()))
+ collapse_sidebar();
+ else if ((value == 'expanded') && (sidebar_is_collapsed()))
+ expand_sidebar();
+ }
+ }
+ }
+
+ add_sidebar_button();
+ var sidebarbutton = $('#sidebarbutton');
+ set_position_from_cookie();
+});
diff --git a/sphinx/themes/default/theme.conf b/sphinx/themes/default/theme.conf
new file mode 100644
index 0000000..59704ac
--- /dev/null
+++ b/sphinx/themes/default/theme.conf
@@ -0,0 +1,32 @@
+[theme]
+inherit = basic
+stylesheet = default.css
+pygments_style = sphinx
+
+[options]
+rightsidebar = false
+stickysidebar = false
+collapsiblesidebar = false
+externalrefs = false
+
+footerbgcolor = #11303d
+footertextcolor = #ffffff
+sidebarbgcolor = #1c4e63
+sidebarbtncolor = #3c6e83
+sidebartextcolor = #ffffff
+sidebarlinkcolor = #98dbcc
+relbarbgcolor = #133f52
+relbartextcolor = #ffffff
+relbarlinkcolor = #ffffff
+bgcolor = #ffffff
+textcolor = #000000
+headbgcolor = #f2f2f2
+headtextcolor = #20435c
+headlinkcolor = #c60f0f
+linkcolor = #355f7c
+visitedlinkcolor = #355f7c
+codebgcolor = #eeffcc
+codetextcolor = #333333
+
+bodyfont = sans-serif
+headfont = 'Trebuchet MS', sans-serif
diff --git a/sphinx/themes/epub/epub-cover.html b/sphinx/themes/epub/epub-cover.html
new file mode 100644
index 0000000..e5a75d7
--- /dev/null
+++ b/sphinx/themes/epub/epub-cover.html
@@ -0,0 +1,25 @@
+{#
+ epub/epub-cover.html
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Sample template for the html cover page.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "layout.html" %}
+{%- block header %}{% endblock %}
+{%- block rootrellink %}{% endblock %}
+{%- block relbaritems %}{% endblock %}
+{%- block sidebarlogo %}{% endblock %}
+{%- block linktags %}{% endblock %}
+{%- block relbar1 %}{% endblock %}
+{%- block sidebar1 %}{% endblock %}
+{%- block sidebar2 %}{% endblock %}
+{%- block footer %}{% endblock %}
+
+{% block content %}
+ <div class="epub-cover">
+ <img src="{{ image }}" alt="Cover image" />
+ </div>
+{% endblock %}
diff --git a/sphinx/themes/epub/layout.html b/sphinx/themes/epub/layout.html
new file mode 100644
index 0000000..49183f1
--- /dev/null
+++ b/sphinx/themes/epub/layout.html
@@ -0,0 +1,29 @@
+{#
+ epub/layout.html
+ ~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the epub theme.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "basic/layout.html" %}
+
+{%- block doctype -%}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+{%- endblock -%}
+{# add only basic navigation links #}
+{% block sidebar1 %}{% endblock %}
+{% block sidebar2 %}{% endblock %}
+{% block relbar2 %}{% endblock %}
+{% block linktags %}{% endblock %}
+
+{# redefine relbar1 and footer to only call super if options are true #}
+{%- block relbar1 %}
+{% if theme_relbar1|tobool %}{{ super() }}{% endif %}
+{%- endblock %}
+{%- block footer %}
+{% if theme_footer|tobool %}{{ super() }}{% endif %}
+{%- endblock %}
+
diff --git a/sphinx/themes/epub/static/epub.css b/sphinx/themes/epub/static/epub.css
new file mode 100644
index 0000000..30912b9
--- /dev/null
+++ b/sphinx/themes/epub/static/epub.css
@@ -0,0 +1,534 @@
+/*
+ * epub.css_t
+ * ~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- epub theme.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+ clear: both;
+}
+
+a:link, a:visited {
+ color: #3333ff;
+ text-decoration: underline;
+}
+
+img {
+ border: 0;
+ max-width: 100%;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+ width: 100%;
+ font-family: sans-serif;
+ 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%;
+}
+
+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: 100%;
+}
+
+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%;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 130%;
+}
+
+span.linkdescr {
+ font-style: italic;
+ padding-top: 5px;
+ font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+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;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+a.headerlink {
+ visibility: hidden;
+}
+
+div.body p.caption {
+ text-align: inherit;
+}
+
+div.body td {
+ text-align: left;
+}
+
+.field-list ul {
+ padding-left: 100%;
+}
+
+.first {
+ margin-top: 0 !important;
+}
+
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+.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: 110%;
+ 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.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.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+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;
+}
+
+/* -- 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, .highlighted {
+ background-color: #ddd;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 110%;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
+.optional {
+ font-size: 130%;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+.system-message {
+ background-color: #fda;
+ padding: 5px;
+ border: 3px solid red;
+}
+
+.footnote:target {
+ background-color: #dddddd;
+}
+
+.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-style: italic;
+}
+
+.accelerator {
+ text-decoration: underline;
+}
+
+.classifier {
+ font-style: oblique;
+}
+
+abbr, acronym {
+ border-bottom: dotted 1px;
+ cursor: help;
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+ font-family: monospace;
+ overflow: auto;
+ overflow-y: hidden;
+}
+
+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;
+}
+
+tt {
+ font-family: monospace;
+}
+
+tt.descname {
+ background-color: transparent;
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+tt.descclassname {
+ background-color: transparent;
+}
+
+tt.xref, a tt {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+ background-color: transparent;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+ vertical-align: middle;
+}
+
+div.body div.math p {
+ text-align: center;
+}
+
+span.eqno {
+ float: right;
+}
+
+/* -- special divs --------------------------------------------------------- */
+
+div.quotebar {
+ background-color: #e3eff1;
+ max-width: 250px;
+ float: right;
+ font-family: sans-serif;
+ padding: 7px 7px;
+ border: 1px solid #ccc;
+}
+div.footer {
+ background-color: #e3eff1;
+ padding: 3px 8px 3px 0;
+ clear: both;
+ font-family: sans-serif;
+ font-size: 80%;
+ text-align: right;
+}
+
+div.footer a {
+ text-decoration: underline;
+}
+
+/* -- link-target ----------------------------------------------------------- */
+
+.link-target {
+ font-size: 80%;
+}
+
+table .link-target {
+ /* Do not show links in tables, there is not enough space */
+ display: none;
+}
+
+/* -- font-face ------------------------------------------------------------- */
+
+/*
+ at font-face {
+ font-family: "LiberationNarrow";
+ font-style: normal;
+ font-weight: normal;
+ src: url("res:///Data/fonts/LiberationNarrow-Regular.otf")
+ format("opentype");
+}
+ at font-face {
+ font-family: "LiberationNarrow";
+ font-style: oblique, italic;
+ font-weight: normal;
+ src: url("res:///Data/fonts/LiberationNarrow-Italic.otf")
+ format("opentype");
+}
+ at font-face {
+ font-family: "LiberationNarrow";
+ font-style: normal;
+ font-weight: bold;
+ src: url("res:///Data/fonts/LiberationNarrow-Bold.otf")
+ format("opentype");
+}
+ at font-face {
+ font-family: "LiberationNarrow";
+ font-style: oblique, italic;
+ font-weight: bold;
+ src: url("res:///Data/fonts/LiberationNarrow-BoldItalic.otf")
+ format("opentype");
+}
+*/
\ No newline at end of file
diff --git a/sphinx/themes/epub/theme.conf b/sphinx/themes/epub/theme.conf
new file mode 100644
index 0000000..11f098e
--- /dev/null
+++ b/sphinx/themes/epub/theme.conf
@@ -0,0 +1,8 @@
+[theme]
+inherit = basic
+stylesheet = epub.css
+pygments_style = none
+
+[options]
+relbar1 = true
+footer = true
diff --git a/sphinx/themes/haiku/layout.html b/sphinx/themes/haiku/layout.html
new file mode 100644
index 0000000..569763b
--- /dev/null
+++ b/sphinx/themes/haiku/layout.html
@@ -0,0 +1,66 @@
+{#
+ haiku/layout.html
+ ~~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the haiku theme.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "basic/layout.html" %}
+
+{# do not display relbars #}
+{% block relbar1 %}{% endblock %}
+{% block relbar2 %}{% endblock %}
+
+{% macro nav() %}
+ <p>
+ {%- block haikurel1 %}
+ {%- endblock %}
+ {%- if prev %}
+ « <a href="{{ prev.link|e }}">{{ prev.title }}</a>
+ ::
+ {%- endif %}
+ <a class="uplink" href="{{ pathto(master_doc) }}">{{ _('Contents') }}</a>
+ {%- if next %}
+ ::
+ <a href="{{ next.link|e }}">{{ next.title }}</a> »
+ {%- endif %}
+ {%- block haikurel2 %}
+ {%- endblock %}
+ </p>
+{% endmacro %}
+
+{% block content %}
+ <div class="header">
+ {%- block haikuheader %}
+ {%- if theme_full_logo != "false" %}
+ <a href="{{ pathto('index') }}">
+ <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
+ </a>
+ {%- else %}
+ {%- if logo -%}
+ <img class="rightlogo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
+ {%- endif -%}
+ <h1 class="heading"><a href="{{ pathto('index') }}">
+ <span>{{ shorttitle|e }}</span></a></h1>
+ <h2 class="heading"><span>{{ title|striptags|e }}</span></h2>
+ {%- endif %}
+ {%- endblock %}
+ </div>
+ <div class="topnav">
+ {{ nav() }}
+ </div>
+ <div class="content">
+ {#{%- if display_toc %}
+ <div id="toc">
+ <h3>{{ _('Table Of Contents') }}</h3>
+ {{ toc }}
+ </div>
+ {%- endif %}#}
+ {% block body %}{% endblock %}
+ </div>
+ <div class="bottomnav">
+ {{ nav() }}
+ </div>
+{% endblock %}
diff --git a/sphinx/themes/haiku/static/alert_info_32.png b/sphinx/themes/haiku/static/alert_info_32.png
new file mode 100644
index 0000000..05b4fe8
Binary files /dev/null and b/sphinx/themes/haiku/static/alert_info_32.png differ
diff --git a/sphinx/themes/haiku/static/alert_warning_32.png b/sphinx/themes/haiku/static/alert_warning_32.png
new file mode 100644
index 0000000..f13611c
Binary files /dev/null and b/sphinx/themes/haiku/static/alert_warning_32.png differ
diff --git a/sphinx/themes/haiku/static/bg-page.png b/sphinx/themes/haiku/static/bg-page.png
new file mode 100644
index 0000000..c6f3bc4
Binary files /dev/null and b/sphinx/themes/haiku/static/bg-page.png differ
diff --git a/sphinx/themes/haiku/static/bullet_orange.png b/sphinx/themes/haiku/static/bullet_orange.png
new file mode 100644
index 0000000..ad5d02f
Binary files /dev/null and b/sphinx/themes/haiku/static/bullet_orange.png differ
diff --git a/sphinx/themes/haiku/static/haiku.css_t b/sphinx/themes/haiku/static/haiku.css_t
new file mode 100644
index 0000000..bd81db0
--- /dev/null
+++ b/sphinx/themes/haiku/static/haiku.css_t
@@ -0,0 +1,371 @@
+/*
+ * 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 at free.fr>
+ * Stephan Assmus <superstippi at gmx.de>
+ * Braden Ewing <brewin at gmail.com>
+ * Humdinger <humdingerb at gmail.com>
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+ at 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: {{ theme_textcolor }};
+}
+
+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: {{ theme_linkcolor }};
+}
+
+a:visited {
+ font-weight: bold;
+ text-decoration: none;
+ color: {{ theme_visitedlinkcolor }};
+}
+
+a:hover, a:active {
+ text-decoration: underline;
+ color: {{ theme_hoverlinkcolor }};
+}
+
+/* Some headers act as anchors, don't give them a hover effect */
+
+h1 a:hover, a:active {
+ text-decoration: none;
+ color: {{ theme_headingcolor }};
+}
+
+h2 a:hover, a:active {
+ text-decoration: none;
+ color: {{ theme_headingcolor }};
+}
+
+h3 a:hover, a:active {
+ text-decoration: none;
+ color: {{ theme_headingcolor }};
+}
+
+h4 a:hover, a:active {
+ text-decoration: none;
+ color: {{ theme_headingcolor }};
+}
+
+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: {{ theme_headingcolor }};
+ border: 0;
+ margin: 0;
+ padding-top: 15px;
+}
+div.header h1 a {
+ font-weight: normal;
+ color: {{ theme_headingcolor }};
+}
+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: {{ theme_headingcolor }};
+ 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: {{ theme_linkcolor }};
+}
+table.index a:hover, table.index a:active {
+ text-decoration: underline;
+ color: {{ theme_hoverlinkcolor }};
+}
+
+
+/* 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: {{ theme_headingcolor }};
+ border-bottom: dotted thin #e0e0e0;
+ margin-top: 30px;
+}
+
+h2 {
+ font-size: 1.2em;
+ font-weight: normal;
+ color: {{ theme_headingcolor }};
+ border-bottom: dotted thin #e0e0e0;
+ margin-top: 30px;
+}
+
+h3 {
+ font-size: 1.1em;
+ font-weight: normal;
+ color: {{ theme_headingcolor }};
+ margin-top: 30px;
+}
+
+h4 {
+ font-size: 1.0em;
+ font-weight: normal;
+ color: {{ theme_headingcolor }};
+ 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;
+}
+
+tt {
+ 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 */
+ at 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;
+}
diff --git a/sphinx/themes/haiku/theme.conf b/sphinx/themes/haiku/theme.conf
new file mode 100644
index 0000000..3537da1
--- /dev/null
+++ b/sphinx/themes/haiku/theme.conf
@@ -0,0 +1,12 @@
+[theme]
+inherit = basic
+stylesheet = haiku.css
+pygments_style = autumn
+
+[options]
+full_logo = false
+textcolor = #333333
+headingcolor = #0c3762
+linkcolor = #dc3c01
+visitedlinkcolor = #892601
+hoverlinkcolor = #ff4500
diff --git a/sphinx/themes/nature/static/nature.css_t b/sphinx/themes/nature/static/nature.css_t
new file mode 100644
index 0000000..ff89148
--- /dev/null
+++ b/sphinx/themes/nature/static/nature.css_t
@@ -0,0 +1,245 @@
+/*
+ * nature.css_t
+ * ~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- nature theme.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+ at import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: Arial, sans-serif;
+ font-size: 100%;
+ background-color: #111;
+ color: #555;
+ margin: 0;
+ padding: 0;
+}
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 {{ theme_sidebarwidth|toint }}px;
+}
+
+hr {
+ border: 1px solid #B1B4B6;
+}
+
+div.document {
+ background-color: #eee;
+}
+
+div.body {
+ background-color: #ffffff;
+ color: #3E4349;
+ padding: 0 30px 30px 30px;
+ font-size: 0.9em;
+}
+
+div.footer {
+ color: #555;
+ width: 100%;
+ padding: 13px 0;
+ text-align: center;
+ font-size: 75%;
+}
+
+div.footer a {
+ color: #444;
+ text-decoration: underline;
+}
+
+div.related {
+ background-color: #6BA81E;
+ line-height: 32px;
+ color: #fff;
+ text-shadow: 0px 1px 0 #444;
+ font-size: 0.9em;
+}
+
+div.related a {
+ color: #E2F3CC;
+}
+
+div.sphinxsidebar {
+ font-size: 0.75em;
+ line-height: 1.5em;
+}
+
+div.sphinxsidebarwrapper{
+ padding: 20px 0;
+}
+
+div.sphinxsidebar h3,
+div.sphinxsidebar h4 {
+ font-family: Arial, sans-serif;
+ color: #222;
+ font-size: 1.2em;
+ font-weight: normal;
+ margin: 0;
+ padding: 5px 10px;
+ background-color: #ddd;
+ text-shadow: 1px 1px 0 white
+}
+
+div.sphinxsidebar h4{
+ font-size: 1.1em;
+}
+
+div.sphinxsidebar h3 a {
+ color: #444;
+}
+
+
+div.sphinxsidebar p {
+ color: #888;
+ padding: 5px 20px;
+}
+
+div.sphinxsidebar p.topless {
+}
+
+div.sphinxsidebar ul {
+ margin: 10px 20px;
+ padding: 0;
+ color: #000;
+}
+
+div.sphinxsidebar a {
+ color: #444;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #ccc;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar input[type=text]{
+ margin-left: 20px;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+a {
+ color: #005B81;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #E32E00;
+ text-decoration: underline;
+}
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: Arial, sans-serif;
+ background-color: #BED4EB;
+ font-weight: normal;
+ color: #212224;
+ margin: 30px 0px 10px 0px;
+ padding: 5px 0 5px 10px;
+ text-shadow: 0px 1px 0 white
+}
+
+div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 150%; background-color: #C8D5E3; }
+div.body h3 { font-size: 120%; background-color: #D8DEE3; }
+div.body h4 { font-size: 110%; background-color: #D8DEE3; }
+div.body h5 { font-size: 100%; background-color: #D8DEE3; }
+div.body h6 { font-size: 100%; background-color: #D8DEE3; }
+
+a.headerlink {
+ color: #c60f0f;
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+}
+
+a.headerlink:hover {
+ background-color: #c60f0f;
+ color: white;
+}
+
+div.body p, div.body dd, div.body li {
+ line-height: 1.5em;
+}
+
+div.admonition p.admonition-title + p {
+ display: inline;
+}
+
+div.highlight{
+ background-color: white;
+}
+
+div.note {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
+
+div.seealso {
+ background-color: #ffc;
+ border: 1px solid #ff6;
+}
+
+div.topic {
+ background-color: #eee;
+}
+
+div.warning {
+ background-color: #ffe4e4;
+ border: 1px solid #f66;
+}
+
+p.admonition-title {
+ display: inline;
+}
+
+p.admonition-title:after {
+ content: ":";
+}
+
+pre {
+ padding: 10px;
+ background-color: White;
+ color: #222;
+ line-height: 1.2em;
+ border: 1px solid #C6C9CB;
+ font-size: 1.1em;
+ margin: 1.5em 0 1.5em 0;
+ -webkit-box-shadow: 1px 1px 1px #d8d8d8;
+ -moz-box-shadow: 1px 1px 1px #d8d8d8;
+}
+
+tt {
+ background-color: #ecf0f3;
+ color: #222;
+ /* padding: 1px 2px; */
+ font-size: 1.1em;
+ font-family: monospace;
+}
+
+.viewcode-back {
+ font-family: Arial, sans-serif;
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+}
diff --git a/sphinx/themes/nature/theme.conf b/sphinx/themes/nature/theme.conf
new file mode 100644
index 0000000..1cc4004
--- /dev/null
+++ b/sphinx/themes/nature/theme.conf
@@ -0,0 +1,4 @@
+[theme]
+inherit = basic
+stylesheet = nature.css
+pygments_style = tango
diff --git a/sphinx/themes/pyramid/layout.html b/sphinx/themes/pyramid/layout.html
new file mode 100644
index 0000000..8780cea
--- /dev/null
+++ b/sphinx/themes/pyramid/layout.html
@@ -0,0 +1,24 @@
+{%- extends "basic/layout.html" %}
+
+{%- block extrahead %}
+<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&subset=latin" type="text/css" media="screen" charset="utf-8" />
+<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&subset=latin" type="text/css" media="screen" charset="utf-8" />
+<!--[if lte IE 6]>
+<link rel="stylesheet" href="{{ pathto('_static/ie6.css', 1) }}" type="text/css" media="screen" charset="utf-8" />
+<![endif]-->
+{% endblock %}
+
+{% block header %}
+{%- if logo %}
+<div class="header">
+ <div class="logo">
+ <a href="{{ pathto(master_doc) }}">
+ <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
+ </a>
+ </div>
+</div>
+{%- endif %}
+{% endblock %}
+
+{%- block sidebarlogo %}{%- endblock %}
+{%- block sidebarsourcelink %}{%- endblock %}
diff --git a/sphinx/themes/pyramid/static/dialog-note.png b/sphinx/themes/pyramid/static/dialog-note.png
new file mode 100644
index 0000000..263fbd5
Binary files /dev/null and b/sphinx/themes/pyramid/static/dialog-note.png differ
diff --git a/sphinx/themes/pyramid/static/dialog-seealso.png b/sphinx/themes/pyramid/static/dialog-seealso.png
new file mode 100644
index 0000000..3eb7b05
Binary files /dev/null and b/sphinx/themes/pyramid/static/dialog-seealso.png differ
diff --git a/sphinx/themes/pyramid/static/dialog-todo.png b/sphinx/themes/pyramid/static/dialog-todo.png
new file mode 100644
index 0000000..babc4b6
Binary files /dev/null and b/sphinx/themes/pyramid/static/dialog-todo.png differ
diff --git a/sphinx/themes/pyramid/static/dialog-topic.png b/sphinx/themes/pyramid/static/dialog-topic.png
new file mode 100644
index 0000000..2ac5747
Binary files /dev/null and b/sphinx/themes/pyramid/static/dialog-topic.png differ
diff --git a/sphinx/themes/pyramid/static/dialog-warning.png b/sphinx/themes/pyramid/static/dialog-warning.png
new file mode 100644
index 0000000..7233d45
Binary files /dev/null and b/sphinx/themes/pyramid/static/dialog-warning.png differ
diff --git a/sphinx/themes/pyramid/static/epub.css b/sphinx/themes/pyramid/static/epub.css
new file mode 100644
index 0000000..7465a42
--- /dev/null
+++ b/sphinx/themes/pyramid/static/epub.css
@@ -0,0 +1,310 @@
+/*
+ * default.css_t
+ * ~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- default theme.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+ at import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: {{ theme_bodyfont }};
+ font-size: 100%;
+ background-color: {{ theme_footerbgcolor }};
+ color: #000;
+ margin: 0;
+ padding: 0;
+}
+
+div.document {
+ background-color: {{ theme_sidebarbgcolor }};
+}
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 230px;
+}
+
+div.body {
+ background-color: {{ theme_bgcolor }};
+ color: {{ theme_textcolor }};
+ padding: 0 20px 30px 20px;
+}
+
+{%- if theme_rightsidebar|tobool %}
+div.bodywrapper {
+ margin: 0 230px 0 0;
+}
+{%- endif %}
+
+div.footer {
+ color: {{ theme_footertextcolor }};
+ width: 100%;
+ padding: 9px 0 9px 0;
+ text-align: center;
+ font-size: 75%;
+}
+
+div.footer a {
+ color: {{ theme_footertextcolor }};
+ text-decoration: underline;
+}
+
+div.related {
+ background-color: {{ theme_relbarbgcolor }};
+ line-height: 30px;
+ color: {{ theme_relbartextcolor }};
+}
+
+div.related a {
+ color: {{ theme_relbarlinkcolor }};
+}
+
+div.sphinxsidebar {
+ {%- if theme_stickysidebar|tobool %}
+ top: 30px;
+ bottom: 0;
+ margin: 0;
+ position: fixed;
+ overflow: auto;
+ height: auto;
+ {%- endif %}
+ {%- if theme_rightsidebar|tobool %}
+ float: right;
+ {%- if theme_stickysidebar|tobool %}
+ right: 0;
+ {%- endif %}
+ {%- endif %}
+}
+
+{%- if theme_stickysidebar|tobool %}
+/* this is nice, but it it leads to hidden headings when jumping
+ to an anchor */
+/*
+div.related {
+ position: fixed;
+}
+
+div.documentwrapper {
+ margin-top: 30px;
+}
+*/
+{%- endif %}
+
+div.sphinxsidebar h3 {
+ font-family: {{ theme_headfont }};
+ color: {{ theme_sidebartextcolor }};
+ font-size: 1.4em;
+ font-weight: normal;
+ margin: 0;
+ padding: 0;
+}
+
+div.sphinxsidebar h3 a {
+ color: {{ theme_sidebartextcolor }};
+}
+
+div.sphinxsidebar h4 {
+ font-family: {{ theme_headfont }};
+ color: {{ theme_sidebartextcolor }};
+ font-size: 1.3em;
+ font-weight: normal;
+ margin: 5px 0 0 0;
+ padding: 0;
+}
+
+div.sphinxsidebar p {
+ color: {{ theme_sidebartextcolor }};
+}
+
+div.sphinxsidebar p.topless {
+ margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+ margin: 10px;
+ padding: 0;
+ color: {{ theme_sidebartextcolor }};
+}
+
+div.sphinxsidebar a {
+ color: {{ theme_sidebarlinkcolor }};
+}
+
+div.sphinxsidebar input {
+ border: 1px solid {{ theme_sidebarlinkcolor }};
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+{% if theme_collapsiblesidebar|tobool %}
+/* for collapsible sidebar */
+div#sidebarbutton {
+ background-color: {{ theme_sidebarbtncolor }};
+}
+{% endif %}
+
+/* -- hyperlink styles ------------------------------------------------------ */
+
+a {
+ color: {{ theme_linkcolor }};
+ text-decoration: none;
+}
+
+a:visited {
+ color: {{ theme_visitedlinkcolor }};
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+{% if theme_externalrefs|tobool %}
+a.external {
+ text-decoration: none;
+ border-bottom: 1px dashed {{ theme_linkcolor }};
+}
+
+a.external:hover {
+ text-decoration: none;
+ border-bottom: none;
+}
+
+a.external:visited {
+ text-decoration: none;
+ border-bottom: 1px dashed {{ theme_visitedlinkcolor }};
+}
+{% endif %}
+
+/* -- body styles ----------------------------------------------------------- */
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: {{ theme_headfont }};
+ background-color: {{ theme_headbgcolor }};
+ font-weight: normal;
+ color: {{ theme_headtextcolor }};
+ border-bottom: 1px solid #ccc;
+ margin: 20px -20px 10px -20px;
+ padding: 3px 0 3px 10px;
+}
+
+div.body h1 { margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 160%; }
+div.body h3 { font-size: 140%; }
+div.body h4 { font-size: 120%; }
+div.body h5 { font-size: 110%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+ color: {{ theme_headlinkcolor }};
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+}
+
+a.headerlink:hover {
+ background-color: {{ theme_headlinkcolor }};
+ color: white;
+}
+
+div.body p, div.body dd, div.body li {
+ text-align: justify;
+ line-height: 130%;
+}
+
+div.admonition p.admonition-title + p {
+ display: inline;
+}
+
+div.admonition p {
+ margin-bottom: 5px;
+}
+
+div.admonition pre {
+ margin-bottom: 5px;
+}
+
+div.admonition ul, div.admonition ol {
+ margin-bottom: 5px;
+}
+
+div.note {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
+
+div.seealso {
+ background-color: #ffc;
+ border: 1px solid #ff6;
+}
+
+div.topic {
+ background-color: #eee;
+}
+
+div.warning {
+ background-color: #ffe4e4;
+ border: 1px solid #f66;
+}
+
+p.admonition-title {
+ display: inline;
+}
+
+p.admonition-title:after {
+ content: ":";
+}
+
+pre {
+ padding: 5px;
+ background-color: {{ theme_codebgcolor }};
+ color: {{ theme_codetextcolor }};
+ line-height: 120%;
+ border: 1px solid #ac9;
+ border-left: none;
+ border-right: none;
+}
+
+tt {
+ background-color: #ecf0f3;
+ padding: 0 1px 0 1px;
+ font-size: 0.95em;
+}
+
+th {
+ background-color: #ede;
+}
+
+.warning tt {
+ background: #efc2c2;
+}
+
+.note tt {
+ background: #d6d6d6;
+}
+
+.viewcode-back {
+ font-family: {{ theme_bodyfont }};
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+}
diff --git a/sphinx/themes/pyramid/static/footerbg.png b/sphinx/themes/pyramid/static/footerbg.png
new file mode 100644
index 0000000..1fbc873
Binary files /dev/null and b/sphinx/themes/pyramid/static/footerbg.png differ
diff --git a/sphinx/themes/pyramid/static/headerbg.png b/sphinx/themes/pyramid/static/headerbg.png
new file mode 100644
index 0000000..0596f20
Binary files /dev/null and b/sphinx/themes/pyramid/static/headerbg.png differ
diff --git a/sphinx/themes/pyramid/static/ie6.css b/sphinx/themes/pyramid/static/ie6.css
new file mode 100644
index 0000000..74baa5d
--- /dev/null
+++ b/sphinx/themes/pyramid/static/ie6.css
@@ -0,0 +1,7 @@
+* html img,
+* html .png{position:relative;behavior:expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none",
+this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "',sizingMethod='image')",
+this.src = "_static/transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''),
+this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "',sizingMethod='crop')",
+this.runtimeStyle.backgroundImage = "none")),this.pngSet=true)
+);}
diff --git a/sphinx/themes/pyramid/static/middlebg.png b/sphinx/themes/pyramid/static/middlebg.png
new file mode 100644
index 0000000..2369cfb
Binary files /dev/null and b/sphinx/themes/pyramid/static/middlebg.png differ
diff --git a/sphinx/themes/pyramid/static/pyramid.css_t b/sphinx/themes/pyramid/static/pyramid.css_t
new file mode 100644
index 0000000..168e52d
--- /dev/null
+++ b/sphinx/themes/pyramid/static/pyramid.css_t
@@ -0,0 +1,342 @@
+/*
+ * pyramid.css_t
+ * ~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- pylons theme.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+ at import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: "Nobile", sans-serif;
+ font-size: 100%;
+ background-color: #393939;
+ color: #ffffff;
+ margin: 0;
+ padding: 0;
+}
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 {{ theme_sidebarwidth }}px;
+}
+
+hr {
+ border: 1px solid #B1B4B6;
+}
+
+div.document {
+ background-color: #eee;
+}
+
+div.header {
+ width:100%;
+ background: #f4ad32 url(headerbg.png) repeat-x 0 top;
+ border-bottom: 2px solid #ffffff;
+}
+
+div.logo {
+ text-align: center;
+ padding-top: 10px;
+}
+
+div.body {
+ background-color: #ffffff;
+ color: #3E4349;
+ padding: 0 30px 30px 30px;
+ font-size: 1em;
+ border: 2px solid #ddd;
+ border-right-style: none;
+ overflow: auto;
+}
+
+div.footer {
+ color: #ffffff;
+ width: 100%;
+ padding: 13px 0;
+ text-align: center;
+ font-size: 75%;
+ background: transparent;
+ clear:both;
+}
+
+div.footer a {
+ color: #ffffff;
+ text-decoration: none;
+}
+
+div.footer a:hover {
+ color: #e88f00;
+ text-decoration: underline;
+}
+
+div.related {
+ line-height: 30px;
+ color: #373839;
+ font-size: 0.8em;
+ background-color: #eee;
+}
+
+div.related a {
+ color: #1b61d6;
+}
+
+div.related ul {
+ padding-left: {{ theme_sidebarwidth|toint + 10 }}px;
+}
+
+div.sphinxsidebar {
+ font-size: 0.75em;
+ line-height: 1.5em;
+}
+
+div.sphinxsidebarwrapper{
+ padding: 10px 0;
+}
+
+div.sphinxsidebar h3,
+div.sphinxsidebar h4 {
+ font-family: "Neuton", sans-serif;
+ color: #373839;
+ font-size: 1.4em;
+ font-weight: normal;
+ margin: 0;
+ padding: 5px 10px;
+ border-bottom: 2px solid #ddd;
+}
+
+div.sphinxsidebar h4{
+ font-size: 1.3em;
+}
+
+div.sphinxsidebar h3 a {
+ color: #000000;
+}
+
+
+div.sphinxsidebar p {
+ color: #888;
+ padding: 5px 20px;
+}
+
+div.sphinxsidebar p.topless {
+}
+
+div.sphinxsidebar ul {
+ margin: 10px 20px;
+ padding: 0;
+ color: #373839;
+}
+
+div.sphinxsidebar a {
+ color: #444;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #ccc;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar input[type=text]{
+ margin-left: 20px;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar {
+ margin: 0 0 0.5em 1em;
+ border: 2px solid #c6d880;
+ background-color: #e6efc2;
+ width: 40%;
+ float: right;
+ border-right-style: none;
+ border-left-style: none;
+ padding: 10px 20px;
+}
+
+p.sidebar-title {
+ font-weight: bold;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+a, a .pre {
+ color: #1b61d6;
+ text-decoration: none;
+}
+
+a:hover, a:hover .pre {
+ text-decoration: underline;
+}
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: "Neuton", sans-serif;
+ background-color: #ffffff;
+ font-weight: normal;
+ color: #373839;
+ margin: 30px 0px 10px 0px;
+ padding: 5px 0;
+}
+
+div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 150%; background-color: #ffffff; }
+div.body h3 { font-size: 120%; background-color: #ffffff; }
+div.body h4 { font-size: 110%; background-color: #ffffff; }
+div.body h5 { font-size: 100%; background-color: #ffffff; }
+div.body h6 { font-size: 100%; background-color: #ffffff; }
+
+a.headerlink {
+ color: #1b61d6;
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+}
+
+a.headerlink:hover {
+ text-decoration: underline;
+}
+
+div.body p, div.body dd, div.body li {
+ line-height: 1.5em;
+}
+
+div.admonition p.admonition-title + p {
+ display: inline;
+}
+
+div.admonition {
+ background: #eeeeec;
+ border: 2px solid #babdb6;
+ border-right-style: none;
+ border-left-style: none;
+ padding: 10px 20px 10px 60px;
+}
+
+div.highlight{
+ background-color: white;
+}
+
+div.note {
+ border: 2px solid #7a9eec;
+ border-right-style: none;
+ border-left-style: none;
+ padding: 10px 20px 10px 60px;
+ background: #e1ecfe url(dialog-note.png) no-repeat 10px 8px;
+}
+
+div.seealso {
+ background: #fff6bf url(dialog-seealso.png) no-repeat 10px 8px;
+ border: 2px solid #ffd324;
+ border-left-style: none;
+ border-right-style: none;
+ padding: 10px 20px 10px 60px;
+}
+
+div.topic {
+ background: #eeeeee;
+ border: 2px solid #C6C9CB;
+ padding: 10px 20px;
+ border-right-style: none;
+ border-left-style: none;
+}
+
+div.warning {
+ background: #fbe3e4 url(dialog-warning.png) no-repeat 10px 8px;
+ border: 2px solid #fbc2c4;
+ border-right-style: none;
+ border-left-style: none;
+ padding: 10px 20px 10px 60px;
+}
+
+div.admonition-todo {
+ background: #f2d9b4 url(dialog-todo.png) no-repeat 10px 8px;
+ border: 2px solid #e9b96e;
+ border-right-style: none;
+ border-left-style: none;
+ padding: 10px 20px 10px 60px;
+}
+
+div.note p.admonition-title,
+div.warning p.admonition-title,
+div.seealso p.admonition-title,
+div.admonition-todo p.admonition-title {
+ display: none;
+}
+
+p.admonition-title:after {
+ content: ":";
+}
+
+pre {
+ padding: 10px;
+ background-color: #fafafa;
+ color: #222;
+ line-height: 1.2em;
+ border: 2px solid #C6C9CB;
+ font-size: 1.1em;
+ margin: 1.5em 0 1.5em 0;
+ border-right-style: none;
+ border-left-style: none;
+}
+
+tt {
+ background-color: transparent;
+ color: #222;
+ font-size: 1.1em;
+ font-family: monospace;
+}
+
+.viewcode-back {
+ font-family: "Nobile", sans-serif;
+}
+
+div.viewcode-block:target {
+ background-color: #fff6bf;
+ border: 2px solid #ffd324;
+ border-left-style: none;
+ border-right-style: none;
+ padding: 10px 20px;
+}
+
+table.highlighttable {
+ width: 100%;
+}
+
+table.highlighttable td {
+ padding: 0;
+}
+
+a em.std-term {
+ color: #007f00;
+}
+
+a:hover em.std-term {
+ text-decoration: underline;
+}
+
+.download {
+ font-family: "Nobile", sans-serif;
+ font-weight: normal;
+ font-style: normal;
+}
+
+tt.xref {
+ font-weight: normal;
+ font-style: normal;
+}
diff --git a/sphinx/themes/pyramid/static/transparent.gif b/sphinx/themes/pyramid/static/transparent.gif
new file mode 100644
index 0000000..0341802
Binary files /dev/null and b/sphinx/themes/pyramid/static/transparent.gif differ
diff --git a/sphinx/themes/pyramid/theme.conf b/sphinx/themes/pyramid/theme.conf
new file mode 100644
index 0000000..409579f
--- /dev/null
+++ b/sphinx/themes/pyramid/theme.conf
@@ -0,0 +1,4 @@
+[theme]
+inherit = basic
+stylesheet = pyramid.css
+pygments_style = sphinx.pygments_styles.PyramidStyle
diff --git a/sphinx/themes/scrolls/artwork/logo.svg b/sphinx/themes/scrolls/artwork/logo.svg
new file mode 100644
index 0000000..0907a4e
--- /dev/null
+++ b/sphinx/themes/scrolls/artwork/logo.svg
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="200"
+ height="80"
+ id="svg2766"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="logo.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs2768">
+ <linearGradient
+ id="linearGradient6558">
+ <stop
+ style="stop-color:#575757;stop-opacity:1;"
+ offset="0"
+ id="stop6560" />
+ <stop
+ style="stop-color:#2f2f2f;stop-opacity:1;"
+ offset="1"
+ id="stop6562" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective2774" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6558"
+ id="radialGradient2797"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7160081,0,0,0.6767021,-34.98413,-3.3035294e-2)"
+ cx="61.297766"
+ cy="60.910986"
+ fx="61.297766"
+ fy="60.910986"
+ r="44.688254" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="6.1848684"
+ inkscape:cx="95.923838"
+ inkscape:cy="34.518668"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1440"
+ inkscape:window-height="852"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata2771">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="opacity:1;fill:url(#radialGradient2797);fill-opacity:1;fill-rule:evenodd;stroke:#323232;stroke-width:0.71600807000000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 72.4375 8.6875 L 3.0625 18.71875 L 20.84375 29.0625 L 20.6875 44.09375 L 7.75 36.1875 L 8.40625 71.75 L 17.125 65.625 L 29.09375 67.5625 L 33.15625 39.90625 L 25.875 43.78125 L 26.1875 33.59375 L 46.875 31.34375 L 47.21875 42.96875 L 39.28125 40.5625 L 42.6875 67.71875 L 52.375 66.75 L 60.3125 71.75 L 62.90625 33.4375 L 53.03125 43.625 L 53.03125 28.25 L 72.4375 8.6875 z M 48.03125 22.125 L 47.0625 26.46875 L 28.46875 28.09375 L 28.46875 25.1875 L 48.03125 22.125 z M 58.375 4 [...]
+ id="path2783" />
+ <path
+ style="opacity:1;fill:#e7eef6;fill-opacity:1;fill-rule:nonzero;stroke:#e1e8f3;stroke-width:0.52748101999999997;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 75.632462,22.265877 L 64.489624,64.880679 L 92.7889,40.941187 L 91.373937,61.872575 L 128.87048,23.519253 L 116.84328,58.36312 L 144.25821,44.450641 L 145.49631,65.632704 L 169.02007,38.183758 L 170.78877,60.493861 L 193.07447,18.631085 L 176.09491,36.554369 L 176.44864,19.633786 L 152.0405,44.701316 L 156.81601,27.655396 L 128.87048,44.325304 L 137.00652,14.494942 L 99.863721,44.325304 L 100.74807,27.028707 L 76.163076,45.829355 L 75.632462,22.265877 z"
+ id="path2804" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;opacity:1;fill:#1752b4;fill-opacity:1;fill-rule:nonzero;stroke:#28437f;stroke-width:0.71600807000000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans"
+ x="68.40242"
+ y="54.03759"
+ id="text2800"><tspan
+ sodipodi:role="line"
+ id="tspan2802"
+ x="68.40242"
+ y="54.03759"
+ style="font-size:36px;fill:#1752b4;fill-opacity:1;fill-rule:nonzero;stroke:#28437f;stroke-width:0.71600807000000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate">Project</tspan></text>
+ </g>
+</svg>
diff --git a/sphinx/themes/scrolls/layout.html b/sphinx/themes/scrolls/layout.html
new file mode 100644
index 0000000..a27f60a
--- /dev/null
+++ b/sphinx/themes/scrolls/layout.html
@@ -0,0 +1,42 @@
+{#
+ scrolls/layout.html
+ ~~~~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the scrolls theme, originally written
+ by Armin Ronacher.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "basic/layout.html" %}
+{% set script_files = script_files + ['_static/theme_extras.js'] %}
+{% set css_files = css_files + ['_static/print.css'] %}
+{# do not display relbars #}
+{% block relbar1 %}{% endblock %}
+{% block relbar2 %}{% endblock %}
+{% block content %}
+ <div id="content">
+ <div class="header">
+ <h1 class="heading"><a href="{{ pathto('index') }}"
+ title="back to the documentation overview"><span>{{ title|striptags|e }}</span></a></h1>
+ </div>
+ <div class="relnav">
+ {%- if prev %}
+ <a href="{{ prev.link|e }}">« {{ prev.title }}</a> |
+ {%- endif %}
+ <a href="{{ pathto(current_page_name) if current_page_name else '#' }}">{{ title }}</a>
+ {%- if next %}
+ | <a href="{{ next.link|e }}">{{ next.title }} »</a>
+ {%- endif %}
+ </div>
+ <div id="contentwrapper">
+ {%- if display_toc %}
+ <div id="toc">
+ <h3>{{ _('Table Of Contents') }}</h3>
+ {{ toc }}
+ </div>
+ {%- endif %}
+ {% block body %}{% endblock %}
+ </div>
+ </div>
+{% endblock %}
diff --git a/sphinx/themes/scrolls/static/darkmetal.png b/sphinx/themes/scrolls/static/darkmetal.png
new file mode 100644
index 0000000..e8c9ff6
Binary files /dev/null and b/sphinx/themes/scrolls/static/darkmetal.png differ
diff --git a/sphinx/themes/scrolls/static/headerbg.png b/sphinx/themes/scrolls/static/headerbg.png
new file mode 100644
index 0000000..0c5b365
Binary files /dev/null and b/sphinx/themes/scrolls/static/headerbg.png differ
diff --git a/sphinx/themes/scrolls/static/logo.png b/sphinx/themes/scrolls/static/logo.png
new file mode 100644
index 0000000..d1961cf
Binary files /dev/null and b/sphinx/themes/scrolls/static/logo.png differ
diff --git a/sphinx/themes/scrolls/static/metal.png b/sphinx/themes/scrolls/static/metal.png
new file mode 100644
index 0000000..97166f1
Binary files /dev/null and b/sphinx/themes/scrolls/static/metal.png differ
diff --git a/sphinx/themes/scrolls/static/navigation.png b/sphinx/themes/scrolls/static/navigation.png
new file mode 100644
index 0000000..1e248d4
Binary files /dev/null and b/sphinx/themes/scrolls/static/navigation.png differ
diff --git a/sphinx/themes/scrolls/static/print.css b/sphinx/themes/scrolls/static/print.css
new file mode 100644
index 0000000..715d90a
--- /dev/null
+++ b/sphinx/themes/scrolls/static/print.css
@@ -0,0 +1,7 @@
+ at media print {
+ div.header, div.relnav, #toc { display: none; }
+ #contentwrapper { padding: 0; margin: 0; border: none; }
+ body { color: black; background-color: white; }
+ div.footer { border-top: 1px solid #888; color: #888; margin-top: 1cm; }
+ div.footer a { text-decoration: none; }
+}
diff --git a/sphinx/themes/scrolls/static/scrolls.css_t b/sphinx/themes/scrolls/static/scrolls.css_t
new file mode 100644
index 0000000..197aef2
--- /dev/null
+++ b/sphinx/themes/scrolls/static/scrolls.css_t
@@ -0,0 +1,431 @@
+/*
+ * scrolls.css_t
+ * ~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- scrolls theme.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+body {
+ background-color: #222;
+ margin: 0;
+ padding: 0;
+ font-family: 'Georgia', serif;
+ font-size: 15px;
+ color: #eee;
+}
+
+div.footer {
+ border-top: 1px solid #111;
+ padding: 8px;
+ font-size: 11px;
+ text-align: center;
+ letter-spacing: 0.5px;
+}
+
+div.footer a {
+ color: #eee;
+}
+
+div.header {
+ margin: 0 -15px 0 -15px;
+ background: url(headerbg.png) repeat-x;
+ border-top: 6px solid {{ theme_headerbordercolor }};
+}
+
+div.relnav {
+ border-bottom: 1px solid #111;
+ background: url(navigation.png);
+ margin: 0 -15px 0 -15px;
+ padding: 2px 20px 0 28px;
+ line-height: 25px;
+ color: #aaa;
+ font-size: 12px;
+ text-align: center;
+}
+
+div.relnav a {
+ color: #eee;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+div.relnav a:hover {
+ text-decoration: underline;
+}
+
+#content {
+ background-color: white;
+ color: #111;
+ border-bottom: 1px solid black;
+ background: url(watermark.png) center 0;
+ padding: 0 15px 0 15px;
+ margin: 0;
+}
+
+h1 {
+ margin: 0;
+ padding: 15px 0 0 0;
+}
+
+h1.heading {
+ margin: 0;
+ padding: 0;
+ height: 80px;
+}
+
+h1.heading:hover {
+ background: #222;
+}
+
+h1.heading a {
+ background: url({{ logo if logo else 'logo.png' }}) no-repeat center 0;
+ display: block;
+ width: 100%;
+ height: 80px;
+}
+
+h1.heading a:focus {
+ -moz-outline: none;
+ outline: none;
+}
+
+h1.heading span {
+ display: none;
+}
+
+#contentwrapper {
+ max-width: 680px;
+ padding: 0 18px 20px 18px;
+ margin: 0 auto 0 auto;
+ border-right: 1px solid #eee;
+ border-left: 1px solid #eee;
+ background: url(watermark_blur.png) center -114px;
+}
+
+#contentwrapper h2,
+#contentwrapper h2 a {
+ color: #222;
+ font-size: 24px;
+ margin: 20px 0 0 0;
+}
+
+#contentwrapper h3,
+#contentwrapper h3 a {
+ color: {{ theme_subheadlinecolor }};
+ font-size: 20px;
+ margin: 20px 0 0 0;
+}
+
+table.docutils {
+ border-collapse: collapse;
+ border: 2px solid #aaa;
+ margin: 0.5em 1.5em 0.5em 1.5em;
+}
+
+table.docutils td {
+ padding: 2px;
+ border: 1px solid #ddd;
+}
+
+p, li, dd, dt, blockquote {
+ color: #333;
+}
+
+blockquote {
+ margin: 10px 0 10px 20px;
+}
+
+p {
+ line-height: 20px;
+ margin-bottom: 0;
+ margin-top: 10px;
+}
+
+hr {
+ border-top: 1px solid #ccc;
+ border-bottom: 0;
+ border-right: 0;
+ border-left: 0;
+ margin-bottom: 10px;
+ margin-top: 20px;
+}
+
+dl {
+ margin-left: 10px;
+}
+
+li, dt {
+ margin-top: 5px;
+}
+
+dt {
+ font-weight: bold;
+ color: #000;
+}
+
+dd {
+ margin-top: 10px;
+ line-height: 20px;
+}
+
+th {
+ text-align: left;
+ padding: 3px;
+ background-color: #f2f2f2;
+}
+
+a {
+ color: {{ theme_linkcolor }};
+}
+
+a:hover {
+ color: {{ theme_visitedlinkcolor }};
+}
+
+pre {
+ background: #ededed url(metal.png);
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ padding: 5px;
+ font-size: 13px;
+ font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+}
+
+tt {
+ font-size: 13px;
+ font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+ color: black;
+ padding: 1px 2px 1px 2px;
+ background-color: #fafafa;
+ border-bottom: 1px solid #eee;
+}
+
+a.reference:hover tt {
+ border-bottom-color: #aaa;
+}
+
+cite {
+ /* abusing <cite>, it's generated by ReST for `x` */
+ font-size: 13px;
+ font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+ font-weight: bold;
+ font-style: normal;
+}
+
+div.admonition {
+ margin: 10px 0 10px 0;
+ padding: 10px;
+ border: 1px solid #ccc;
+}
+
+div.admonition p.admonition-title {
+ background-color: {{ theme_admonitioncolor }};
+ color: white;
+ margin: -10px -10px 10px -10px;
+ padding: 4px 10px 4px 10px;
+ font-weight: bold;
+ font-size: 15px;
+}
+
+div.admonition p.admonition-title a {
+ color: white!important;
+}
+
+a.headerlink {
+ color: #B4B4B4!important;
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none!important;
+ 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,
+dt:hover > a.headerlink {
+ visibility: visible;
+}
+
+a.headerlink:hover {
+ background-color: #B4B4B4;
+ color: #F0F0F0!important;
+}
+
+table.indextable {
+ width: 100%;
+}
+
+table.genindextable td {
+ vertical-align: top;
+ width: 50%;
+}
+
+table.indextable dl dd {
+ font-size: 11px;
+}
+
+table.indextable dl dd a {
+ color: #000;
+}
+
+div.modindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+table.modindextable {
+ width: 100%;
+ border: none;
+}
+
+table.modindextable img.toggler {
+ margin-right: 10px;
+}
+
+dl.function dt,
+dl.class dt,
+dl.exception dt,
+dl.method dt,
+dl.attribute dt {
+ font-weight: normal;
+}
+
+dt .descname {
+ font-weight: bold;
+ margin-right: 4px;
+}
+
+dt .descname, dt .descclassname {
+ padding: 0;
+ background: transparent;
+ border-bottom: 1px solid #111;
+}
+
+dt .descclassname {
+ margin-left: 2px;
+}
+
+dl dt big {
+ font-size: 100%;
+}
+
+ul.search {
+ margin: 10px 0 0 30px;
+ padding: 0;
+}
+
+ul.search li {
+ margin: 10px 0 0 0;
+ padding: 0;
+}
+
+ul.search div.context {
+ font-size: 12px;
+ padding: 4px 0 0 20px;
+ color: #888;
+}
+
+span.highlight {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
+
+#toc {
+ margin: 0 -17px 0 -17px;
+ display: none;
+}
+
+#toc h3 {
+ float: right;
+ margin: 5px 5px 0 0;
+ padding: 0;
+ font-size: 12px;
+ color: #777;
+}
+
+#toc h3:hover {
+ color: #333;
+ cursor: pointer;
+}
+
+.expandedtoc {
+ background: #222 url(darkmetal.png);
+ border-bottom: 1px solid #111;
+ outline-bottom: 1px solid #000;
+ padding: 5px;
+}
+
+.expandedtoc h3 {
+ color: #aaa;
+ margin: 0!important;
+}
+
+.expandedtoc h3:hover {
+ color: white!important;
+}
+
+#tod h3:hover {
+ color: white;
+}
+
+#toc a {
+ color: #ddd;
+ text-decoration: none;
+}
+
+#toc a:hover {
+ color: white;
+ text-decoration: underline;
+}
+
+#toc ul {
+ margin: 5px 0 12px 17px;
+ padding: 0 7px 0 7px;
+}
+
+#toc ul ul {
+ margin-bottom: 0;
+}
+
+#toc ul li {
+ margin: 2px 0 0 0;
+}
+
+.line-block {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.line-block .line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 1.5em;
+}
+
+.viewcode-link {
+ float: right;
+}
+
+.viewcode-back {
+ float: right;
+ font-family: 'Georgia', serif;
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+ margin: -1px -5px;
+ padding: 0 5px;
+}
diff --git a/sphinx/themes/scrolls/static/theme_extras.js b/sphinx/themes/scrolls/static/theme_extras.js
new file mode 100644
index 0000000..1c04218
--- /dev/null
+++ b/sphinx/themes/scrolls/static/theme_extras.js
@@ -0,0 +1,26 @@
+$(function() {
+
+ var
+ toc = $('#toc').show(),
+ items = $('#toc > ul').hide();
+
+ $('#toc h3')
+ .click(function() {
+ if (items.is(':visible')) {
+ items.animate({
+ height: 'hide',
+ opacity: 'hide'
+ }, 300, function() {
+ toc.removeClass('expandedtoc');
+ });
+ }
+ else {
+ items.animate({
+ height: 'show',
+ opacity: 'show'
+ }, 400);
+ toc.addClass('expandedtoc');
+ }
+ });
+
+});
diff --git a/sphinx/themes/scrolls/static/watermark.png b/sphinx/themes/scrolls/static/watermark.png
new file mode 100644
index 0000000..eb1b6be
Binary files /dev/null and b/sphinx/themes/scrolls/static/watermark.png differ
diff --git a/sphinx/themes/scrolls/static/watermark_blur.png b/sphinx/themes/scrolls/static/watermark_blur.png
new file mode 100644
index 0000000..563f6cd
Binary files /dev/null and b/sphinx/themes/scrolls/static/watermark_blur.png differ
diff --git a/sphinx/themes/scrolls/theme.conf b/sphinx/themes/scrolls/theme.conf
new file mode 100644
index 0000000..4e7800f
--- /dev/null
+++ b/sphinx/themes/scrolls/theme.conf
@@ -0,0 +1,11 @@
+[theme]
+inherit = basic
+stylesheet = scrolls.css
+pygments_style = tango
+
+[options]
+headerbordercolor = #1752b4
+subheadlinecolor = #0d306b
+linkcolor = #1752b4
+visitedlinkcolor = #444
+admonitioncolor = #28437f
diff --git a/sphinx/themes/sphinxdoc/layout.html b/sphinx/themes/sphinxdoc/layout.html
new file mode 100644
index 0000000..5bf78eb
--- /dev/null
+++ b/sphinx/themes/sphinxdoc/layout.html
@@ -0,0 +1,14 @@
+{#
+ sphinxdoc/layout.html
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the sphinxdoc theme.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "basic/layout.html" %}
+
+{# put the sidebar before the body #}
+{% block sidebar1 %}{{ sidebar() }}{% endblock %}
+{% block sidebar2 %}{% endblock %}
diff --git a/sphinx/themes/sphinxdoc/static/contents.png b/sphinx/themes/sphinxdoc/static/contents.png
new file mode 100644
index 0000000..7fb8215
Binary files /dev/null and b/sphinx/themes/sphinxdoc/static/contents.png differ
diff --git a/sphinx/themes/sphinxdoc/static/navigation.png b/sphinx/themes/sphinxdoc/static/navigation.png
new file mode 100644
index 0000000..1081dc1
Binary files /dev/null and b/sphinx/themes/sphinxdoc/static/navigation.png differ
diff --git a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t
new file mode 100644
index 0000000..0f3b9aa
--- /dev/null
+++ b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t
@@ -0,0 +1,339 @@
+/*
+ * sphinxdoc.css_t
+ * ~~~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- sphinxdoc theme. Originally created by
+ * Armin Ronacher for Werkzeug.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+ at import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+ 'Verdana', sans-serif;
+ font-size: 14px;
+ letter-spacing: -0.01em;
+ line-height: 150%;
+ text-align: center;
+ background-color: #BFD1D4;
+ color: black;
+ padding: 0;
+ border: 1px solid #aaa;
+
+ margin: 0px 80px 0px 80px;
+ min-width: 740px;
+}
+
+div.document {
+ background-color: white;
+ text-align: left;
+ background-image: url(contents.png);
+ background-repeat: repeat-x;
+}
+
+div.bodywrapper {
+ margin: 0 {{ theme_sidebarwidth|toint + 10 }}px 0 0;
+ border-right: 1px solid #ccc;
+}
+
+div.body {
+ margin: 0;
+ padding: 0.5em 20px 20px 20px;
+}
+
+div.related {
+ font-size: 1em;
+}
+
+div.related ul {
+ background-image: url(navigation.png);
+ height: 2em;
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+}
+
+div.related ul li {
+ margin: 0;
+ padding: 0;
+ height: 2em;
+ float: left;
+}
+
+div.related ul li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+div.related ul li a {
+ margin: 0;
+ padding: 0 5px 0 5px;
+ line-height: 1.75em;
+ color: #EE9816;
+}
+
+div.related ul li a:hover {
+ color: #3CA8E7;
+}
+
+div.sphinxsidebarwrapper {
+ padding: 0;
+}
+
+div.sphinxsidebar {
+ margin: 0;
+ padding: 0.5em 15px 15px 0;
+ width: {{ theme_sidebarwidth|toint - 20 }}px;
+ float: right;
+ font-size: 1em;
+ text-align: left;
+}
+
+div.sphinxsidebar h3, div.sphinxsidebar h4 {
+ margin: 1em 0 0.5em 0;
+ font-size: 1em;
+ padding: 0.1em 0 0.1em 0.5em;
+ color: white;
+ border: 1px solid #86989B;
+ background-color: #AFC1C4;
+}
+
+div.sphinxsidebar h3 a {
+ color: white;
+}
+
+div.sphinxsidebar ul {
+ padding-left: 1.5em;
+ margin-top: 7px;
+ padding: 0;
+ line-height: 130%;
+}
+
+div.sphinxsidebar ul ul {
+ margin-left: 20px;
+}
+
+div.footer {
+ background-color: #E3EFF1;
+ color: #86989B;
+ padding: 3px 8px 3px 0;
+ clear: both;
+ font-size: 0.8em;
+ text-align: right;
+}
+
+div.footer a {
+ color: #86989B;
+ text-decoration: underline;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+p {
+ margin: 0.8em 0 0.5em 0;
+}
+
+a {
+ color: #CA7900;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #2491CF;
+}
+
+div.body a {
+ text-decoration: underline;
+}
+
+h1 {
+ margin: 0;
+ padding: 0.7em 0 0.3em 0;
+ font-size: 1.5em;
+ color: #11557C;
+}
+
+h2 {
+ margin: 1.3em 0 0.2em 0;
+ font-size: 1.35em;
+ padding: 0;
+}
+
+h3 {
+ margin: 1em 0 -0.3em 0;
+ font-size: 1.2em;
+}
+
+div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
+ color: black!important;
+}
+
+h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
+ display: none;
+ margin: 0 0 0 0.3em;
+ padding: 0 0.2em 0 0.2em;
+ color: #aaa!important;
+}
+
+h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
+h5:hover a.anchor, h6:hover a.anchor {
+ display: inline;
+}
+
+h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
+h5 a.anchor:hover, h6 a.anchor:hover {
+ color: #777;
+ background-color: #eee;
+}
+
+a.headerlink {
+ color: #c60f0f!important;
+ font-size: 1em;
+ margin-left: 6px;
+ padding: 0 4px 0 4px;
+ text-decoration: none!important;
+}
+
+a.headerlink:hover {
+ background-color: #ccc;
+ color: white!important;
+}
+
+cite, code, tt {
+ font-family: 'Consolas', 'Deja Vu Sans Mono',
+ 'Bitstream Vera Sans Mono', monospace;
+ font-size: 0.95em;
+ letter-spacing: 0.01em;
+}
+
+tt {
+ background-color: #f2f2f2;
+ border-bottom: 1px solid #ddd;
+ color: #333;
+}
+
+tt.descname, tt.descclassname, tt.xref {
+ border: 0;
+}
+
+hr {
+ border: 1px solid #abc;
+ margin: 2em;
+}
+
+a tt {
+ border: 0;
+ color: #CA7900;
+}
+
+a tt:hover {
+ color: #2491CF;
+}
+
+pre {
+ font-family: 'Consolas', 'Deja Vu Sans Mono',
+ 'Bitstream Vera Sans Mono', monospace;
+ font-size: 0.95em;
+ letter-spacing: 0.015em;
+ line-height: 120%;
+ padding: 0.5em;
+ border: 1px solid #ccc;
+ background-color: #f8f8f8;
+}
+
+pre a {
+ color: inherit;
+ text-decoration: underline;
+}
+
+td.linenos pre {
+ padding: 0.5em 0;
+}
+
+div.quotebar {
+ background-color: #f8f8f8;
+ max-width: 250px;
+ float: right;
+ padding: 2px 7px;
+ border: 1px solid #ccc;
+}
+
+div.topic {
+ background-color: #f8f8f8;
+}
+
+table {
+ border-collapse: collapse;
+ margin: 0 -0.5em 0 -0.5em;
+}
+
+table td, table th {
+ padding: 0.2em 0.5em 0.2em 0.5em;
+}
+
+div.admonition, div.warning {
+ font-size: 0.9em;
+ margin: 1em 0 1em 0;
+ border: 1px solid #86989B;
+ background-color: #f7f7f7;
+ padding: 0;
+}
+
+div.admonition p, div.warning p {
+ margin: 0.5em 1em 0.5em 1em;
+ padding: 0;
+}
+
+div.admonition pre, div.warning pre {
+ margin: 0.4em 1em 0.4em 1em;
+}
+
+div.admonition p.admonition-title,
+div.warning p.admonition-title {
+ margin: 0;
+ padding: 0.1em 0 0.1em 0.5em;
+ color: white;
+ border-bottom: 1px solid #86989B;
+ font-weight: bold;
+ background-color: #AFC1C4;
+}
+
+div.warning {
+ border: 1px solid #940000;
+}
+
+div.warning p.admonition-title {
+ background-color: #CF0000;
+ border-bottom-color: #940000;
+}
+
+div.admonition ul, div.admonition ol,
+div.warning ul, div.warning ol {
+ margin: 0.1em 0.5em 0.5em 3em;
+ padding: 0;
+}
+
+div.versioninfo {
+ margin: 1em 0 0 0;
+ border: 1px solid #ccc;
+ background-color: #DDEAF0;
+ padding: 8px;
+ line-height: 1.3em;
+ font-size: 0.9em;
+}
+
+.viewcode-back {
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+ 'Verdana', sans-serif;
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+}
diff --git a/sphinx/themes/sphinxdoc/theme.conf b/sphinx/themes/sphinxdoc/theme.conf
new file mode 100644
index 0000000..9a22fef
--- /dev/null
+++ b/sphinx/themes/sphinxdoc/theme.conf
@@ -0,0 +1,4 @@
+[theme]
+inherit = basic
+stylesheet = sphinxdoc.css
+pygments_style = friendly
diff --git a/sphinx/themes/traditional/static/traditional.css_t b/sphinx/themes/traditional/static/traditional.css_t
new file mode 100644
index 0000000..c0328b2
--- /dev/null
+++ b/sphinx/themes/traditional/static/traditional.css_t
@@ -0,0 +1,700 @@
+/*
+ * traditional.css
+ * ~~~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- traditional docs.python.org theme.
+ *
+ * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+body {
+ color: #000;
+ margin: 0;
+ padding: 0;
+}
+
+/* :::: LAYOUT :::: */
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 {{ theme_sidebarwidth }}px 0 0;
+}
+
+div.body {
+ background-color: white;
+ padding: 0 20px 30px 20px;
+}
+
+div.sphinxsidebarwrapper {
+ border: 1px solid #99ccff;
+ padding: 10px;
+ margin: 10px 15px 10px 0;
+}
+
+div.sphinxsidebar {
+ float: right;
+ margin-left: -100%;
+ width: {{ theme_sidebarwidth }}px;
+}
+
+div.clearer {
+ clear: both;
+}
+
+div.footer {
+ clear: both;
+ width: 100%;
+ background-color: #99ccff;
+ padding: 9px 0 9px 0;
+ text-align: center;
+}
+
+div.related {
+ background-color: #99ccff;
+ color: #333;
+ width: 100%;
+ height: 30px;
+ line-height: 30px;
+ border-bottom: 5px solid white;
+}
+
+div.related h3 {
+ display: none;
+}
+
+div.related ul {
+ margin: 0;
+ padding: 0 0 0 10px;
+ list-style: none;
+}
+
+div.related li {
+ display: inline;
+ font-weight: bold;
+}
+
+div.related li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+/* ::: SIDEBAR :::: */
+div.sphinxsidebar h3 {
+ margin: 0;
+}
+
+div.sphinxsidebar h4 {
+ margin: 5px 0 0 0;
+}
+
+div.sphinxsidebar p.topless {
+ margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+ margin: 10px;
+ margin-left: 15px;
+ padding: 0;
+}
+
+div.sphinxsidebar ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+ margin-top: 10px;
+}
+
+
+/* :::: SEARCH :::: */
+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;
+}
+
+/* :::: COMMON FORM STYLES :::: */
+
+div.actions {
+ border-top: 1px solid #aaa;
+ background-color: #ddd;
+ margin: 10px 0 0 -20px;
+ padding: 5px 0 5px 20px;
+}
+
+form dl {
+ color: #333;
+}
+
+form dt {
+ clear: both;
+ float: left;
+ min-width: 110px;
+ margin-right: 10px;
+ padding-top: 2px;
+}
+
+input#homepage {
+ display: none;
+}
+
+div.error {
+ margin: 5px 20px 0 0;
+ padding: 5px;
+ border: 1px solid #d00;
+ /*border: 2px solid #05171e;
+ background-color: #092835;
+ color: white;*/
+ font-weight: bold;
+}
+
+/* :::: INLINE COMMENTS :::: */
+
+div.inlinecommentswrapper {
+ float: right;
+ max-width: 40%;
+}
+
+div.commentmarker {
+ float: right;
+ background-image: url(style/comment.png);
+ background-repeat: no-repeat;
+ width: 25px;
+ height: 25px;
+ text-align: center;
+ padding-top: 3px;
+}
+
+div.nocommentmarker {
+ float: right;
+ background-image: url(style/nocomment.png);
+ background-repeat: no-repeat;
+ width: 25px;
+ height: 25px;
+}
+
+div.inlinecomments {
+ margin-left: 10px;
+ margin-bottom: 5px;
+ background-color: #eee;
+ border: 1px solid #ccc;
+ padding: 5px;
+}
+
+div.inlinecomment {
+ border-top: 1px solid #ccc;
+ padding-top: 5px;
+ margin-top: 5px;
+}
+
+.inlinecomments p {
+ margin: 5px 0 5px 0;
+}
+
+.inlinecomments .head {
+ font-weight: bold;
+}
+
+.inlinecomments .meta {
+ font-style: italic;
+}
+
+
+/* :::: COMMENTS :::: */
+
+div#comments h3 {
+ border-top: 1px solid #aaa;
+ padding: 5px 20px 5px 20px;
+ margin: 20px -20px 20px -20px;
+ background-color: #ddd;
+}
+
+/*
+div#comments {
+ background-color: #ccc;
+ margin: 40px -20px -30px -20px;
+ padding: 0 0 1px 0;
+}
+
+div#comments h4 {
+ margin: 30px 0 20px 0;
+ background-color: #aaa;
+ border-bottom: 1px solid #09232e;
+ color: #333;
+}
+
+div#comments form {
+ display: block;
+ margin: 0 0 0 20px;
+}
+
+div#comments textarea {
+ width: 98%;
+ height: 160px;
+}
+
+div#comments div.help {
+ margin: 20px 20px 10px 0;
+ background-color: #ccc;
+ color: #333;
+}
+
+div#comments div.help p {
+ margin: 0;
+ padding: 0 0 10px 0;
+}
+
+div#comments input, div#comments textarea {
+ font-family: 'Bitstream Vera Sans', 'Arial', sans-serif;
+ font-size: 13px;
+ color: black;
+ background-color: #aaa;
+ border: 1px solid #092835;
+}
+
+div#comments input[type="reset"],
+div#comments input[type="submit"] {
+ cursor: pointer;
+ font-weight: bold;
+ padding: 2px;
+ margin: 5px 5px 5px 0;
+ background-color: #666;
+ color: white;
+}
+
+div#comments div.comment {
+ margin: 10px 10px 10px 20px;
+ padding: 10px;
+ border: 1px solid #0f3646;
+ background-color: #aaa;
+ color: #333;
+}
+
+div#comments div.comment p {
+ margin: 5px 0 5px 0;
+}
+
+div#comments div.comment p.meta {
+ font-style: italic;
+ color: #444;
+ text-align: right;
+ margin: -5px 0 -5px 0;
+}
+
+div#comments div.comment h4 {
+ margin: -10px -10px 5px -10px;
+ padding: 3px;
+ font-size: 15px;
+ background-color: #888;
+ color: white;
+ border: 0;
+}
+
+div#comments div.comment pre,
+div#comments div.comment tt {
+ background-color: #ddd;
+ color: #111;
+ border: none;
+}
+
+div#comments div.comment a {
+ color: #fff;
+ text-decoration: underline;
+}
+
+div#comments div.comment blockquote {
+ margin: 10px;
+ padding: 10px;
+ border-left: 1px solid #0f3646;
+ /*border: 1px solid #0f3646;
+ background-color: #071c25;*/
+}
+
+div#comments em.important {
+ color: #d00;
+ font-weight: bold;
+ font-style: normal;
+}*/
+
+/* :::: SUGGEST CHANGES :::: */
+div#suggest-changes-box input, div#suggest-changes-box textarea {
+ border: 1px solid #ccc;
+ background-color: white;
+ color: black;
+}
+
+div#suggest-changes-box textarea {
+ width: 99%;
+ height: 400px;
+}
+
+
+/* :::: PREVIEW :::: */
+div.preview {
+ background-image: url(style/preview.png);
+ padding: 0 20px 20px 20px;
+ margin-bottom: 30px;
+}
+
+
+/* :::: INDEX PAGE :::: */
+
+table.contentstable {
+ width: 90%;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 1.5em;
+}
+
+span.linkdescr {
+ font-style: italic;
+ padding-top: 5px;
+}
+
+/* :::: GENINDEX STYLES :::: */
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+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;
+}
+
+/* :::: GLOBAL STYLES :::: */
+
+p.subhead {
+ font-weight: bold;
+ margin-top: 20px;
+}
+
+a:link:active { color: #ff0000; }
+a:link:hover { background-color: #bbeeff; }
+a:visited:hover { background-color: #bbeeff; }
+a:visited { color: #551a8b; }
+a:link { color: #0000bb; }
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: avantgarde, sans-serif;
+ font-weight: bold;
+}
+
+div.body h1 { font-size: 180%; }
+div.body h2 { font-size: 150%; }
+div.body h3 { font-size: 120%; }
+div.body h4 { font-size: 120%; }
+
+a.headerlink,
+a.headerlink,
+a.headerlink,
+a.headerlink,
+a.headerlink,
+a.headerlink {
+ color: #c60f0f;
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+ visibility: hidden;
+}
+
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink {
+ visibility: visible;
+}
+
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover {
+ background-color: #c60f0f;
+ color: white;
+}
+
+div.body p, div.body dd, div.body li {
+ text-align: justify;
+}
+
+div.body td {
+ text-align: left;
+}
+
+ul.fakelist {
+ list-style: none;
+ margin: 10px 0 10px 20px;
+ padding: 0;
+}
+
+/* "Footnotes" heading */
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+/* "Topics" */
+
+div.topic {
+ background-color: #eee;
+ border: 1px solid #ccc;
+ padding: 0 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 dd {
+ margin-bottom: 10px;
+}
+
+div.admonition dl {
+ margin-bottom: 0;
+}
+
+div.admonition p {
+ display: inline;
+}
+
+div.seealso {
+ background-color: #ffc;
+ border: 1px solid #ff6;
+}
+
+div.warning {
+ background-color: #ffe4e4;
+ border: 1px solid #f66;
+}
+
+div.note {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+ display: inline;
+}
+
+p.admonition-title:after {
+ content: ":";
+}
+
+div.body p.centered {
+ text-align: center;
+ margin-top: 25px;
+}
+
+table.docutils {
+ border: 0;
+}
+
+table.docutils td, table.docutils th {
+ padding: 0 8px 2px 0;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid #aaa;
+}
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+table.footnote td, table.footnote th {
+ border: 0 !important;
+}
+
+dl {
+ margin-bottom: 15px;
+ clear: both;
+}
+
+dd p {
+ margin-top: 0px;
+}
+
+dd ul, dd table {
+ margin-bottom: 10px;
+}
+
+dd {
+ margin-top: 3px;
+ margin-bottom: 10px;
+ margin-left: 30px;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+th {
+ text-align: left;
+ padding-right: 5px;
+}
+
+pre {
+ font-family: monospace;
+ padding: 5px;
+ color: #00008b;
+ border-left: none;
+ border-right: none;
+}
+
+tt {
+ font-family: monospace;
+ background-color: #ecf0f3;
+ padding: 0 1px 0 1px;
+}
+
+tt.descname {
+ background-color: transparent;
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+tt.descclassname {
+ background-color: transparent;
+}
+
+tt.xref, a tt {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+.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;
+}
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+ background-color: transparent;
+}
+
+.optional {
+ font-size: 1.3em;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+/* :::: PRINT :::: */
+ at media print {
+ div.documentwrapper {
+ width: 100%;
+ }
+
+ div.body {
+ margin: 0;
+ }
+
+ div.sphinxsidebar,
+ div.related,
+ div.footer,
+ div#comments div.new-comment-box,
+ #top-link {
+ display: none;
+ }
+}
+
+.viewcode-link {
+ float: right;
+}
+
+.viewcode-back {
+ float: right;
+ font-family: serif;
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+ margin: -1px -10px;
+ padding: 0 10px;
+}
diff --git a/sphinx/themes/traditional/theme.conf b/sphinx/themes/traditional/theme.conf
new file mode 100644
index 0000000..02b7783
--- /dev/null
+++ b/sphinx/themes/traditional/theme.conf
@@ -0,0 +1,3 @@
+[theme]
+inherit = basic
+stylesheet = traditional.css
diff --git a/sphinx/theming.py b/sphinx/theming.py
new file mode 100644
index 0000000..abc09c1
--- /dev/null
+++ b/sphinx/theming.py
@@ -0,0 +1,197 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.theming
+ ~~~~~~~~~~~~~~
+
+ Theming support for HTML builders.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import shutil
+import zipfile
+import tempfile
+import ConfigParser
+from os import path
+
+try:
+ import pkg_resources
+except ImportError:
+ pkg_resources = False
+
+from sphinx import package_dir
+from sphinx.errors import ThemeError
+
+
+NODEFAULT = object()
+THEMECONF = 'theme.conf'
+
+class Theme(object):
+ """
+ Represents the theme chosen in the configuration.
+ """
+ themes = {}
+
+ @classmethod
+ def init_themes(cls, confdir, theme_path, warn=None):
+ """Search all theme paths for available themes."""
+ cls.themepath = list(theme_path)
+ cls.themepath.append(path.join(package_dir, 'themes'))
+
+ for themedir in cls.themepath[::-1]:
+ themedir = path.join(confdir, themedir)
+ if not path.isdir(themedir):
+ continue
+ for theme in os.listdir(themedir):
+ if theme.lower().endswith('.zip'):
+ try:
+ zfile = zipfile.ZipFile(path.join(themedir, theme))
+ if THEMECONF not in zfile.namelist():
+ continue
+ tname = theme[:-4]
+ tinfo = zfile
+ except Exception:
+ if warn:
+ warn('file %r on theme path is not a valid '
+ 'zipfile or contains no theme' % theme)
+ continue
+ else:
+ if not path.isfile(path.join(themedir, theme, THEMECONF)):
+ continue
+ tname = theme
+ tinfo = None
+ cls.themes[tname] = (path.join(themedir, theme), tinfo)
+
+ @classmethod
+ def load_extra_themes(cls):
+ for themedir in load_theme_plugins():
+ if not path.isdir(themedir):
+ continue
+ for theme in os.listdir(themedir):
+ if not path.isfile(path.join(themedir, theme, THEMECONF)):
+ continue
+ cls.themes[theme] = (path.join(themedir, theme), None)
+
+ def __init__(self, name):
+ if name not in self.themes:
+ self.load_extra_themes()
+ if name not in self.themes:
+ raise ThemeError('no theme named %r found '
+ '(missing theme.conf?)' % name)
+ self.name = name
+
+ tdir, tinfo = self.themes[name]
+ if tinfo is None:
+ # already a directory, do nothing
+ self.themedir = tdir
+ self.themedir_created = False
+ else:
+ # extract the theme to a temp directory
+ self.themedir = tempfile.mkdtemp('sxt')
+ self.themedir_created = True
+ for name in tinfo.namelist():
+ if name.endswith('/'): continue
+ dirname = path.dirname(name)
+ if not path.isdir(path.join(self.themedir, dirname)):
+ os.makedirs(path.join(self.themedir, dirname))
+ fp = open(path.join(self.themedir, name), 'wb')
+ fp.write(tinfo.read(name))
+ fp.close()
+
+ self.themeconf = ConfigParser.RawConfigParser()
+ self.themeconf.read(path.join(self.themedir, THEMECONF))
+
+ try:
+ inherit = self.themeconf.get('theme', 'inherit')
+ except ConfigParser.NoOptionError:
+ raise ThemeError('theme %r doesn\'t have "inherit" setting' % name)
+ if inherit == 'none':
+ self.base = None
+ elif inherit not in self.themes:
+ raise ThemeError('no theme named %r found, inherited by %r' %
+ (inherit, name))
+ else:
+ self.base = Theme(inherit)
+
+ def get_confstr(self, section, name, default=NODEFAULT):
+ """Return the value for a theme configuration setting, searching the
+ base theme chain.
+ """
+ try:
+ return self.themeconf.get(section, name)
+ except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
+ if self.base is not None:
+ return self.base.get_confstr(section, name, default)
+ if default is NODEFAULT:
+ raise ThemeError('setting %s.%s occurs in none of the '
+ 'searched theme configs' % (section, name))
+ else:
+ return default
+
+ def get_options(self, overrides):
+ """Return a dictionary of theme options and their values."""
+ chain = [self.themeconf]
+ base = self.base
+ while base is not None:
+ chain.append(base.themeconf)
+ base = base.base
+ options = {}
+ for conf in reversed(chain):
+ try:
+ options.update(conf.items('options'))
+ except ConfigParser.NoSectionError:
+ pass
+ for option, value in overrides.iteritems():
+ if option not in options:
+ raise ThemeError('unsupported theme option %r given' % option)
+ options[option] = value
+ return options
+
+ def get_dirchain(self):
+ """Return a list of theme directories, beginning with this theme's,
+ then the base theme's, then that one's base theme's, etc.
+ """
+ chain = [self.themedir]
+ base = self.base
+ while base is not None:
+ chain.append(base.themedir)
+ base = base.base
+ return chain
+
+ def cleanup(self):
+ """Remove temporary directories."""
+ if self.themedir_created:
+ try:
+ shutil.rmtree(self.themedir)
+ except Exception:
+ pass
+ if self.base:
+ self.base.cleanup()
+
+
+def load_theme_plugins():
+ """load plugins by using``sphinx_themes`` section in setuptools entry_points.
+ This API will return list of directory that contain some theme directory.
+ """
+
+ if not pkg_resources:
+ return []
+
+ theme_paths = []
+
+ for plugin in pkg_resources.iter_entry_points('sphinx_themes'):
+ func_or_path = plugin.load()
+ try:
+ path = func_or_path()
+ except:
+ path = func_or_path
+
+ if isinstance(path, basestring):
+ theme_paths.append(path)
+ else:
+ raise ThemeError('Plugin %r does not response correctly.' %
+ plugin.module_name)
+
+ return theme_paths
diff --git a/sphinx/transforms.py b/sphinx/transforms.py
new file mode 100644
index 0000000..0e103ac
--- /dev/null
+++ b/sphinx/transforms.py
@@ -0,0 +1,490 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.transforms
+ ~~~~~~~~~~~~~~~~~
+
+ Docutils transforms used by Sphinx when reading documents.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from os import path
+
+from docutils import nodes
+from docutils.utils import new_document, relative_path
+from docutils.parsers.rst import Parser as RSTParser
+from docutils.transforms import Transform
+from docutils.transforms.parts import ContentsFilter
+
+from sphinx import addnodes
+from sphinx.locale import _, init as init_locale
+from sphinx.util import split_index_msg
+from sphinx.util.nodes import traverse_translatable_index, extract_messages
+from sphinx.util.osutil import ustrftime, find_catalog
+from sphinx.util.compat import docutils_version
+from sphinx.util.pycompat import all
+from sphinx.domains.std import (
+ make_term_from_paragraph_node,
+ make_termnodes_from_paragraph_node,
+)
+
+
+default_substitutions = set([
+ 'version',
+ 'release',
+ 'today',
+])
+
+class DefaultSubstitutions(Transform):
+ """
+ Replace some substitutions if they aren't defined in the document.
+ """
+ # run before the default Substitutions
+ default_priority = 210
+
+ def apply(self):
+ config = self.document.settings.env.config
+ # only handle those not otherwise defined in the document
+ to_handle = default_substitutions - set(self.document.substitution_defs)
+ for ref in self.document.traverse(nodes.substitution_reference):
+ refname = ref['refname']
+ if refname in to_handle:
+ text = config[refname]
+ if refname == 'today' and not text:
+ # special handling: can also specify a strftime format
+ text = ustrftime(config.today_fmt or _('%B %d, %Y'))
+ ref.replace_self(nodes.Text(text, text))
+
+
+class MoveModuleTargets(Transform):
+ """
+ Move module targets that are the first thing in a section to the section
+ title.
+
+ XXX Python specific
+ """
+ default_priority = 210
+
+ def apply(self):
+ for node in self.document.traverse(nodes.target):
+ if not node['ids']:
+ continue
+ if (node.has_key('ismod') and
+ node.parent.__class__ is nodes.section and
+ # index 0 is the section title node
+ node.parent.index(node) == 1):
+ node.parent['ids'][0:0] = node['ids']
+ node.parent.remove(node)
+
+
+class HandleCodeBlocks(Transform):
+ """
+ Several code block related transformations.
+ """
+ default_priority = 210
+
+ def apply(self):
+ # move doctest blocks out of blockquotes
+ for node in self.document.traverse(nodes.block_quote):
+ if all(isinstance(child, nodes.doctest_block) for child
+ in node.children):
+ node.replace_self(node.children)
+ # combine successive doctest blocks
+ #for node in self.document.traverse(nodes.doctest_block):
+ # if node not in node.parent.children:
+ # continue
+ # parindex = node.parent.index(node)
+ # while len(node.parent) > parindex+1 and \
+ # isinstance(node.parent[parindex+1], nodes.doctest_block):
+ # node[0] = nodes.Text(node[0] + '\n\n' +
+ # node.parent[parindex+1][0])
+ # del node.parent[parindex+1]
+
+
+class SortIds(Transform):
+ """
+ Sort secion IDs so that the "id[0-9]+" one comes last.
+ """
+ default_priority = 261
+
+ def apply(self):
+ for node in self.document.traverse(nodes.section):
+ if len(node['ids']) > 1 and node['ids'][0].startswith('id'):
+ node['ids'] = node['ids'][1:] + [node['ids'][0]]
+
+
+class CitationReferences(Transform):
+ """
+ Replace citation references by pending_xref nodes before the default
+ docutils transform tries to resolve them.
+ """
+ default_priority = 619
+
+ def apply(self):
+ for citnode in self.document.traverse(nodes.citation_reference):
+ cittext = citnode.astext()
+ refnode = addnodes.pending_xref(cittext, reftype='citation',
+ reftarget=cittext, refwarn=True,
+ ids=citnode["ids"])
+ refnode.line = citnode.line or citnode.parent.line
+ refnode += nodes.Text('[' + cittext + ']')
+ citnode.parent.replace(citnode, refnode)
+
+
+class CustomLocaleReporter(object):
+ """
+ Replacer for document.reporter.get_source_and_line method.
+
+ reST text lines for translation do not have the original source line number.
+ This class provides the correct line numbers when reporting.
+ """
+ def __init__(self, source, line):
+ self.source, self.line = source, line
+
+ def set_reporter(self, document):
+ if docutils_version < (0, 9):
+ document.reporter.locator = self.get_source_and_line
+ else:
+ document.reporter.get_source_and_line = self.get_source_and_line
+
+ def get_source_and_line(self, lineno=None):
+ return self.source, self.line
+
+
+class Locale(Transform):
+ """
+ Replace translatable nodes with their translated doctree.
+ """
+ default_priority = 0
+
+ def apply(self):
+ env = self.document.settings.env
+ settings, source = self.document.settings, self.document['source']
+ # XXX check if this is reliable
+ assert source.startswith(env.srcdir)
+ docname = path.splitext(relative_path(path.join(env.srcdir, 'dummy'),
+ source))[0]
+ textdomain = find_catalog(docname,
+ self.document.settings.gettext_compact)
+
+ # fetch translations
+ dirs = [path.join(env.srcdir, directory)
+ for directory in env.config.locale_dirs]
+ catalog, has_catalog = init_locale(dirs, env.config.language,
+ textdomain)
+ if not has_catalog:
+ return
+
+ parser = RSTParser()
+
+ #phase1: replace reference ids with translated names
+ for node, msg in extract_messages(self.document):
+ msgstr = catalog.gettext(msg)
+ # XXX add marker to untranslated parts
+ if not msgstr or msgstr == msg or not msgstr.strip():
+ # as-of-yet untranslated
+ continue
+
+ # Avoid "Literal block expected; none found." warnings.
+ # If msgstr ends with '::' then it cause warning message at
+ # parser.parse() processing.
+ # literal-block-warning is only appear in avobe case.
+ if msgstr.strip().endswith('::'):
+ msgstr += '\n\n dummy literal'
+ # dummy literal node will discard by 'patch = patch[0]'
+
+ patch = new_document(source, settings)
+ CustomLocaleReporter(node.source, node.line).set_reporter(patch)
+ parser.parse(msgstr, patch)
+ try:
+ patch = patch[0]
+ except IndexError: # empty node
+ pass
+ # XXX doctest and other block markup
+ if not isinstance(patch, nodes.paragraph):
+ continue # skip for now
+
+ processed = False # skip flag
+
+ # update title(section) target name-id mapping
+ if isinstance(node, nodes.title):
+ section_node = node.parent
+ new_name = nodes.fully_normalize_name(patch.astext())
+ old_name = nodes.fully_normalize_name(node.astext())
+
+ if old_name != new_name:
+ # if name would be changed, replace node names and
+ # document nameids mapping with new name.
+ names = section_node.setdefault('names', [])
+ names.append(new_name)
+ if old_name in names:
+ names.remove(old_name)
+
+ _id = self.document.nameids.get(old_name, None)
+ explicit = self.document.nametypes.get(old_name, None)
+
+ # * if explicit: _id is label. title node need another id.
+ # * if not explicit:
+ #
+ # * _id is None:
+ #
+ # _id is None means _id was duplicated.
+ # old_name entry still exists in nameids and
+ # nametypes for another duplicated entry.
+ #
+ # * _id is provided: bellow process
+ if not explicit and _id:
+ # _id was not duplicated.
+ # remove old_name entry from document ids database
+ # to reuse original _id.
+ self.document.nameids.pop(old_name, None)
+ self.document.nametypes.pop(old_name, None)
+ self.document.ids.pop(_id, None)
+
+ # re-entry with new named section node.
+ #
+ # Note: msgnode that is a second parameter of the
+ # `note_implicit_target` is not necessary here because
+ # section_node has been noted previously on rst parsing by
+ # `docutils.parsers.rst.states.RSTState.new_subsection()`
+ # and already has `system_message` if needed.
+ self.document.note_implicit_target(section_node)
+
+ # replace target's refname to new target name
+ def is_named_target(node):
+ return isinstance(node, nodes.target) and \
+ node.get('refname') == old_name
+ for old_target in self.document.traverse(is_named_target):
+ old_target['refname'] = new_name
+
+ processed = True
+
+ # glossary terms update refid
+ if isinstance(node, nodes.term):
+ gloss_entries = env.temp_data.setdefault('gloss_entries', set())
+ ids = []
+ termnodes = []
+ for _id in node['names']:
+ if _id in gloss_entries:
+ gloss_entries.remove(_id)
+ _id, _, new_termnodes = \
+ make_termnodes_from_paragraph_node(env, patch, _id)
+ ids.append(_id)
+ termnodes.extend(new_termnodes)
+
+ if termnodes and ids:
+ patch = make_term_from_paragraph_node(termnodes, ids)
+ node['ids'] = patch['ids']
+ node['names'] = patch['names']
+ processed = True
+
+ # update leaves with processed nodes
+ if processed:
+ for child in patch.children:
+ child.parent = node
+ node.children = patch.children
+ node['translated'] = True
+
+
+ #phase2: translation
+ for node, msg in extract_messages(self.document):
+ if node.get('translated', False):
+ continue
+
+ msgstr = catalog.gettext(msg)
+ # XXX add marker to untranslated parts
+ if not msgstr or msgstr == msg: # as-of-yet untranslated
+ continue
+
+ # Avoid "Literal block expected; none found." warnings.
+ # If msgstr ends with '::' then it cause warning message at
+ # parser.parse() processing.
+ # literal-block-warning is only appear in avobe case.
+ if msgstr.strip().endswith('::'):
+ msgstr += '\n\n dummy literal'
+ # dummy literal node will discard by 'patch = patch[0]'
+
+ patch = new_document(source, settings)
+ CustomLocaleReporter(node.source, node.line).set_reporter(patch)
+ parser.parse(msgstr, patch)
+ try:
+ patch = patch[0]
+ except IndexError: # empty node
+ pass
+ # XXX doctest and other block markup
+ if not isinstance(patch, nodes.paragraph):
+ continue # skip for now
+
+ # auto-numbered foot note reference should use original 'ids'.
+ def is_autonumber_footnote_ref(node):
+ return isinstance(node, nodes.footnote_reference) and \
+ node.get('auto') == 1
+ def list_replace_or_append(lst, old, new):
+ if old in lst:
+ lst[lst.index(old)] = new
+ else:
+ lst.append(new)
+ old_foot_refs = node.traverse(is_autonumber_footnote_ref)
+ new_foot_refs = patch.traverse(is_autonumber_footnote_ref)
+ if len(old_foot_refs) != len(new_foot_refs):
+ env.warn_node('inconsistent footnote references in '
+ 'translated message', node)
+ old_foot_namerefs = {}
+ for r in old_foot_refs:
+ old_foot_namerefs.setdefault(r.get('refname'), []).append(r)
+ for new in new_foot_refs:
+ refname = new.get('refname')
+ refs = old_foot_namerefs.get(refname, [])
+ if not refs:
+ continue
+
+ old = refs.pop(0)
+ new['ids'] = old['ids']
+ for id in new['ids']:
+ self.document.ids[id] = new
+ list_replace_or_append(
+ self.document.autofootnote_refs, old, new)
+ if refname:
+ list_replace_or_append(
+ self.document.footnote_refs.setdefault(refname, []),
+ old, new)
+ list_replace_or_append(
+ self.document.refnames.setdefault(refname, []),
+ old, new)
+
+ # reference should use new (translated) 'refname'.
+ # * reference target ".. _Python: ..." is not translatable.
+ # * use translated refname for section refname.
+ # * inline reference "`Python <...>`_" has no 'refname'.
+ def is_refnamed_ref(node):
+ return isinstance(node, nodes.reference) and \
+ 'refname' in node
+ old_refs = node.traverse(is_refnamed_ref)
+ new_refs = patch.traverse(is_refnamed_ref)
+ if len(old_refs) != len(new_refs):
+ env.warn_node('inconsistent references in '
+ 'translated message', node)
+ old_ref_names = [r['refname'] for r in old_refs]
+ new_ref_names = [r['refname'] for r in new_refs]
+ orphans = list(set(old_ref_names) - set(new_ref_names))
+ for new in new_refs:
+ if not self.document.has_name(new['refname']):
+ # Maybe refname is translated but target is not translated.
+ # Note: multiple translated refnames break link ordering.
+ if orphans:
+ new['refname'] = orphans.pop(0)
+ else:
+ # orphan refnames is already empty!
+ # reference number is same in new_refs and old_refs.
+ pass
+
+ self.document.note_refname(new)
+
+ # refnamed footnote and citation should use original 'ids'.
+ def is_refnamed_footnote_ref(node):
+ footnote_ref_classes = (nodes.footnote_reference,
+ nodes.citation_reference)
+ return isinstance(node, footnote_ref_classes) and \
+ 'refname' in node
+ old_refs = node.traverse(is_refnamed_footnote_ref)
+ new_refs = patch.traverse(is_refnamed_footnote_ref)
+ refname_ids_map = {}
+ if len(old_refs) != len(new_refs):
+ env.warn_node('inconsistent references in '
+ 'translated message', node)
+ for old in old_refs:
+ refname_ids_map[old["refname"]] = old["ids"]
+ for new in new_refs:
+ refname = new["refname"]
+ if refname in refname_ids_map:
+ new["ids"] = refname_ids_map[refname]
+
+ # Original pending_xref['reftarget'] contain not-translated
+ # target name, new pending_xref must use original one.
+ # This code restricts to change ref-targets in the translation.
+ old_refs = node.traverse(addnodes.pending_xref)
+ new_refs = patch.traverse(addnodes.pending_xref)
+ xref_reftarget_map = {}
+ if len(old_refs) != len(new_refs):
+ env.warn_node('inconsistent term references in '
+ 'translated message', node)
+ def get_ref_key(node):
+ case = node["refdomain"], node["reftype"]
+ if case == ('std', 'term'):
+ return None
+ else:
+ return (
+ node["refdomain"],
+ node["reftype"],
+ node['reftarget'],)
+
+ for old in old_refs:
+ key = get_ref_key(old)
+ if key:
+ xref_reftarget_map[key] = old.attributes
+ for new in new_refs:
+ key = get_ref_key(new)
+ # Copy attributes to keep original node behavior. Especially
+ # copying 'reftarget', 'py:module', 'py:class' are needed.
+ for k, v in xref_reftarget_map.get(key, {}).items():
+ # Note: This implementation overwrite all attributes.
+ # if some attributes `k` should not be overwritten,
+ # you should provide exclude list as:
+ # `if k not in EXCLUDE_LIST: new[k] = v`
+ new[k] = v
+
+ # update leaves
+ for child in patch.children:
+ child.parent = node
+ node.children = patch.children
+ node['translated'] = True
+
+ # Extract and translate messages for index entries.
+ for node, entries in traverse_translatable_index(self.document):
+ new_entries = []
+ for type, msg, tid, main in entries:
+ msg_parts = split_index_msg(type, msg)
+ msgstr_parts = []
+ for part in msg_parts:
+ msgstr = catalog.gettext(part)
+ if not msgstr:
+ msgstr = part
+ msgstr_parts.append(msgstr)
+
+ new_entries.append((type, ';'.join(msgstr_parts), tid, main))
+
+ node['raw_entries'] = entries
+ node['entries'] = new_entries
+
+
+class RemoveTranslatableInline(Transform):
+ """
+ Remove inline nodes used for translation as placeholders.
+ """
+ default_priority = 999
+
+ def apply(self):
+ from sphinx.builders.gettext import MessageCatalogBuilder
+ env = self.document.settings.env
+ builder = env.app.builder
+ if isinstance(builder, MessageCatalogBuilder):
+ return
+ for inline in self.document.traverse(nodes.inline):
+ if 'translatable' in inline:
+ inline.parent.remove(inline)
+ inline.parent += inline.children
+
+
+class SphinxContentsFilter(ContentsFilter):
+ """
+ Used with BuildEnvironment.add_toc_from() to discard cross-file links
+ within table-of-contents link nodes.
+ """
+ def visit_pending_xref(self, node):
+ text = node.astext()
+ self.parent.append(nodes.literal(text, text))
+ raise nodes.SkipNode
+
+ def visit_image(self, node):
+ raise nodes.SkipNode
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
new file mode 100644
index 0000000..cf3ae32
--- /dev/null
+++ b/sphinx/util/__init__.py
@@ -0,0 +1,439 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util
+ ~~~~~~~~~~~
+
+ Utility functions for Sphinx.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import sys
+import shutil
+import fnmatch
+import tempfile
+import posixpath
+import traceback
+import unicodedata
+from os import path
+from codecs import open, BOM_UTF8
+from collections import deque
+
+import docutils
+from docutils.utils import relative_path
+
+import jinja2
+
+import sphinx
+from sphinx.errors import PycodeError
+from sphinx.util.pycompat import bytes
+
+# import other utilities; partly for backwards compatibility, so don't
+# prune unused ones indiscriminately
+from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, walk, \
+ mtimes_of_files, movefile, copyfile, copytimes, make_filename, ustrftime
+from sphinx.util.nodes import nested_parse_with_titles, split_explicit_title, \
+ explicit_title_re, caption_ref_re
+from sphinx.util.matching import patfilter
+
+# Generally useful regular expressions.
+ws_re = re.compile(r'\s+')
+url_re = re.compile(r'(?P<schema>.+)://.*')
+
+
+# High-level utility functions.
+
+def docname_join(basedocname, docname):
+ return posixpath.normpath(
+ posixpath.join('/' + basedocname, '..', docname))[1:]
+
+
+def path_stabilize(filepath):
+ "normalize path separater and unicode string"
+ newpath = filepath.replace(os.path.sep, SEP)
+ if isinstance(newpath, unicode):
+ newpath = unicodedata.normalize('NFC', newpath)
+ return newpath
+
+
+def get_matching_files(dirname, exclude_matchers=()):
+ """Get all file names in a directory, recursively.
+
+ Exclude files and dirs matching some matcher in *exclude_matchers*.
+ """
+ # dirname is a normalized absolute path.
+ dirname = path.normpath(path.abspath(dirname))
+ dirlen = len(dirname) + 1 # exclude final os.path.sep
+
+ for root, dirs, files in walk(dirname, followlinks=True):
+ relativeroot = root[dirlen:]
+
+ qdirs = enumerate(path_stabilize(path.join(relativeroot, dn))
+ for dn in dirs)
+ qfiles = enumerate(path_stabilize(path.join(relativeroot, fn))
+ for fn in files)
+ for matcher in exclude_matchers:
+ qdirs = [entry for entry in qdirs if not matcher(entry[1])]
+ qfiles = [entry for entry in qfiles if not matcher(entry[1])]
+
+ dirs[:] = sorted(dirs[i] for (i, _) in qdirs)
+
+ for i, filename in sorted(qfiles):
+ yield filename
+
+
+def get_matching_docs(dirname, suffix, exclude_matchers=()):
+ """Get all file names (without suffix) matching a suffix in a directory,
+ recursively.
+
+ Exclude files and dirs matching a pattern in *exclude_patterns*.
+ """
+ suffixpattern = '*' + suffix
+ for filename in get_matching_files(dirname, exclude_matchers):
+ if not fnmatch.fnmatch(filename, suffixpattern):
+ continue
+ yield filename[:-len(suffix)]
+
+
+class FilenameUniqDict(dict):
+ """
+ A dictionary that automatically generates unique names for its keys,
+ interpreted as filenames, and keeps track of a set of docnames they
+ appear in. Used for images and downloadable files in the environment.
+ """
+ def __init__(self):
+ self._existing = set()
+
+ def add_file(self, docname, newfile):
+ if newfile in self:
+ self[newfile][0].add(docname)
+ return self[newfile][1]
+ uniquename = path.basename(newfile)
+ base, ext = path.splitext(uniquename)
+ i = 0
+ while uniquename in self._existing:
+ i += 1
+ uniquename = '%s%s%s' % (base, i, ext)
+ self[newfile] = (set([docname]), uniquename)
+ self._existing.add(uniquename)
+ return uniquename
+
+ def purge_doc(self, docname):
+ for filename, (docs, unique) in self.items():
+ docs.discard(docname)
+ if not docs:
+ del self[filename]
+ self._existing.discard(unique)
+
+ def __getstate__(self):
+ return self._existing
+
+ def __setstate__(self, state):
+ self._existing = state
+
+
+def copy_static_entry(source, targetdir, builder, context={},
+ exclude_matchers=(), level=0):
+ """Copy a HTML builder static_path entry from source to targetdir.
+
+ Handles all possible cases of files, directories and subdirectories.
+ """
+ if exclude_matchers:
+ relpath = relative_path(path.join(builder.srcdir, 'dummy'), source)
+ for matcher in exclude_matchers:
+ if matcher(relpath):
+ return
+ if path.isfile(source):
+ target = path.join(targetdir, path.basename(source))
+ if source.lower().endswith('_t') and builder.templates:
+ # templated!
+ fsrc = open(source, 'r', encoding='utf-8')
+ fdst = open(target[:-2], 'w', encoding='utf-8')
+ fdst.write(builder.templates.render_string(fsrc.read(), context))
+ fsrc.close()
+ fdst.close()
+ else:
+ copyfile(source, target)
+ elif path.isdir(source):
+ if not path.isdir(targetdir):
+ os.mkdir(targetdir)
+ for entry in os.listdir(source):
+ if entry.startswith('.'):
+ continue
+ newtarget = targetdir
+ if path.isdir(path.join(source, entry)):
+ newtarget = path.join(targetdir, entry)
+ copy_static_entry(path.join(source, entry), newtarget,
+ builder, context, level=level+1,
+ exclude_matchers=exclude_matchers)
+
+
+_DEBUG_HEADER = '''\
+# Sphinx version: %s
+# Python version: %s
+# Docutils version: %s %s
+# Jinja2 version: %s
+# Loaded extensions:
+'''
+
+def save_traceback(app):
+ """Save the current exception's traceback in a temporary file."""
+ import platform
+ exc = traceback.format_exc()
+ fd, path = tempfile.mkstemp('.log', 'sphinx-err-')
+ os.write(fd, (_DEBUG_HEADER %
+ (sphinx.__version__,
+ platform.python_version(),
+ docutils.__version__, docutils.__version_details__,
+ jinja2.__version__)).encode('utf-8'))
+ if app is not None:
+ for extname, extmod in app._extensions.iteritems():
+ os.write(fd, ('# %s from %s\n' % (
+ extname, getattr(extmod, '__file__', 'unknown'))
+ ).encode('utf-8'))
+ os.write(fd, exc.encode('utf-8'))
+ os.close(fd)
+ return path
+
+
+def get_module_source(modname):
+ """Try to find the source code for a module.
+
+ Can return ('file', 'filename') in which case the source is in the given
+ file, or ('string', 'source') which which case the source is the string.
+ """
+ if modname not in sys.modules:
+ try:
+ __import__(modname)
+ except Exception, err:
+ raise PycodeError('error importing %r' % modname, err)
+ mod = sys.modules[modname]
+ filename = getattr(mod, '__file__', None)
+ loader = getattr(mod, '__loader__', None)
+ if loader and getattr(loader, 'get_filename', None):
+ try:
+ filename = loader.get_filename(modname)
+ except Exception, err:
+ raise PycodeError('error getting filename for %r' % filename, err)
+ if filename is None and loader:
+ try:
+ return 'string', loader.get_source(modname)
+ except Exception, err:
+ raise PycodeError('error getting source for %r' % modname, err)
+ if filename is None:
+ raise PycodeError('no source found for module %r' % modname)
+ filename = path.normpath(path.abspath(filename))
+ lfilename = filename.lower()
+ if lfilename.endswith('.pyo') or lfilename.endswith('.pyc'):
+ filename = filename[:-1]
+ if not path.isfile(filename) and path.isfile(filename + 'w'):
+ filename += 'w'
+ elif not (lfilename.endswith('.py') or lfilename.endswith('.pyw')):
+ raise PycodeError('source is not a .py file: %r' % filename)
+ if not path.isfile(filename):
+ raise PycodeError('source file is not present: %r' % filename)
+ return 'file', filename
+
+
+# a regex to recognize coding cookies
+_coding_re = re.compile(r'coding[:=]\s*([-\w.]+)')
+
+def detect_encoding(readline):
+ """Like tokenize.detect_encoding() from Py3k, but a bit simplified."""
+
+ def read_or_stop():
+ try:
+ return readline()
+ except StopIteration:
+ return None
+
+ def get_normal_name(orig_enc):
+ """Imitates get_normal_name in tokenizer.c."""
+ # Only care about the first 12 characters.
+ enc = orig_enc[:12].lower().replace('_', '-')
+ if enc == 'utf-8' or enc.startswith('utf-8-'):
+ return 'utf-8'
+ if enc in ('latin-1', 'iso-8859-1', 'iso-latin-1') or \
+ enc.startswith(('latin-1-', 'iso-8859-1-', 'iso-latin-1-')):
+ return 'iso-8859-1'
+ return orig_enc
+
+ def find_cookie(line):
+ try:
+ line_string = line.decode('ascii')
+ except UnicodeDecodeError:
+ return None
+
+ matches = _coding_re.findall(line_string)
+ if not matches:
+ return None
+ return get_normal_name(matches[0])
+
+ default = sys.getdefaultencoding()
+ first = read_or_stop()
+ if first and first.startswith(BOM_UTF8):
+ first = first[3:]
+ default = 'utf-8-sig'
+ if not first:
+ return default
+ encoding = find_cookie(first)
+ if encoding:
+ return encoding
+ second = read_or_stop()
+ if not second:
+ return default
+ encoding = find_cookie(second)
+ if encoding:
+ return encoding
+ return default
+
+
+# Low-level utility functions and classes.
+
+class Tee(object):
+ """
+ File-like object writing to two streams.
+ """
+ def __init__(self, stream1, stream2):
+ self.stream1 = stream1
+ self.stream2 = stream2
+
+ def write(self, text):
+ self.stream1.write(text)
+ self.stream2.write(text)
+
+ def flush(self):
+ if hasattr(self.stream1, 'flush'):
+ self.stream1.flush()
+ if hasattr(self.stream2, 'flush'):
+ self.stream2.flush()
+
+
+def parselinenos(spec, total):
+ """Parse a line number spec (such as "1,2,4-6") and return a list of
+ wanted line numbers.
+ """
+ items = list()
+ parts = spec.split(',')
+ for part in parts:
+ try:
+ begend = part.strip().split('-')
+ if len(begend) > 2:
+ raise ValueError
+ if len(begend) == 1:
+ items.append(int(begend[0])-1)
+ else:
+ start = (begend[0] == '') and 0 or int(begend[0])-1
+ end = (begend[1] == '') and total or int(begend[1])
+ items.extend(xrange(start, end))
+ except Exception:
+ raise ValueError('invalid line number spec: %r' % spec)
+ return items
+
+
+def force_decode(string, encoding):
+ """Forcibly get a unicode string out of a bytestring."""
+ if isinstance(string, bytes):
+ try:
+ if encoding:
+ string = string.decode(encoding)
+ else:
+ # try decoding with utf-8, should only work for real UTF-8
+ string = string.decode('utf-8')
+ except UnicodeError:
+ # last resort -- can't fail
+ string = string.decode('latin1')
+ return string
+
+
+class attrdict(dict):
+ def __getattr__(self, key):
+ return self[key]
+ def __setattr__(self, key, val):
+ self[key] = val
+ def __delattr__(self, key):
+ del self[key]
+
+
+def rpartition(s, t):
+ """Similar to str.rpartition from 2.5, but doesn't return the separator."""
+ i = s.rfind(t)
+ if i != -1:
+ return s[:i], s[i+len(t):]
+ return '', s
+
+
+def split_into(n, type, value):
+ """Split an index entry into a given number of parts at semicolons."""
+ parts = map(lambda x: x.strip(), value.split(';', n-1))
+ if sum(1 for part in parts if part) < n:
+ raise ValueError('invalid %s index entry %r' % (type, value))
+ return parts
+
+
+def split_index_msg(type, value):
+ # new entry types must be listed in directives/other.py!
+ result = []
+ try:
+ if type == 'single':
+ try:
+ result = split_into(2, 'single', value)
+ except ValueError:
+ result = split_into(1, 'single', value)
+ elif type == 'pair':
+ result = split_into(2, 'pair', value)
+ elif type == 'triple':
+ result = split_into(3, 'triple', value)
+ elif type == 'see':
+ result = split_into(2, 'see', value)
+ elif type == 'seealso':
+ result = split_into(2, 'see', value)
+ except ValueError:
+ pass
+
+ return result
+
+
+def format_exception_cut_frames(x=1):
+ """Format an exception with traceback, but only the last x frames."""
+ typ, val, tb = sys.exc_info()
+ #res = ['Traceback (most recent call last):\n']
+ res = []
+ tbres = traceback.format_tb(tb)
+ res += tbres[-x:]
+ res += traceback.format_exception_only(typ, val)
+ return ''.join(res)
+
+
+class PeekableIterator(object):
+ """
+ An iterator which wraps any iterable and makes it possible to peek to see
+ what's the next item.
+ """
+ def __init__(self, iterable):
+ self.remaining = deque()
+ self._iterator = iter(iterable)
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ """Return the next item from the iterator."""
+ if self.remaining:
+ return self.remaining.popleft()
+ return self._iterator.next()
+
+ def push(self, item):
+ """Push the `item` on the internal stack, it will be returned on the
+ next :meth:`next` call.
+ """
+ self.remaining.append(item)
+
+ def peek(self):
+ """Return the next item without changing the state of the iterator."""
+ item = self.next()
+ self.push(item)
+ return item
diff --git a/sphinx/util/compat.py b/sphinx/util/compat.py
new file mode 100644
index 0000000..9e5d619
--- /dev/null
+++ b/sphinx/util/compat.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.compat
+ ~~~~~~~~~~~~~~~~~~
+
+ Stuff for docutils compatibility.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from docutils import __version__ as _du_version
+docutils_version = tuple(int(x) for x in _du_version.split('.')[:2])
+
+def make_admonition(node_class, name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ #if not content:
+ # error = state_machine.reporter.error(
+ # 'The "%s" admonition is empty; content required.' % (name),
+ # nodes.literal_block(block_text, block_text), line=lineno)
+ # return [error]
+ text = '\n'.join(content)
+ admonition_node = node_class(text)
+ if arguments:
+ title_text = arguments[0]
+ textnodes, messages = state.inline_text(title_text, lineno)
+ admonition_node += nodes.title(title_text, '', *textnodes)
+ admonition_node += messages
+ if 'class' in options:
+ classes = options['class']
+ else:
+ classes = ['admonition-' + nodes.make_id(title_text)]
+ admonition_node['classes'] += classes
+ state.nested_parse(content, content_offset, admonition_node)
+ return [admonition_node]
+
+from docutils.parsers.rst import Directive
diff --git a/sphinx/util/console.py b/sphinx/util/console.py
new file mode 100644
index 0000000..c233010
--- /dev/null
+++ b/sphinx/util/console.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.console
+ ~~~~~~~~~~~~~~~~~~~
+
+ Format colored console output.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import sys
+import re
+
+_ansi_re = re.compile('\x1b\\[(\\d\\d;){0,2}\\d\\dm')
+codes = {}
+
+def get_terminal_width():
+ """Borrowed from the py lib."""
+ try:
+ import termios, fcntl, struct
+ call = fcntl.ioctl(0, termios.TIOCGWINSZ,
+ struct.pack('hhhh', 0, 0, 0, 0))
+ height, width = struct.unpack('hhhh', call)[:2]
+ terminal_width = width
+ except (SystemExit, KeyboardInterrupt):
+ raise
+ except:
+ # FALLBACK
+ terminal_width = int(os.environ.get('COLUMNS', 80)) - 1
+ return terminal_width
+
+
+_tw = get_terminal_width()
+def term_width_line(text):
+ if not codes:
+ # if no coloring, don't output fancy backspaces
+ return text + '\n'
+ else:
+ # codes are not displayed, this must be taken into account
+ return text.ljust(_tw + len(text) - len(_ansi_re.sub('', text))) + '\r'
+
+def color_terminal():
+ if not hasattr(sys.stdout, 'isatty'):
+ return False
+ if not sys.stdout.isatty():
+ return False
+ if 'COLORTERM' in os.environ:
+ return True
+ term = os.environ.get('TERM', 'dumb').lower()
+ if term in ('xterm', 'linux') or 'color' in term:
+ return True
+ return False
+
+
+def nocolor():
+ codes.clear()
+
+def coloron():
+ codes.update(_orig_codes)
+
+def colorize(name, text):
+ return codes.get(name, '') + text + codes.get('reset', '')
+
+def create_color_func(name):
+ def inner(text):
+ return colorize(name, text)
+ globals()[name] = inner
+
+_attrs = {
+ 'reset': '39;49;00m',
+ 'bold': '01m',
+ 'faint': '02m',
+ 'standout': '03m',
+ 'underline': '04m',
+ 'blink': '05m',
+}
+
+for _name, _value in _attrs.items():
+ codes[_name] = '\x1b[' + _value
+
+_colors = [
+ ('black', 'darkgray'),
+ ('darkred', 'red'),
+ ('darkgreen', 'green'),
+ ('brown', 'yellow'),
+ ('darkblue', 'blue'),
+ ('purple', 'fuchsia'),
+ ('turquoise', 'teal'),
+ ('lightgray', 'white'),
+]
+
+for i, (dark, light) in enumerate(_colors):
+ codes[dark] = '\x1b[%im' % (i+30)
+ codes[light] = '\x1b[%i;01m' % (i+30)
+
+_orig_codes = codes.copy()
+
+for _name in codes:
+ create_color_func(_name)
diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py
new file mode 100644
index 0000000..d6f46ab
--- /dev/null
+++ b/sphinx/util/docfields.py
@@ -0,0 +1,293 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.docfields
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ "Doc fields" are reST field lists in object descriptions that will
+ be domain-specifically transformed to a more appealing presentation.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from sphinx import addnodes
+
+
+def _is_single_paragraph(node):
+ """True if the node only contains one paragraph (and system messages)."""
+ if len(node) == 0:
+ return False
+ elif len(node) > 1:
+ for subnode in node[1:]:
+ if not isinstance(subnode, nodes.system_message):
+ return False
+ if isinstance(node[0], nodes.paragraph):
+ return True
+ return False
+
+
+class Field(object):
+ """
+ A doc field that is never grouped. It can have an argument or not, the
+ argument can be linked using a specified *rolename*. Field should be used
+ for doc fields that usually don't occur more than once.
+
+ Example::
+
+ :returns: description of the return value
+ :rtype: description of the return type
+ """
+ is_grouped = False
+ is_typed = False
+
+ def __init__(self, name, names=(), label=None, has_arg=True, rolename=None):
+ self.name = name
+ self.names = names
+ self.label = label
+ self.has_arg = has_arg
+ self.rolename = rolename
+
+ def make_xref(self, rolename, domain, target, innernode=nodes.emphasis):
+ if not rolename:
+ return innernode(target, target)
+ refnode = addnodes.pending_xref('', refdomain=domain, refexplicit=False,
+ reftype=rolename, reftarget=target)
+ refnode += innernode(target, target)
+ return refnode
+
+ def make_entry(self, fieldarg, content):
+ return (fieldarg, content)
+
+ def make_field(self, types, domain, item):
+ fieldarg, content = item
+ fieldname = nodes.field_name('', self.label)
+ if fieldarg:
+ fieldname += nodes.Text(' ')
+ fieldname += self.make_xref(self.rolename, domain,
+ fieldarg, nodes.Text)
+ fieldbody = nodes.field_body('', nodes.paragraph('', '', *content))
+ return nodes.field('', fieldname, fieldbody)
+
+
+class GroupedField(Field):
+ """
+ A doc field that is grouped; i.e., all fields of that type will be
+ transformed into one field with its body being a bulleted list. It always
+ has an argument. The argument can be linked using the given *rolename*.
+ GroupedField should be used for doc fields that can occur more than once.
+ If *can_collapse* is true, this field will revert to a Field if only used
+ once.
+
+ Example::
+
+ :raises ErrorClass: description when it is raised
+ """
+ is_grouped = True
+ list_type = nodes.bullet_list
+
+ def __init__(self, name, names=(), label=None, rolename=None,
+ can_collapse=False):
+ Field.__init__(self, name, names, label, True, rolename)
+ self.can_collapse = can_collapse
+
+ def make_field(self, types, domain, items):
+ fieldname = nodes.field_name('', self.label)
+ listnode = self.list_type()
+ if len(items) == 1 and self.can_collapse:
+ return Field.make_field(self, types, domain, items[0])
+ for fieldarg, content in items:
+ par = nodes.paragraph()
+ par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong)
+ par += nodes.Text(' -- ')
+ par += content
+ listnode += nodes.list_item('', par)
+ fieldbody = nodes.field_body('', listnode)
+ return nodes.field('', fieldname, fieldbody)
+
+
+class TypedField(GroupedField):
+ """
+ A doc field that is grouped and has type information for the arguments. It
+ always has an argument. The argument can be linked using the given
+ *rolename*, the type using the given *typerolename*.
+
+ Two uses are possible: either parameter and type description are given
+ separately, using a field from *names* and one from *typenames*,
+ respectively, or both are given using a field from *names*, see the example.
+
+ Example::
+
+ :param foo: description of parameter foo
+ :type foo: SomeClass
+
+ -- or --
+
+ :param SomeClass foo: description of parameter foo
+ """
+ is_typed = True
+
+ def __init__(self, name, names=(), typenames=(), label=None,
+ rolename=None, typerolename=None, can_collapse=False):
+ GroupedField.__init__(self, name, names, label, rolename, can_collapse)
+ self.typenames = typenames
+ self.typerolename = typerolename
+
+ def make_field(self, types, domain, items):
+ def handle_item(fieldarg, content):
+ par = nodes.paragraph()
+ par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong)
+ if fieldarg in types:
+ par += nodes.Text(' (')
+ # NOTE: using .pop() here to prevent a single type node to be
+ # inserted twice into the doctree, which leads to
+ # inconsistencies later when references are resolved
+ fieldtype = types.pop(fieldarg)
+ if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text):
+ typename = u''.join(n.astext() for n in fieldtype)
+ par += self.make_xref(self.typerolename, domain, typename)
+ else:
+ par += fieldtype
+ par += nodes.Text(')')
+ par += nodes.Text(' -- ')
+ par += content
+ return par
+
+ fieldname = nodes.field_name('', self.label)
+ if len(items) == 1 and self.can_collapse:
+ fieldarg, content = items[0]
+ bodynode = handle_item(fieldarg, content)
+ else:
+ bodynode = self.list_type()
+ for fieldarg, content in items:
+ bodynode += nodes.list_item('', handle_item(fieldarg, content))
+ fieldbody = nodes.field_body('', bodynode)
+ return nodes.field('', fieldname, fieldbody)
+
+
+class DocFieldTransformer(object):
+ """
+ Transforms field lists in "doc field" syntax into better-looking
+ equivalents, using the field type definitions given on a domain.
+ """
+
+ def __init__(self, directive):
+ self.domain = directive.domain
+ if '_doc_field_type_map' not in directive.__class__.__dict__:
+ directive.__class__._doc_field_type_map = \
+ self.preprocess_fieldtypes(directive.__class__.doc_field_types)
+ self.typemap = directive._doc_field_type_map
+
+ def preprocess_fieldtypes(self, types):
+ typemap = {}
+ for fieldtype in types:
+ for name in fieldtype.names:
+ typemap[name] = fieldtype, False
+ if fieldtype.is_typed:
+ for name in fieldtype.typenames:
+ typemap[name] = fieldtype, True
+ return typemap
+
+ def transform_all(self, node):
+ """Transform all field list children of a node."""
+ # don't traverse, only handle field lists that are immediate children
+ for child in node:
+ if isinstance(child, nodes.field_list):
+ self.transform(child)
+
+ def transform(self, node):
+ """Transform a single field list *node*."""
+ typemap = self.typemap
+
+ entries = []
+ groupindices = {}
+ types = {}
+
+ # step 1: traverse all fields and collect field types and content
+ for field in node:
+ fieldname, fieldbody = field
+ try:
+ # split into field type and argument
+ fieldtype, fieldarg = fieldname.astext().split(None, 1)
+ except ValueError:
+ # maybe an argument-less field type?
+ fieldtype, fieldarg = fieldname.astext(), ''
+ typedesc, is_typefield = typemap.get(fieldtype, (None, None))
+
+ # sort out unknown fields
+ if typedesc is None or typedesc.has_arg != bool(fieldarg):
+ # either the field name is unknown, or the argument doesn't
+ # match the spec; capitalize field name and be done with it
+ new_fieldname = fieldtype[0:1].upper() + fieldtype[1:]
+ if fieldarg:
+ new_fieldname += ' ' + fieldarg
+ fieldname[0] = nodes.Text(new_fieldname)
+ entries.append(field)
+ continue
+
+ typename = typedesc.name
+
+ # collect the content, trying not to keep unnecessary paragraphs
+ if _is_single_paragraph(fieldbody):
+ content = fieldbody.children[0].children
+ else:
+ content = fieldbody.children
+
+ # if the field specifies a type, put it in the types collection
+ if is_typefield:
+ # filter out only inline nodes; others will result in invalid
+ # markup being written out
+ content = filter(
+ lambda n: isinstance(n, nodes.Inline) or
+ isinstance(n, nodes.Text),
+ content)
+ if content:
+ types.setdefault(typename, {})[fieldarg] = content
+ continue
+
+ # also support syntax like ``:param type name:``
+ if typedesc.is_typed:
+ try:
+ argtype, argname = fieldarg.split(None, 1)
+ except ValueError:
+ pass
+ else:
+ types.setdefault(typename, {})[argname] = \
+ [nodes.Text(argtype)]
+ fieldarg = argname
+
+ translatable_content = nodes.inline(fieldbody.rawsource,
+ translatable=True)
+ translatable_content.source = fieldbody.parent.source
+ translatable_content.line = fieldbody.parent.line
+ translatable_content += content
+
+ # grouped entries need to be collected in one entry, while others
+ # get one entry per field
+ if typedesc.is_grouped:
+ if typename in groupindices:
+ group = entries[groupindices[typename]]
+ else:
+ groupindices[typename] = len(entries)
+ group = [typedesc, []]
+ entries.append(group)
+ entry = typedesc.make_entry(fieldarg, [translatable_content])
+ group[1].append(entry)
+ else:
+ entry = typedesc.make_entry(fieldarg, [translatable_content])
+ entries.append([typedesc, entry])
+
+ # step 2: all entries are collected, construct the new field list
+ new_list = nodes.field_list()
+ for entry in entries:
+ if isinstance(entry, nodes.field):
+ # pass-through old field
+ new_list += entry
+ else:
+ fieldtype, content = entry
+ fieldtypes = types.get(fieldtype.name, {})
+ new_list += fieldtype.make_field(fieldtypes, self.domain,
+ content)
+
+ node.replace_self(new_list)
diff --git a/sphinx/util/docstrings.py b/sphinx/util/docstrings.py
new file mode 100644
index 0000000..7138130
--- /dev/null
+++ b/sphinx/util/docstrings.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.docstrings
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Utilities for docstring processing.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+
+
+def prepare_docstring(s, ignore=1):
+ """Convert a docstring into lines of parseable reST. Remove common leading
+ indentation, where the indentation of a given number of lines (usually just
+ one) is ignored.
+
+ Return the docstring as a list of lines usable for inserting into a docutils
+ ViewList (used as argument of nested_parse().) An empty line is added to
+ act as a separator between this docstring and following content.
+ """
+ lines = s.expandtabs().splitlines()
+ # Find minimum indentation of any non-blank lines after ignored lines.
+ margin = sys.maxint
+ for line in lines[ignore:]:
+ content = len(line.lstrip())
+ if content:
+ indent = len(line) - content
+ margin = min(margin, indent)
+ # Remove indentation from ignored lines.
+ for i in range(ignore):
+ if i < len(lines):
+ lines[i] = lines[i].lstrip()
+ if margin < sys.maxint:
+ for i in range(ignore, len(lines)): lines[i] = lines[i][margin:]
+ # Remove any leading blank lines.
+ while lines and not lines[0]:
+ lines.pop(0)
+ # make sure there is an empty line at the end
+ if lines and lines[-1]:
+ lines.append('')
+ return lines
+
+
+def prepare_commentdoc(s):
+ """Extract documentation comment lines (starting with #:) and return them
+ as a list of lines. Returns an empty list if there is no documentation.
+ """
+ result = []
+ lines = [line.strip() for line in s.expandtabs().splitlines()]
+ for line in lines:
+ if line.startswith('#:'):
+ line = line[2:]
+ # the first space after the comment is ignored
+ if line and line[0] == ' ':
+ line = line[1:]
+ result.append(line)
+ if result and result[-1]:
+ result.append('')
+ return result
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
new file mode 100644
index 0000000..cdbfea7
--- /dev/null
+++ b/sphinx/util/inspect.py
@@ -0,0 +1,156 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.inspect
+ ~~~~~~~~~~~~~~~~~~~
+
+ Helpers for inspecting Python modules.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+
+# this imports the standard library inspect module without resorting to
+# relatively import this module
+inspect = __import__('inspect')
+
+from sphinx.util import force_decode
+from sphinx.util.pycompat import bytes, builtins
+
+
+if sys.version_info >= (3, 0):
+ from functools import partial
+ def getargspec(func):
+ """Like inspect.getargspec but supports functools.partial as well."""
+ if inspect.ismethod(func):
+ func = func.__func__
+ if type(func) is partial:
+ orig_func = func.func
+ argspec = getargspec(orig_func)
+ args = list(argspec[0])
+ defaults = list(argspec[3] or ())
+ kwoargs = list(argspec[4])
+ kwodefs = dict(argspec[5] or {})
+ if func.args:
+ args = args[len(func.args):]
+ for arg in func.keywords or ():
+ try:
+ i = args.index(arg) - len(args)
+ del args[i]
+ try:
+ del defaults[i]
+ except IndexError:
+ pass
+ except ValueError: # must be a kwonly arg
+ i = kwoargs.index(arg)
+ del kwoargs[i]
+ del kwodefs[arg]
+ return inspect.FullArgSpec(args, argspec[1], argspec[2],
+ tuple(defaults), kwoargs,
+ kwodefs, argspec[6])
+ while hasattr(func, '__wrapped__'):
+ func = func.__wrapped__
+ if not inspect.isfunction(func):
+ raise TypeError('%r is not a Python function' % func)
+ return inspect.getfullargspec(func)
+
+elif sys.version_info >= (2, 5):
+ from functools import partial
+ def getargspec(func):
+ """Like inspect.getargspec but supports functools.partial as well."""
+ if inspect.ismethod(func):
+ func = func.im_func
+ parts = 0, ()
+ if type(func) is partial:
+ keywords = func.keywords
+ if keywords is None:
+ keywords = {}
+ parts = len(func.args), keywords.keys()
+ func = func.func
+ if not inspect.isfunction(func):
+ raise TypeError('%r is not a Python function' % func)
+ args, varargs, varkw = inspect.getargs(func.func_code)
+ func_defaults = func.func_defaults
+ if func_defaults is None:
+ func_defaults = []
+ else:
+ func_defaults = list(func_defaults)
+ if parts[0]:
+ args = args[parts[0]:]
+ if parts[1]:
+ for arg in parts[1]:
+ i = args.index(arg) - len(args)
+ del args[i]
+ try:
+ del func_defaults[i]
+ except IndexError:
+ pass
+ if sys.version_info >= (2, 6):
+ return inspect.ArgSpec(args, varargs, varkw, func_defaults)
+ else:
+ return (args, varargs, varkw, func_defaults)
+else:
+ getargspec = inspect.getargspec
+
+
+def isdescriptor(x):
+ """Check if the object is some kind of descriptor."""
+ for item in '__get__', '__set__', '__delete__':
+ if hasattr(safe_getattr(x, item, None), '__call__'):
+ return True
+ return False
+
+
+def safe_getattr(obj, name, *defargs):
+ """A getattr() that turns all exceptions into AttributeErrors."""
+ try:
+ return getattr(obj, name, *defargs)
+ except Exception:
+ # this is a catch-all for all the weird things that some modules do
+ # with attribute access
+ if defargs:
+ return defargs[0]
+ raise AttributeError(name)
+
+
+def safe_getmembers(object, predicate=None, attr_getter=safe_getattr):
+ """A version of inspect.getmembers() that uses safe_getattr()."""
+ results = []
+ for key in dir(object):
+ try:
+ value = attr_getter(object, key, None)
+ except AttributeError:
+ continue
+ if not predicate or predicate(value):
+ results.append((key, value))
+ results.sort()
+ return results
+
+
+def safe_repr(object):
+ """A repr() implementation that returns text safe to use in reST context."""
+ try:
+ s = repr(object)
+ except Exception:
+ raise ValueError
+ if isinstance(s, bytes):
+ return force_decode(s, None).replace('\n', ' ')
+ return s.replace('\n', ' ')
+
+
+def is_builtin_class_method(obj, attr_name):
+ """If attr_name is implemented at builtin class, return True.
+
+ >>> is_builtin_class_method(int, '__init__')
+ True
+
+ Why this function needed? CPython implements int.__init__ by Descriptor
+ but PyPy implements it by pure Python code.
+ """
+ classes = [c for c in inspect.getmro(obj) if attr_name in c.__dict__]
+ cls = classes[0] if classes else object
+
+ if not hasattr(builtins, safe_getattr(cls, '__name__', '')):
+ return False
+ return getattr(builtins, safe_getattr(cls, '__name__', '')) is cls
diff --git a/sphinx/util/jsdump.py b/sphinx/util/jsdump.py
new file mode 100644
index 0000000..85845a7
--- /dev/null
+++ b/sphinx/util/jsdump.py
@@ -0,0 +1,195 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.jsdump
+ ~~~~~~~~~~~~~~~~~~
+
+ This module implements a simple JavaScript serializer.
+ Uses the basestring encode function from simplejson by Bob Ippolito.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from sphinx.util.pycompat import u
+
+_str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
+_int_re = re.compile(r'\d+')
+_name_re = re.compile(r'[a-zA-Z]\w*')
+_nameonly_re = re.compile(r'[a-zA-Z]\w*$')
+
+# escape \, ", control characters and everything outside ASCII
+ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
+ESCAPE_DICT = {
+ '\\': '\\\\',
+ '"': '\\"',
+ '\b': '\\b',
+ '\f': '\\f',
+ '\n': '\\n',
+ '\r': '\\r',
+ '\t': '\\t',
+}
+
+ESCAPED = re.compile(r'\\u.{4}|\\.')
+
+
+def encode_string(s):
+ def replace(match):
+ s = match.group(0)
+ try:
+ return ESCAPE_DICT[s]
+ except KeyError:
+ n = ord(s)
+ if n < 0x10000:
+ return '\\u%04x' % (n,)
+ else:
+ # surrogate pair
+ n -= 0x10000
+ s1 = 0xd800 | ((n >> 10) & 0x3ff)
+ s2 = 0xdc00 | (n & 0x3ff)
+ return '\\u%04x\\u%04x' % (s1, s2)
+ return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
+
+def decode_string(s):
+ return ESCAPED.sub(lambda m: eval(u + '"' + m.group() + '"'), s)
+
+
+reswords = set("""\
+abstract else instanceof switch
+boolean enum int synchronized
+break export interface this
+byte extends long throw
+case false native throws
+catch final new transient
+char finally null true
+class float package try
+const for private typeof
+continue function protected var
+debugger goto public void
+default if return volatile
+delete implements short while
+do import static with
+double in super""".split())
+
+def dumps(obj, key=False):
+ if key:
+ if not isinstance(obj, basestring):
+ obj = str(obj)
+ if _nameonly_re.match(obj) and obj not in reswords:
+ return obj # return it as a bare word
+ else:
+ return encode_string(obj)
+ if obj is None:
+ return 'null'
+ elif obj is True or obj is False:
+ return obj and 'true' or 'false'
+ elif isinstance(obj, (int, long, float)):
+ return str(obj)
+ elif isinstance(obj, dict):
+ return '{%s}' % ','.join('%s:%s' % (
+ dumps(key, True),
+ dumps(value)
+ ) for key, value in obj.iteritems())
+ elif isinstance(obj, (tuple, list, set)):
+ return '[%s]' % ','.join(dumps(x) for x in obj)
+ elif isinstance(obj, basestring):
+ return encode_string(obj)
+ raise TypeError(type(obj))
+
+def dump(obj, f):
+ f.write(dumps(obj))
+
+
+def loads(x):
+ """Loader that can read the JS subset the indexer produces."""
+ nothing = object()
+ i = 0
+ n = len(x)
+ stack = []
+ obj = nothing
+ key = False
+ keys = []
+ while i < n:
+ c = x[i]
+ if c == '{':
+ obj = {}
+ stack.append(obj)
+ key = True
+ keys.append(nothing)
+ i += 1
+ elif c == '[':
+ obj = []
+ stack.append(obj)
+ key = False
+ keys.append(nothing)
+ i += 1
+ elif c in '}]':
+ if key:
+ if keys[-1] is not nothing:
+ raise ValueError("unfinished dict")
+ # empty dict
+ key = False
+ oldobj = stack.pop()
+ keys.pop()
+ if stack:
+ obj = stack[-1]
+ if isinstance(obj, dict):
+ if keys[-1] is nothing:
+ raise ValueError("invalid key object", oldobj)
+ obj[keys[-1]] = oldobj
+ else:
+ obj.append(oldobj)
+ else:
+ break
+ i += 1
+ elif c == ',':
+ if key:
+ raise ValueError("multiple keys")
+ if isinstance(obj, dict):
+ key = True
+ i += 1
+ elif c == ':':
+ if not isinstance(obj, dict):
+ raise ValueError("colon in list")
+ i += 1
+ if not key:
+ raise ValueError("multiple values")
+ key = False
+ else:
+ m = _str_re.match(x, i)
+ if m:
+ y = decode_string(m.group()[1:-1])
+ else:
+ m = _int_re.match(x, i)
+ if m:
+ y = int(m.group())
+ else:
+ m = _name_re.match(x, i)
+ if m:
+ y = m.group()
+ if y == 'true':
+ y = True
+ elif y == 'false':
+ y = False
+ elif y == 'null':
+ y = None
+ elif not key:
+ raise ValueError("bareword as value")
+ else:
+ raise ValueError("read error at pos %d" % i)
+ i = m.end()
+ if isinstance(obj, dict):
+ if key:
+ keys[-1] = y
+ else:
+ obj[keys[-1]] = y
+ key = False
+ else:
+ obj.append(y)
+ if obj is nothing:
+ raise ValueError("nothing loaded from string")
+ return obj
+
+def load(f):
+ return loads(f.read())
diff --git a/sphinx/util/jsonimpl.py b/sphinx/util/jsonimpl.py
new file mode 100644
index 0000000..8ccbf0c
--- /dev/null
+++ b/sphinx/util/jsonimpl.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.jsonimpl
+ ~~~~~~~~~~~~~~~~~~~~
+
+ JSON serializer implementation wrapper.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import UserString
+
+try:
+ import json
+ # json-py's json module has no JSONEncoder; this will raise AttributeError
+ # if json-py is imported instead of the built-in json module
+ JSONEncoder = json.JSONEncoder
+except (ImportError, AttributeError):
+ try:
+ import simplejson as json
+ JSONEncoder = json.JSONEncoder
+ except ImportError:
+ json = None
+ JSONEncoder = object
+
+
+class SphinxJSONEncoder(JSONEncoder):
+ """JSONEncoder subclass that forces translation proxies."""
+ def default(self, obj):
+ if isinstance(obj, UserString.UserString):
+ return unicode(obj)
+ return JSONEncoder.default(self, obj)
+
+
+def dump(obj, fp, *args, **kwds):
+ kwds['cls'] = SphinxJSONEncoder
+ return json.dump(obj, fp, *args, **kwds)
+
+def dumps(obj, *args, **kwds):
+ kwds['cls'] = SphinxJSONEncoder
+ return json.dumps(obj, *args, **kwds)
+
+def load(*args, **kwds):
+ return json.load(*args, **kwds)
+
+def loads(*args, **kwds):
+ return json.loads(*args, **kwds)
diff --git a/sphinx/util/matching.py b/sphinx/util/matching.py
new file mode 100644
index 0000000..51b2056
--- /dev/null
+++ b/sphinx/util/matching.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.matching
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Pattern-matching utility functions for Sphinx.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+
+def _translate_pattern(pat):
+ """Translate a shell-style glob pattern to a regular expression.
+
+ Adapted from the fnmatch module, but enhanced so that single stars don't
+ match slashes.
+ """
+ i, n = 0, len(pat)
+ res = ''
+ while i < n:
+ c = pat[i]
+ i += 1
+ if c == '*':
+ if i < n and pat[i] == '*':
+ # double star matches slashes too
+ i += 1
+ res = res + '.*'
+ else:
+ # single star doesn't match slashes
+ res = res + '[^/]*'
+ elif c == '?':
+ # question mark doesn't match slashes too
+ res = res + '[^/]'
+ elif c == '[':
+ j = i
+ if j < n and pat[j] == '!':
+ j += 1
+ if j < n and pat[j] == ']':
+ j += 1
+ while j < n and pat[j] != ']':
+ j += 1
+ if j >= n:
+ res = res + '\\['
+ else:
+ stuff = pat[i:j].replace('\\', '\\\\')
+ i = j + 1
+ if stuff[0] == '!':
+ # negative pattern mustn't match slashes too
+ stuff = '^/' + stuff[1:]
+ elif stuff[0] == '^':
+ stuff = '\\' + stuff
+ res = '%s[%s]' % (res, stuff)
+ else:
+ res += re.escape(c)
+ return res + '$'
+
+def compile_matchers(patterns):
+ return [re.compile(_translate_pattern(pat)).match for pat in patterns]
+
+
+_pat_cache = {}
+
+def patmatch(name, pat):
+ """Return if name matches pat. Adapted from fnmatch module."""
+ if pat not in _pat_cache:
+ _pat_cache[pat] = re.compile(_translate_pattern(pat))
+ return _pat_cache[pat].match(name)
+
+def patfilter(names, pat):
+ """Return the subset of the list NAMES that match PAT.
+
+ Adapted from fnmatch module.
+ """
+ if pat not in _pat_cache:
+ _pat_cache[pat] = re.compile(_translate_pattern(pat))
+ match = _pat_cache[pat].match
+ return filter(match, names)
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
new file mode 100644
index 0000000..eb3b86b
--- /dev/null
+++ b/sphinx/util/nodes.py
@@ -0,0 +1,268 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.nodes
+ ~~~~~~~~~~~~~~~~~
+
+ Docutils node-related utility functions for Sphinx.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import sys
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.locale import pairindextypes
+
+
+class WarningStream(object):
+
+ def __init__(self, warnfunc):
+ self.warnfunc = warnfunc
+ self._re = re.compile(r'\((DEBUG|INFO|WARNING|ERROR|SEVERE)/[0-4]\)')
+
+ def write(self, text):
+ text = text.strip()
+ if text:
+ self.warnfunc(self._re.sub(r'\1:', text), None, '')
+
+
+# \x00 means the "<" was backslash-escaped
+explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL)
+caption_ref_re = explicit_title_re # b/w compat alias
+
+
+def apply_source_workaround(node):
+ if node.source:
+ return
+
+ # workaround: nodes.term doesn't have source, line and rawsource
+ # (fixed in Docutils r7495)
+ if isinstance(node, nodes.term):
+ definition_list_item = node.parent
+ if definition_list_item.line is not None:
+ node.source = definition_list_item.source
+ node.line = definition_list_item.line - 1
+ node.rawsource = definition_list_item. \
+ rawsource.split("\n", 2)[0]
+ return
+
+ # workaround: docutils-0.10.0 or older's nodes.caption for nodes.figure
+ # and nodes.title for nodes.admonition doesn't have source, line.
+ # this issue was filed to Docutils tracker:
+ # sf.net/tracker/?func=detail&aid=3599485&group_id=38414&atid=422032
+ # sourceforge.net/p/docutils/patches/108/
+ if (isinstance(node, (
+ nodes.caption,
+ nodes.title,
+ nodes.rubric,
+ nodes.line,
+ ))):
+ node.source = find_source_node(node)
+ node.line = 0 # need fix docutils to get `node.line`
+ return
+
+
+IGNORED_NODES = (
+ nodes.Invisible,
+ nodes.Inline,
+ nodes.literal_block,
+ nodes.doctest_block,
+ #XXX there are probably more
+)
+def extract_messages(doctree):
+ """Extract translatable messages from a document tree."""
+ for node in doctree.traverse(nodes.TextElement):
+ apply_source_workaround(node)
+
+ if not node.source:
+ continue # built-in message
+ if isinstance(node, IGNORED_NODES) and 'translatable' not in node:
+ continue
+ # <field_name>orphan</field_name>
+ # XXX ignore all metadata (== docinfo)
+ if isinstance(node, nodes.field_name) and node.children[0] == 'orphan':
+ continue
+
+ msg = node.rawsource.replace('\n', ' ').strip()
+ # XXX nodes rendering empty are likely a bug in sphinx.addnodes
+ if msg:
+ yield node, msg
+
+
+def find_source_node(node):
+ for pnode in traverse_parent(node):
+ if pnode.source:
+ return pnode.source
+
+
+def traverse_parent(node):
+ while node:
+ yield node
+ node = node.parent
+
+
+def traverse_translatable_index(doctree):
+ """Traverse translatable index node from a document tree."""
+ def is_block_index(node):
+ return isinstance(node, addnodes.index) and \
+ node.get('inline') == False
+ for node in doctree.traverse(is_block_index):
+ if 'raw_entries' in node:
+ entries = node['raw_entries']
+ else:
+ entries = node['entries']
+ yield node, entries
+
+
+def nested_parse_with_titles(state, content, node):
+ """Version of state.nested_parse() that allows titles and does not require
+ titles to have the same decoration as the calling document.
+
+ This is useful when the parsed content comes from a completely different
+ context, such as docstrings.
+ """
+ # hack around title style bookkeeping
+ surrounding_title_styles = state.memo.title_styles
+ surrounding_section_level = state.memo.section_level
+ state.memo.title_styles = []
+ state.memo.section_level = 0
+ try:
+ return state.nested_parse(content, 0, node, match_titles=1)
+ finally:
+ state.memo.title_styles = surrounding_title_styles
+ state.memo.section_level = surrounding_section_level
+
+
+def clean_astext(node):
+ """Like node.astext(), but ignore images."""
+ node = node.deepcopy()
+ for img in node.traverse(nodes.image):
+ img['alt'] = ''
+ return node.astext()
+
+
+def split_explicit_title(text):
+ """Split role content into title and target, if given."""
+ match = explicit_title_re.match(text)
+ if match:
+ return True, match.group(1), match.group(2)
+ return False, text, text
+
+
+indextypes = [
+ 'single', 'pair', 'double', 'triple', 'see', 'seealso',
+]
+
+def process_index_entry(entry, targetid):
+ indexentries = []
+ entry = entry.strip()
+ oentry = entry
+ main = ''
+ if entry.startswith('!'):
+ main = 'main'
+ entry = entry[1:].lstrip()
+ for type in pairindextypes:
+ if entry.startswith(type+':'):
+ value = entry[len(type)+1:].strip()
+ value = pairindextypes[type] + '; ' + value
+ indexentries.append(('pair', value, targetid, main))
+ break
+ else:
+ for type in indextypes:
+ if entry.startswith(type+':'):
+ value = entry[len(type)+1:].strip()
+ if type == 'double':
+ type = 'pair'
+ indexentries.append((type, value, targetid, main))
+ break
+ # shorthand notation for single entries
+ else:
+ for value in oentry.split(','):
+ value = value.strip()
+ main = ''
+ if value.startswith('!'):
+ main = 'main'
+ value = value[1:].lstrip()
+ if not value:
+ continue
+ indexentries.append(('single', value, targetid, main))
+ return indexentries
+
+
+def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc):
+ """Inline all toctrees in the *tree*.
+
+ Record all docnames in *docnameset*, and output docnames with *colorfunc*.
+ """
+ tree = tree.deepcopy()
+ for toctreenode in tree.traverse(addnodes.toctree):
+ newnodes = []
+ includefiles = map(unicode, toctreenode['includefiles'])
+ for includefile in includefiles:
+ try:
+ builder.info(colorfunc(includefile) + " ", nonl=1)
+ subtree = inline_all_toctrees(builder, docnameset, includefile,
+ builder.env.get_doctree(includefile), colorfunc)
+ docnameset.add(includefile)
+ except Exception:
+ builder.warn('toctree contains ref to nonexisting '
+ 'file %r' % includefile,
+ builder.env.doc2path(docname))
+ else:
+ sof = addnodes.start_of_file(docname=includefile)
+ sof.children = subtree.children
+ newnodes.append(sof)
+ toctreenode.parent.replace(toctreenode, newnodes)
+ return tree
+
+
+def make_refnode(builder, fromdocname, todocname, targetid, child, title=None):
+ """Shortcut to create a reference node."""
+ node = nodes.reference('', '', internal=True)
+ if fromdocname == todocname:
+ node['refid'] = targetid
+ else:
+ node['refuri'] = (builder.get_relative_uri(fromdocname, todocname)
+ + '#' + targetid)
+ if title:
+ node['reftitle'] = title
+ node.append(child)
+ return node
+
+
+def set_source_info(directive, node):
+ node.source, node.line = \
+ directive.state_machine.get_source_and_line(directive.lineno)
+
+def set_role_source_info(inliner, lineno, node):
+ try:
+ node.source, node.line = \
+ inliner.reporter.locator(lineno)
+ except AttributeError:
+ # docutils 0.9+
+ node.source, node.line = inliner.reporter.get_source_and_line(lineno)
+
+# monkey-patch Element.copy to copy the rawsource
+
+def _new_copy(self):
+ return self.__class__(self.rawsource, **self.attributes)
+
+nodes.Element.copy = _new_copy
+
+# monkey-patch Element.__repr__ to return str if it returns unicode.
+# Was fixed in docutils since 0.10. See sf.net/p/docutils/bugs/218/.
+
+if sys.version_info < (3,):
+ _element_repr_orig = nodes.Element.__repr__
+
+ def _new_repr(self):
+ s = _element_repr_orig(self)
+ if isinstance(s, unicode):
+ return s.encode('utf-8')
+ return s
+
+ nodes.Element.__repr__ = _new_repr
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
new file mode 100644
index 0000000..d7b292b
--- /dev/null
+++ b/sphinx/util/osutil.py
@@ -0,0 +1,198 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.osutil
+ ~~~~~~~~~~~~~~~~~~
+
+ Operating system-related utility functions for Sphinx.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import sys
+import time
+import errno
+import locale
+import shutil
+import gettext
+from os import path
+
+# Errnos that we need.
+EEXIST = getattr(errno, 'EEXIST', 0)
+ENOENT = getattr(errno, 'ENOENT', 0)
+EPIPE = getattr(errno, 'EPIPE', 0)
+EINVAL = getattr(errno, 'EINVAL', 0)
+
+# SEP separates path elements in the canonical file names
+#
+# Define SEP as a manifest constant, not so much because we expect it to change
+# in the future as to avoid the suspicion that a stray "/" in the code is a
+# hangover from more *nix-oriented origins.
+SEP = "/"
+
+def os_path(canonicalpath):
+ return canonicalpath.replace(SEP, path.sep)
+
+
+def relative_uri(base, to):
+ """Return a relative URL from ``base`` to ``to``."""
+ if to.startswith(SEP):
+ return to
+ b2 = base.split(SEP)
+ t2 = to.split(SEP)
+ # remove common segments (except the last segment)
+ for x, y in zip(b2[:-1], t2[:-1]):
+ if x != y:
+ break
+ b2.pop(0)
+ t2.pop(0)
+ if b2 == t2:
+ # Special case: relative_uri('f/index.html','f/index.html')
+ # returns '', not 'index.html'
+ return ''
+ if len(b2) == 1 and t2 == ['']:
+ # Special case: relative_uri('f/index.html','f/') should
+ # return './', not ''
+ return '.' + SEP
+ return ('..' + SEP) * (len(b2)-1) + SEP.join(t2)
+
+
+def ensuredir(path):
+ """Ensure that a path exists."""
+ try:
+ os.makedirs(path)
+ except OSError, err:
+ # 0 for Jython/Win32
+ if err.errno not in [0, EEXIST]:
+ raise
+
+
+def walk(top, topdown=True, followlinks=False):
+ """Backport of os.walk from 2.6, where the *followlinks* argument was
+ added.
+ """
+ names = os.listdir(top)
+
+ dirs, nondirs = [], []
+ for name in names:
+ try:
+ fullpath = path.join(top, name)
+ except UnicodeError:
+ print >>sys.stderr, (
+ '%s:: ERROR: non-ASCII filename not supported on this '
+ 'filesystem encoding %r, skipped.' % (name, fs_encoding))
+ continue
+ if path.isdir(fullpath):
+ dirs.append(name)
+ else:
+ nondirs.append(name)
+
+ if topdown:
+ yield top, dirs, nondirs
+ for name in dirs:
+ fullpath = path.join(top, name)
+ if followlinks or not path.islink(fullpath):
+ for x in walk(fullpath, topdown, followlinks):
+ yield x
+ if not topdown:
+ yield top, dirs, nondirs
+
+
+def mtimes_of_files(dirnames, suffix):
+ for dirname in dirnames:
+ for root, dirs, files in os.walk(dirname):
+ for sfile in files:
+ if sfile.endswith(suffix):
+ try:
+ yield path.getmtime(path.join(root, sfile))
+ except EnvironmentError:
+ pass
+
+
+def movefile(source, dest):
+ """Move a file, removing the destination if it exists."""
+ if os.path.exists(dest):
+ try:
+ os.unlink(dest)
+ except OSError:
+ pass
+ os.rename(source, dest)
+
+
+def copytimes(source, dest):
+ """Copy a file's modification times."""
+ st = os.stat(source)
+ if hasattr(os, 'utime'):
+ os.utime(dest, (st.st_atime, st.st_mtime))
+
+
+def copyfile(source, dest):
+ """Copy a file and its modification times, if possible."""
+ shutil.copyfile(source, dest)
+ try:
+ # don't do full copystat because the source may be read-only
+ copytimes(source, dest)
+ except OSError:
+ pass
+
+
+no_fn_re = re.compile(r'[^a-zA-Z0-9_-]')
+
+def make_filename(string):
+ return no_fn_re.sub('', string) or 'sphinx'
+
+if sys.version_info < (3, 0):
+ # strftime for unicode strings
+ def ustrftime(format, *args):
+ # if a locale is set, the time strings are encoded in the encoding
+ # given by LC_TIME; if that is available, use it
+ enc = locale.getlocale(locale.LC_TIME)[1] or 'utf-8'
+ return time.strftime(unicode(format).encode(enc), *args).decode(enc)
+else:
+ ustrftime = time.strftime
+
+
+def safe_relpath(path, start=None):
+ from sphinx.util.pycompat import relpath
+ try:
+ return relpath(path, start)
+ except ValueError:
+ return path
+
+def find_catalog(docname, compaction):
+ if compaction:
+ ret = docname.split(SEP, 1)[0]
+ else:
+ ret = docname
+
+ return ret
+
+
+def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction):
+ from sphinx.util.pycompat import relpath
+ if not(lang and locale_dirs):
+ return []
+
+ domain = find_catalog(docname, compaction)
+ files = [gettext.find(domain, path.join(srcdir, dir_), [lang])
+ for dir_ in locale_dirs]
+ files = [relpath(f, srcdir) for f in files if f]
+ return files
+
+
+fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
+
+
+if sys.version_info < (3, 0):
+ bytes = str
+else:
+ bytes = bytes
+
+
+def abspath(pathdir):
+ pathdir = path.abspath(pathdir)
+ if isinstance(pathdir, bytes):
+ pathdir = pathdir.decode(fs_encoding)
+ return pathdir
diff --git a/sphinx/util/png.py b/sphinx/util/png.py
new file mode 100644
index 0000000..65fc4d8
--- /dev/null
+++ b/sphinx/util/png.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.png
+ ~~~~~~~~~~~~~~~
+
+ PNG image manipulation helpers.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import struct
+import binascii
+
+from sphinx.util.pycompat import b
+
+LEN_IEND = 12
+LEN_DEPTH = 22
+
+DEPTH_CHUNK_LEN = struct.pack('!i', 10)
+DEPTH_CHUNK_START = b('tEXtDepth\x00')
+IEND_CHUNK = b('\x00\x00\x00\x00IEND\xAE\x42\x60\x82')
+
+
+def read_png_depth(filename):
+ """Read the special tEXt chunk indicating the depth from a PNG file."""
+ result = None
+ f = open(filename, 'rb')
+ try:
+ f.seek(- (LEN_IEND + LEN_DEPTH), 2)
+ depthchunk = f.read(LEN_DEPTH)
+ if not depthchunk.startswith(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START):
+ # either not a PNG file or not containing the depth chunk
+ return None
+ result = struct.unpack('!i', depthchunk[14:18])[0]
+ finally:
+ f.close()
+ return result
+
+
+def write_png_depth(filename, depth):
+ """Write the special tEXt chunk indicating the depth to a PNG file.
+
+ The chunk is placed immediately before the special IEND chunk.
+ """
+ data = struct.pack('!i', depth)
+ f = open(filename, 'r+b')
+ try:
+ # seek to the beginning of the IEND chunk
+ f.seek(-LEN_IEND, 2)
+ # overwrite it with the depth chunk
+ f.write(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START + data)
+ # calculate the checksum over chunk name and data
+ crc = binascii.crc32(DEPTH_CHUNK_START + data) & 0xffffffff
+ f.write(struct.pack('!I', crc))
+ # replace the IEND chunk
+ f.write(IEND_CHUNK)
+ finally:
+ f.close()
diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py
new file mode 100644
index 0000000..17f8871
--- /dev/null
+++ b/sphinx/util/pycompat.py
@@ -0,0 +1,282 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.pycompat
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Stuff for Python version compatibility.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import codecs
+import encodings
+
+# ------------------------------------------------------------------------------
+# Python 2/3 compatibility
+
+if sys.version_info >= (3, 0):
+ # Python 3
+ class_types = (type,)
+ # the ubiquitous "bytes" helper functions
+ def b(s):
+ return s.encode('utf-8')
+ bytes = bytes
+ # prefix for Unicode strings
+ u = ''
+ # StringIO/BytesIO classes
+ from io import StringIO, BytesIO, TextIOWrapper
+ # safely encode a string for printing to the terminal
+ def terminal_safe(s):
+ return s.encode('ascii', 'backslashreplace').decode('ascii')
+ # some kind of default system encoding; should be used with a lenient
+ # error handler
+ sys_encoding = sys.getdefaultencoding()
+ # support for running 2to3 over config files
+ def convert_with_2to3(filepath):
+ from lib2to3.refactor import RefactoringTool, get_fixers_from_package
+ from lib2to3.pgen2.parse import ParseError
+ fixers = get_fixers_from_package('lib2to3.fixes')
+ refactoring_tool = RefactoringTool(fixers)
+ source = refactoring_tool._read_python_source(filepath)[0]
+ try:
+ tree = refactoring_tool.refactor_string(source, 'conf.py')
+ except ParseError, err:
+ # do not propagate lib2to3 exceptions
+ lineno, offset = err.context[1]
+ # try to match ParseError details with SyntaxError details
+ raise SyntaxError(err.msg, (filepath, lineno, offset, err.value))
+ return unicode(tree)
+ from itertools import zip_longest # Python 3 name
+ import builtins
+
+else:
+ # Python 2
+ from types import ClassType
+ class_types = (type, ClassType)
+ b = str
+ bytes = str
+ u = 'u'
+ from StringIO import StringIO
+ BytesIO = StringIO
+ # no need to refactor on 2.x versions
+ convert_with_2to3 = None
+ def TextIOWrapper(stream, encoding):
+ return codecs.lookup(encoding or 'ascii')[2](stream)
+ # safely encode a string for printing to the terminal
+ def terminal_safe(s):
+ return s.encode('ascii', 'backslashreplace')
+ # some kind of default system encoding; should be used with a lenient
+ # error handler
+ import locale
+ sys_encoding = locale.getpreferredencoding()
+ # use Python 3 name
+ from itertools import izip_longest as zip_longest
+ import __builtin__ as builtins
+
+
+def execfile_(filepath, _globals):
+ from sphinx.util.osutil import fs_encoding
+ # get config source -- 'b' is a no-op under 2.x, while 'U' is
+ # ignored under 3.x (but 3.x compile() accepts \r\n newlines)
+ f = open(filepath, 'rbU')
+ try:
+ source = f.read()
+ finally:
+ f.close()
+
+ # py25,py26,py31 accept only LF eol instead of CRLF
+ if sys.version_info[:2] in ((2, 5), (2, 6), (3, 1)):
+ source = source.replace(b('\r\n'), b('\n'))
+
+ # compile to a code object, handle syntax errors
+ filepath_enc = filepath.encode(fs_encoding)
+ try:
+ code = compile(source, filepath_enc, 'exec')
+ except SyntaxError:
+ if convert_with_2to3:
+ # maybe the file uses 2.x syntax; try to refactor to
+ # 3.x syntax using 2to3
+ source = convert_with_2to3(filepath)
+ code = compile(source, filepath_enc, 'exec')
+ else:
+ raise
+ exec code in _globals
+
+
+try:
+ from html import escape as htmlescape
+except ImportError:
+ from cgi import escape as htmlescape
+
+# ------------------------------------------------------------------------------
+# Missing builtins and itertools in Python < 2.6
+
+if sys.version_info >= (2, 6):
+ # Python >= 2.6
+ next = next
+
+ from itertools import product
+ try:
+ from itertools import zip_longest # Python 3 name
+ except ImportError:
+ from itertools import izip_longest as zip_longest
+
+ import os
+ relpath = os.path.relpath
+ del os
+
+ import io
+ open = io.open
+
+else:
+ # Python < 2.6
+ from itertools import izip, repeat, chain
+
+ # this is on Python 2, where the method is called "next" (it is refactored
+ # to __next__ by 2to3, but in that case never executed)
+ def next(iterator):
+ return iterator.next()
+
+ # These replacement functions have been taken from the Python 2.6
+ # itertools documentation.
+ def product(*args, **kwargs):
+ pools = map(tuple, args) * kwargs.get('repeat', 1)
+ result = [[]]
+ for pool in pools:
+ result = [x + [y] for x in result for y in pool]
+ for prod in result:
+ yield tuple(prod)
+
+ def zip_longest(*args, **kwds):
+ # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
+ fillvalue = kwds.get('fillvalue')
+ def sentinel(counter = ([fillvalue]*(len(args)-1)).pop):
+ yield counter() # yields the fillvalue, or raises IndexError
+ fillers = repeat(fillvalue)
+ iters = [chain(it, sentinel(), fillers) for it in args]
+ try:
+ for tup in izip(*iters):
+ yield tup
+ except IndexError:
+ pass
+
+ from os.path import curdir
+ def relpath(path, start=curdir):
+ """Return a relative version of a path"""
+ from os.path import sep, abspath, commonprefix, join, pardir
+
+ if not path:
+ raise ValueError("no path specified")
+
+ start_list = abspath(start).split(sep)
+ path_list = abspath(path).split(sep)
+
+ # Work out how much of the filepath is shared by start and path.
+ i = len(commonprefix([start_list, path_list]))
+
+ rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
+ if not rel_list:
+ return start
+ return join(*rel_list)
+ del curdir
+
+ from types import MethodType
+ def open(filename, mode='r', *args, **kw):
+ newline = kw.pop('newline', None)
+ mode = mode.replace('t', '')
+ f = codecs.open(filename, mode, *args, **kw)
+ if newline is not None:
+ f._write = f.write
+ def write(self, text):
+ text = text.replace(u'\r\n', u'\n').replace(u'\n', newline)
+ self._write(text)
+ f.write = MethodType(write, f)
+ return f
+
+
+# ------------------------------------------------------------------------------
+# Missing builtins and codecs in Python < 2.5
+
+if sys.version_info >= (2, 5):
+ # Python >= 2.5
+ base_exception = BaseException
+ any = any
+ all = all
+
+else:
+ # Python 2.4
+ base_exception = Exception
+
+ def all(gen):
+ for i in gen:
+ if not i:
+ return False
+ return True
+
+ def any(gen):
+ for i in gen:
+ if i:
+ return True
+ return False
+
+ # Python 2.4 doesn't know the utf-8-sig encoding, so deliver it here
+
+ def my_search_function(encoding):
+ norm_encoding = encodings.normalize_encoding(encoding)
+ if norm_encoding != 'utf_8_sig':
+ return None
+ return (encode, decode, StreamReader, StreamWriter)
+
+ codecs.register(my_search_function)
+
+ # begin code copied from utf_8_sig.py in Python 2.6
+
+ def encode(input, errors='strict'):
+ return (codecs.BOM_UTF8 +
+ codecs.utf_8_encode(input, errors)[0], len(input))
+
+ def decode(input, errors='strict'):
+ prefix = 0
+ if input[:3] == codecs.BOM_UTF8:
+ input = input[3:]
+ prefix = 3
+ (output, consumed) = codecs.utf_8_decode(input, errors, True)
+ return (output, consumed+prefix)
+
+ class StreamWriter(codecs.StreamWriter):
+ def reset(self):
+ codecs.StreamWriter.reset(self)
+ try:
+ del self.encode
+ except AttributeError:
+ pass
+
+ def encode(self, input, errors='strict'):
+ self.encode = codecs.utf_8_encode
+ return encode(input, errors)
+
+ class StreamReader(codecs.StreamReader):
+ def reset(self):
+ codecs.StreamReader.reset(self)
+ try:
+ del self.decode
+ except AttributeError:
+ pass
+
+ def decode(self, input, errors='strict'):
+ if len(input) < 3:
+ if codecs.BOM_UTF8.startswith(input):
+ # not enough data to decide if this is a BOM
+ # => try again on the next call
+ return (u"", 0)
+ elif input[:3] == codecs.BOM_UTF8:
+ self.decode = codecs.utf_8_decode
+ (output, consumed) = codecs.utf_8_decode(input[3:],errors)
+ return (output, consumed+3)
+ # (else) no BOM present
+ self.decode = codecs.utf_8_decode
+ return codecs.utf_8_decode(input, errors)
+
+ # end code copied from utf_8_sig.py
diff --git a/sphinx/util/smartypants.py b/sphinx/util/smartypants.py
new file mode 100644
index 0000000..a92327d
--- /dev/null
+++ b/sphinx/util/smartypants.py
@@ -0,0 +1,299 @@
+r"""
+This is based on SmartyPants.py by `Chad Miller`_ <smartypantspy at chad.org>,
+version 1.5_1.6.
+
+Copyright and License
+=====================
+
+SmartyPants_ license::
+
+ Copyright (c) 2003 John Gruber
+ (http://daringfireball.net/)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name "SmartyPants" nor the names of its contributors
+ may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ 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
+ owner 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.
+
+
+smartypants.py license::
+
+ smartypants.py is a derivative work of SmartyPants.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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
+ owner 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.
+
+.. _Chad Miller: http://web.chad.org/
+"""
+
+import re
+
+
+def sphinx_smarty_pants(t):
+ t = t.replace('"', '"')
+ t = educate_dashes_oldschool(t)
+ t = educate_quotes(t)
+ t = t.replace('"', '"')
+ return t
+
+# Constants for quote education.
+
+punct_class = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]"""
+end_of_word_class = r"""[\s.,;:!?)]"""
+close_class = r"""[^\ \t\r\n\[\{\(\-]"""
+dec_dashes = r"""–|—"""
+
+# Special case if the very first character is a quote
+# followed by punctuation at a non-word-break. Close the quotes by brute force:
+single_quote_start_re = re.compile(r"""^'(?=%s\\B)""" % (punct_class,))
+double_quote_start_re = re.compile(r"""^"(?=%s\\B)""" % (punct_class,))
+
+# Special case for double sets of quotes, e.g.:
+# <p>He said, "'Quoted' words in a larger quote."</p>
+double_quote_sets_re = re.compile(r""""'(?=\w)""")
+single_quote_sets_re = re.compile(r"""'"(?=\w)""")
+
+# Special case for decade abbreviations (the '80s):
+decade_abbr_re = re.compile(r"""\b'(?=\d{2}s)""")
+
+# Get most opening double quotes:
+opening_double_quotes_regex = re.compile(r"""
+ (
+ \s | # a whitespace char, or
+ | # a non-breaking space entity, or
+ -- | # dashes, or
+ &[mn]dash; | # named dash entities
+ %s | # or decimal entities
+ &\#x201[34]; # or hex
+ )
+ " # the quote
+ (?=\w) # followed by a word character
+ """ % (dec_dashes,), re.VERBOSE)
+
+# Double closing quotes:
+closing_double_quotes_regex = re.compile(r"""
+ #(%s)? # character that indicates the quote should be closing
+ "
+ (?=%s)
+ """ % (close_class, end_of_word_class), re.VERBOSE)
+
+closing_double_quotes_regex_2 = re.compile(r"""
+ (%s) # character that indicates the quote should be closing
+ "
+ """ % (close_class,), re.VERBOSE)
+
+# Get most opening single quotes:
+opening_single_quotes_regex = re.compile(r"""
+ (
+ \s | # a whitespace char, or
+ | # a non-breaking space entity, or
+ -- | # dashes, or
+ &[mn]dash; | # named dash entities
+ %s | # or decimal entities
+ &\#x201[34]; # or hex
+ )
+ ' # the quote
+ (?=\w) # followed by a word character
+ """ % (dec_dashes,), re.VERBOSE)
+
+closing_single_quotes_regex = re.compile(r"""
+ (%s)
+ '
+ (?!\s | s\b | \d)
+ """ % (close_class,), re.VERBOSE)
+
+closing_single_quotes_regex_2 = re.compile(r"""
+ (%s)
+ '
+ (\s | s\b)
+ """ % (close_class,), re.VERBOSE)
+
+def educate_quotes(s):
+ """
+ Parameter: String.
+
+ Returns: The string, with "educated" curly quote HTML entities.
+
+ Example input: "Isn't this fun?"
+ Example output: “Isn’t this fun?”
+ """
+
+ # Special case if the very first character is a quote
+ # followed by punctuation at a non-word-break. Close the quotes
+ # by brute force:
+ s = single_quote_start_re.sub("’", s)
+ s = double_quote_start_re.sub("”", s)
+
+ # Special case for double sets of quotes, e.g.:
+ # <p>He said, "'Quoted' words in a larger quote."</p>
+ s = double_quote_sets_re.sub("“‘", s)
+ s = single_quote_sets_re.sub("‘“", s)
+
+ # Special case for decade abbreviations (the '80s):
+ s = decade_abbr_re.sub("’", s)
+
+ s = opening_single_quotes_regex.sub(r"\1‘", s)
+ s = closing_single_quotes_regex.sub(r"\1’", s)
+ s = closing_single_quotes_regex_2.sub(r"\1’\2", s)
+
+ # Any remaining single quotes should be opening ones:
+ s = s.replace("'", "‘")
+
+ s = opening_double_quotes_regex.sub(r"\1“", s)
+ s = closing_double_quotes_regex.sub(r"”", s)
+ s = closing_double_quotes_regex_2.sub(r"\1”", s)
+
+ # Any remaining quotes should be opening ones.
+ return s.replace('"', "“")
+
+
+def educate_quotes_latex(s, dquotes=("``", "''")):
+ """
+ Parameter: String.
+
+ Returns: The string, with double quotes corrected to LaTeX quotes.
+
+ Example input: "Isn't this fun?"
+ Example output: ``Isn't this fun?'';
+ """
+
+ # Special case if the very first character is a quote
+ # followed by punctuation at a non-word-break. Close the quotes
+ # by brute force:
+ s = single_quote_start_re.sub("\x04", s)
+ s = double_quote_start_re.sub("\x02", s)
+
+ # Special case for double sets of quotes, e.g.:
+ # <p>He said, "'Quoted' words in a larger quote."</p>
+ s = double_quote_sets_re.sub("\x01\x03", s)
+ s = single_quote_sets_re.sub("\x03\x01", s)
+
+ # Special case for decade abbreviations (the '80s):
+ s = decade_abbr_re.sub("\x04", s)
+
+ s = opening_single_quotes_regex.sub("\\1\x03", s)
+ s = closing_single_quotes_regex.sub("\\1\x04", s)
+ s = closing_single_quotes_regex_2.sub("\\1\x04\\2", s)
+
+ # Any remaining single quotes should be opening ones:
+ s = s.replace("'", "\x03")
+
+ s = opening_double_quotes_regex.sub("\\1\x01", s)
+ s = closing_double_quotes_regex.sub("\x02", s)
+ s = closing_double_quotes_regex_2.sub("\\1\x02", s)
+
+ # Any remaining quotes should be opening ones.
+ s = s.replace('"', "\x01")
+
+ # Finally, replace all helpers with quotes.
+ return s.replace("\x01", dquotes[0]).replace("\x02", dquotes[1]).\
+ replace("\x03", "`").replace("\x04", "'")
+
+
+def educate_backticks(s):
+ """
+ Parameter: String.
+ Returns: The string, with ``backticks'' -style double quotes
+ translated into HTML curly quote entities.
+ Example input: ``Isn't this fun?''
+ Example output: “Isn't this fun?”
+ """
+ return s.replace("``", "“").replace("''", "”")
+
+
+def educate_single_backticks(s):
+ """
+ Parameter: String.
+ Returns: The string, with `backticks' -style single quotes
+ translated into HTML curly quote entities.
+
+ Example input: `Isn't this fun?'
+ Example output: ‘Isn’t this fun?’
+ """
+ return s.replace('`', "‘").replace("'", "’")
+
+
+def educate_dashes_oldschool(s):
+ """
+ Parameter: String.
+
+ Returns: The string, with each instance of "--" translated to
+ an en-dash HTML entity, and each "---" translated to
+ an em-dash HTML entity.
+ """
+ return s.replace('---', "—").replace('--', "–")
+
+
+def educate_dashes_oldschool_inverted(s):
+ """
+ Parameter: String.
+
+ Returns: The string, with each instance of "--" translated to
+ an em-dash HTML entity, and each "---" translated to
+ an en-dash HTML entity. Two reasons why: First, unlike the
+ en- and em-dash syntax supported by
+ educate_dashes_oldschool(), it's compatible with existing
+ entries written before SmartyPants 1.1, back when "--" was
+ only used for em-dashes. Second, em-dashes are more
+ common than en-dashes, and so it sort of makes sense that
+ the shortcut should be shorter to type. (Thanks to Aaron
+ Swartz for the idea.)
+ """
+ return s.replace('---', "–").replace('--', "—")
+
+
+def educate_ellipses(s):
+ """
+ Parameter: String.
+ Returns: The string, with each instance of "..." translated to
+ an ellipsis HTML entity.
+
+ Example input: Huh...?
+ Example output: Huh…?
+ """
+ return s.replace('...', "…").replace('. . .', "…")
diff --git a/sphinx/util/stemmer.py b/sphinx/util/stemmer.py
new file mode 100644
index 0000000..10ce906
--- /dev/null
+++ b/sphinx/util/stemmer.py
@@ -0,0 +1,348 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.stemmer
+ ~~~~~~~~~~~~~~~~~~~
+
+ Porter Stemming Algorithm
+
+ This is the Porter stemming algorithm, ported to Python from the
+ version coded up in ANSI C by the author. It may be be regarded
+ as canonical, in that it follows the algorithm presented in
+
+ Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14,
+ no. 3, pp 130-137,
+
+ only differing from it at the points maked --DEPARTURE-- below.
+
+ See also http://www.tartarus.org/~martin/PorterStemmer
+
+ The algorithm as described in the paper could be exactly replicated
+ by adjusting the points of DEPARTURE, but this is barely necessary,
+ because (a) the points of DEPARTURE are definitely improvements, and
+ (b) no encoding of the Porter stemmer I have seen is anything like
+ as exact as this version, even with the points of DEPARTURE!
+
+ Release 1: January 2001
+
+ :copyright: Copyright 2001 by Vivake Gupta <v at nano.com>.
+ :license: Public Domain ("can be used free of charge for any purpose").
+"""
+
+class PorterStemmer(object):
+
+ def __init__(self):
+ """The main part of the stemming algorithm starts here.
+ b is a buffer holding a word to be stemmed. The letters are in b[k0],
+ b[k0+1] ... ending at b[k]. In fact k0 = 0 in this demo program. k is
+ readjusted downwards as the stemming progresses. Zero termination is
+ not in fact used in the algorithm.
+
+ Note that only lower case sequences are stemmed. Forcing to lower case
+ should be done before stem(...) is called.
+ """
+
+ self.b = "" # buffer for word to be stemmed
+ self.k = 0
+ self.k0 = 0
+ self.j = 0 # j is a general offset into the string
+
+ def cons(self, i):
+ """cons(i) is TRUE <=> b[i] is a consonant."""
+ if self.b[i] == 'a' or self.b[i] == 'e' or self.b[i] == 'i' \
+ or self.b[i] == 'o' or self.b[i] == 'u':
+ return 0
+ if self.b[i] == 'y':
+ if i == self.k0:
+ return 1
+ else:
+ return (not self.cons(i - 1))
+ return 1
+
+ def m(self):
+ """m() measures the number of consonant sequences between k0 and j.
+ if c is a consonant sequence and v a vowel sequence, and <..>
+ indicates arbitrary presence,
+
+ <c><v> gives 0
+ <c>vc<v> gives 1
+ <c>vcvc<v> gives 2
+ <c>vcvcvc<v> gives 3
+ ....
+ """
+ n = 0
+ i = self.k0
+ while 1:
+ if i > self.j:
+ return n
+ if not self.cons(i):
+ break
+ i = i + 1
+ i = i + 1
+ while 1:
+ while 1:
+ if i > self.j:
+ return n
+ if self.cons(i):
+ break
+ i = i + 1
+ i = i + 1
+ n = n + 1
+ while 1:
+ if i > self.j:
+ return n
+ if not self.cons(i):
+ break
+ i = i + 1
+ i = i + 1
+
+ def vowelinstem(self):
+ """vowelinstem() is TRUE <=> k0,...j contains a vowel"""
+ for i in range(self.k0, self.j + 1):
+ if not self.cons(i):
+ return 1
+ return 0
+
+ def doublec(self, j):
+ """doublec(j) is TRUE <=> j,(j-1) contain a double consonant."""
+ if j < (self.k0 + 1):
+ return 0
+ if (self.b[j] != self.b[j-1]):
+ return 0
+ return self.cons(j)
+
+ def cvc(self, i):
+ """cvc(i) is TRUE <=> i-2,i-1,i has the form
+ consonant - vowel - consonant
+ and also if the second c is not w,x or y. this is used when trying to
+ restore an e at the end of a short e.g.
+
+ cav(e), lov(e), hop(e), crim(e), but
+ snow, box, tray.
+ """
+ if i < (self.k0 + 2) or not self.cons(i) or self.cons(i-1) \
+ or not self.cons(i-2):
+ return 0
+ ch = self.b[i]
+ if ch == 'w' or ch == 'x' or ch == 'y':
+ return 0
+ return 1
+
+ def ends(self, s):
+ """ends(s) is TRUE <=> k0,...k ends with the string s."""
+ length = len(s)
+ if s[length - 1] != self.b[self.k]: # tiny speed-up
+ return 0
+ if length > (self.k - self.k0 + 1):
+ return 0
+ if self.b[self.k-length+1:self.k+1] != s:
+ return 0
+ self.j = self.k - length
+ return 1
+
+ def setto(self, s):
+ """setto(s) sets (j+1),...k to the characters in the string s,
+ readjusting k."""
+ length = len(s)
+ self.b = self.b[:self.j+1] + s + self.b[self.j+length+1:]
+ self.k = self.j + length
+
+ def r(self, s):
+ """r(s) is used further down."""
+ if self.m() > 0:
+ self.setto(s)
+
+ def step1ab(self):
+ """step1ab() gets rid of plurals and -ed or -ing. e.g.
+
+ caresses -> caress
+ ponies -> poni
+ ties -> ti
+ caress -> caress
+ cats -> cat
+
+ feed -> feed
+ agreed -> agree
+ disabled -> disable
+
+ matting -> mat
+ mating -> mate
+ meeting -> meet
+ milling -> mill
+ messing -> mess
+
+ meetings -> meet
+ """
+ if self.b[self.k] == 's':
+ if self.ends("sses"):
+ self.k = self.k - 2
+ elif self.ends("ies"):
+ self.setto("i")
+ elif self.b[self.k - 1] != 's':
+ self.k = self.k - 1
+ if self.ends("eed"):
+ if self.m() > 0:
+ self.k = self.k - 1
+ elif (self.ends("ed") or self.ends("ing")) and self.vowelinstem():
+ self.k = self.j
+ if self.ends("at"): self.setto("ate")
+ elif self.ends("bl"): self.setto("ble")
+ elif self.ends("iz"): self.setto("ize")
+ elif self.doublec(self.k):
+ self.k = self.k - 1
+ ch = self.b[self.k]
+ if ch == 'l' or ch == 's' or ch == 'z':
+ self.k = self.k + 1
+ elif (self.m() == 1 and self.cvc(self.k)):
+ self.setto("e")
+
+ def step1c(self):
+ """step1c() turns terminal y to i when there is another vowel in
+ the stem."""
+ if (self.ends("y") and self.vowelinstem()):
+ self.b = self.b[:self.k] + 'i' + self.b[self.k+1:]
+
+ def step2(self):
+ """step2() maps double suffices to single ones.
+ so -ization ( = -ize plus -ation) maps to -ize etc. note that the
+ string before the suffix must give m() > 0.
+ """
+ if self.b[self.k - 1] == 'a':
+ if self.ends("ational"): self.r("ate")
+ elif self.ends("tional"): self.r("tion")
+ elif self.b[self.k - 1] == 'c':
+ if self.ends("enci"): self.r("ence")
+ elif self.ends("anci"): self.r("ance")
+ elif self.b[self.k - 1] == 'e':
+ if self.ends("izer"): self.r("ize")
+ elif self.b[self.k - 1] == 'l':
+ if self.ends("bli"): self.r("ble") # --DEPARTURE--
+ # To match the published algorithm, replace this phrase with
+ # if self.ends("abli"): self.r("able")
+ elif self.ends("alli"): self.r("al")
+ elif self.ends("entli"): self.r("ent")
+ elif self.ends("eli"): self.r("e")
+ elif self.ends("ousli"): self.r("ous")
+ elif self.b[self.k - 1] == 'o':
+ if self.ends("ization"): self.r("ize")
+ elif self.ends("ation"): self.r("ate")
+ elif self.ends("ator"): self.r("ate")
+ elif self.b[self.k - 1] == 's':
+ if self.ends("alism"): self.r("al")
+ elif self.ends("iveness"): self.r("ive")
+ elif self.ends("fulness"): self.r("ful")
+ elif self.ends("ousness"): self.r("ous")
+ elif self.b[self.k - 1] == 't':
+ if self.ends("aliti"): self.r("al")
+ elif self.ends("iviti"): self.r("ive")
+ elif self.ends("biliti"): self.r("ble")
+ elif self.b[self.k - 1] == 'g': # --DEPARTURE--
+ if self.ends("logi"): self.r("log")
+ # To match the published algorithm, delete this phrase
+
+ def step3(self):
+ """step3() dels with -ic-, -full, -ness etc. similar strategy
+ to step2."""
+ if self.b[self.k] == 'e':
+ if self.ends("icate"): self.r("ic")
+ elif self.ends("ative"): self.r("")
+ elif self.ends("alize"): self.r("al")
+ elif self.b[self.k] == 'i':
+ if self.ends("iciti"): self.r("ic")
+ elif self.b[self.k] == 'l':
+ if self.ends("ical"): self.r("ic")
+ elif self.ends("ful"): self.r("")
+ elif self.b[self.k] == 's':
+ if self.ends("ness"): self.r("")
+
+ def step4(self):
+ """step4() takes off -ant, -ence etc., in context <c>vcvc<v>."""
+ if self.b[self.k - 1] == 'a':
+ if self.ends("al"): pass
+ else: return
+ elif self.b[self.k - 1] == 'c':
+ if self.ends("ance"): pass
+ elif self.ends("ence"): pass
+ else: return
+ elif self.b[self.k - 1] == 'e':
+ if self.ends("er"): pass
+ else: return
+ elif self.b[self.k - 1] == 'i':
+ if self.ends("ic"): pass
+ else: return
+ elif self.b[self.k - 1] == 'l':
+ if self.ends("able"): pass
+ elif self.ends("ible"): pass
+ else: return
+ elif self.b[self.k - 1] == 'n':
+ if self.ends("ant"): pass
+ elif self.ends("ement"): pass
+ elif self.ends("ment"): pass
+ elif self.ends("ent"): pass
+ else: return
+ elif self.b[self.k - 1] == 'o':
+ if self.ends("ion") and (self.b[self.j] == 's' \
+ or self.b[self.j] == 't'): pass
+ elif self.ends("ou"): pass
+ # takes care of -ous
+ else: return
+ elif self.b[self.k - 1] == 's':
+ if self.ends("ism"): pass
+ else: return
+ elif self.b[self.k - 1] == 't':
+ if self.ends("ate"): pass
+ elif self.ends("iti"): pass
+ else: return
+ elif self.b[self.k - 1] == 'u':
+ if self.ends("ous"): pass
+ else: return
+ elif self.b[self.k - 1] == 'v':
+ if self.ends("ive"): pass
+ else: return
+ elif self.b[self.k - 1] == 'z':
+ if self.ends("ize"): pass
+ else: return
+ else:
+ return
+ if self.m() > 1:
+ self.k = self.j
+
+ def step5(self):
+ """step5() removes a final -e if m() > 1, and changes -ll to -l if
+ m() > 1.
+ """
+ self.j = self.k
+ if self.b[self.k] == 'e':
+ a = self.m()
+ if a > 1 or (a == 1 and not self.cvc(self.k-1)):
+ self.k = self.k - 1
+ if self.b[self.k] == 'l' and self.doublec(self.k) and self.m() > 1:
+ self.k = self.k -1
+
+ def stem(self, p, i, j):
+ """In stem(p,i,j), p is a char pointer, and the string to be stemmed
+ is from p[i] to p[j] inclusive. Typically i is zero and j is the
+ offset to the last character of a string, (p[j+1] == '\0'). The
+ stemmer adjusts the characters p[i] ... p[j] and returns the new
+ end-point of the string, k. Stemming never increases word length, so
+ i <= k <= j. To turn the stemmer into a module, declare 'stem' as
+ extern, and delete the remainder of this file.
+ """
+ # copy the parameters into statics
+ self.b = p
+ self.k = j
+ self.k0 = i
+ if self.k <= self.k0 + 1:
+ return self.b # --DEPARTURE--
+
+ # With this line, strings of length 1 or 2 don't go through the
+ # stemming process, although no mention is made of this in the
+ # published algorithm. Remove the line to match the published
+ # algorithm.
+
+ self.step1ab()
+ self.step1c()
+ self.step2()
+ self.step3()
+ self.step4()
+ self.step5()
+ return self.b[self.k0:self.k+1]
diff --git a/sphinx/util/tags.py b/sphinx/util/tags.py
new file mode 100644
index 0000000..2a9b2a0
--- /dev/null
+++ b/sphinx/util/tags.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.tags
+ ~~~~~~~~~~~~~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import warnings
+# jinja2.sandbox imports the sets module on purpose
+warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
+ module='jinja2.sandbox')
+
+# (ab)use the Jinja parser for parsing our boolean expressions
+from jinja2 import nodes
+from jinja2.parser import Parser
+from jinja2.environment import Environment
+
+env = Environment()
+
+
+class BooleanParser(Parser):
+ """
+ Only allow condition exprs and/or/not operations.
+ """
+
+ def parse_compare(self):
+ token = self.stream.current
+ if token.type == 'name':
+ if token.value in ('true', 'false', 'True', 'False'):
+ node = nodes.Const(token.value in ('true', 'True'),
+ lineno=token.lineno)
+ elif token.value in ('none', 'None'):
+ node = nodes.Const(None, lineno=token.lineno)
+ else:
+ node = nodes.Name(token.value, 'load', lineno=token.lineno)
+ self.stream.next()
+ elif token.type == 'lparen':
+ self.stream.next()
+ node = self.parse_expression()
+ self.stream.expect('rparen')
+ else:
+ self.fail("unexpected token '%s'" % (token,), token.lineno)
+ return node
+
+
+class Tags(object):
+ def __init__(self, tags=None):
+ self.tags = dict.fromkeys(tags or [], True)
+
+ def has(self, tag):
+ return tag in self.tags
+
+ __contains__ = has
+
+ def __iter__(self):
+ return iter(self.tags)
+
+ def add(self, tag):
+ self.tags[tag] = True
+
+ def remove(self, tag):
+ self.tags.pop(tag, None)
+
+ def eval_condition(self, condition):
+ # exceptions are handled by the caller
+ parser = BooleanParser(env, condition, state='variable')
+ expr = parser.parse_expression()
+ if not parser.stream.eos:
+ raise ValueError('chunk after expression')
+
+ def eval_node(node):
+ if isinstance(node, nodes.CondExpr):
+ if eval_node(node.test):
+ return eval_node(node.expr1)
+ else:
+ return eval_node(node.expr2)
+ elif isinstance(node, nodes.And):
+ return eval_node(node.left) and eval_node(node.right)
+ elif isinstance(node, nodes.Or):
+ return eval_node(node.left) or eval_node(node.right)
+ elif isinstance(node, nodes.Not):
+ return not eval_node(node.node)
+ elif isinstance(node, nodes.Name):
+ return self.tags.get(node.name, False)
+ else:
+ raise ValueError('invalid node, check parsing')
+
+ return eval_node(expr)
diff --git a/sphinx/util/texescape.py b/sphinx/util/texescape.py
new file mode 100644
index 0000000..c0619f4
--- /dev/null
+++ b/sphinx/util/texescape.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.texescape
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ TeX escaping helper.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+tex_replacements = [
+ # map TeX special chars
+ (u'$', ur'\$'),
+ (u'%', ur'\%'),
+ (u'&', ur'\&'),
+ (u'#', ur'\#'),
+ (u'_', ur'\_'),
+ (u'{', ur'\{'),
+ (u'}', ur'\}'),
+ (u'[', ur'{[}'),
+ (u']', ur'{]}'),
+ (u'`', ur'{}`'),
+ (u'\\',ur'\textbackslash{}'),
+ (u'~', ur'\textasciitilde{}'),
+ (u'<', ur'\textless{}'),
+ (u'>', ur'\textgreater{}'),
+ (u'^', ur'\textasciicircum{}'),
+ # map special Unicode characters to TeX commands
+ (u'¶', ur'\P{}'),
+ (u'§', ur'\S{}'),
+ (u'€', ur'\texteuro{}'),
+ (u'∞', ur'\(\infty\)'),
+ (u'±', ur'\(\pm\)'),
+ (u'→', ur'\(\rightarrow\)'),
+ (u'‣', ur'\(\rightarrow\)'),
+ # used to separate -- in options
+ (u'', ur'{}'),
+ # map some special Unicode characters to similar ASCII ones
+ (u'─', ur'-'),
+ (u'⎽', ur'\_'),
+ (u'╲', ur'\textbackslash{}'),
+ (u'|', ur'\textbar{}'),
+ (u'│', ur'\textbar{}'),
+ (u'ℯ', ur'e'),
+ (u'ⅈ', ur'i'),
+ (u'₁', ur'1'),
+ (u'₂', ur'2'),
+ # map Greek alphabet
+ (u'α', ur'\(\alpha\)'),
+ (u'β', ur'\(\beta\)'),
+ (u'γ', ur'\(\gamma\)'),
+ (u'δ', ur'\(\delta\)'),
+ (u'ε', ur'\(\epsilon\)'),
+ (u'ζ', ur'\(\zeta\)'),
+ (u'η', ur'\(\eta\)'),
+ (u'θ', ur'\(\theta\)'),
+ (u'ι', ur'\(\iota\)'),
+ (u'κ', ur'\(\kappa\)'),
+ (u'λ', ur'\(\lambda\)'),
+ (u'μ', ur'\(\mu\)'),
+ (u'ν', ur'\(\nu\)'),
+ (u'ξ', ur'\(\xi\)'),
+ (u'ο', ur'o'),
+ (u'π', ur'\(\pi\)'),
+ (u'ρ', ur'\(\rho\)'),
+ (u'σ', ur'\(\sigma\)'),
+ (u'τ', ur'\(\tau\)'),
+ (u'υ', u'\\(\\upsilon\\)'),
+ (u'φ', ur'\(\phi\)'),
+ (u'χ', ur'\(\chi\)'),
+ (u'ψ', ur'\(\psi\)'),
+ (u'ω', ur'\(\omega\)'),
+ (u'Α', ur'A'),
+ (u'Β', ur'B'),
+ (u'Γ', ur'\(\Gamma\)'),
+ (u'Δ', ur'\(\Delta\)'),
+ (u'Ε', ur'E'),
+ (u'Ζ', ur'Z'),
+ (u'Η', ur'H'),
+ (u'Θ', ur'\(\Theta\)'),
+ (u'Ι', ur'I'),
+ (u'Κ', ur'K'),
+ (u'Λ', ur'\(\Lambda\)'),
+ (u'Μ', ur'M'),
+ (u'Ν', ur'N'),
+ (u'Ξ', ur'\(\Xi\)'),
+ (u'Ο', ur'O'),
+ (u'Π', ur'\(\Pi\)'),
+ (u'Ρ', ur'P'),
+ (u'Σ', ur'\(\Sigma\)'),
+ (u'Τ', ur'T'),
+ (u'Υ', u'\\(\\Upsilon\\)'),
+ (u'Φ', ur'\(\Phi\)'),
+ (u'Χ', ur'X'),
+ (u'Ψ', ur'\(\Psi\)'),
+ (u'Ω', ur'\(\Omega\)'),
+ (u'Ω', ur'\(\Omega\)'),
+]
+
+tex_escape_map = {}
+tex_replace_map = {}
+tex_hl_escape_map_new = {}
+
+def init():
+ for a, b in tex_replacements:
+ tex_escape_map[ord(a)] = b
+ tex_replace_map[ord(a)] = u'_'
+
+ for a, b in tex_replacements:
+ if a in u'[]{}\\': continue
+ tex_hl_escape_map_new[ord(a)] = b
diff --git a/sphinx/util/websupport.py b/sphinx/util/websupport.py
new file mode 100644
index 0000000..65c4829
--- /dev/null
+++ b/sphinx/util/websupport.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.websupport
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+
+def is_commentable(node):
+ #return node.__class__.__name__ in ('paragraph', 'literal_block')
+ return node.__class__.__name__ == 'paragraph'
diff --git a/sphinx/versioning.py b/sphinx/versioning.py
new file mode 100644
index 0000000..f10e0f2
--- /dev/null
+++ b/sphinx/versioning.py
@@ -0,0 +1,127 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.versioning
+ ~~~~~~~~~~~~~~~~~
+
+ Implements the low-level algorithms Sphinx uses for the versioning of
+ doctrees.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from uuid import uuid4
+from operator import itemgetter
+
+from sphinx.util.pycompat import product, zip_longest, all
+
+
+# anything below that ratio is considered equal/changed
+VERSIONING_RATIO = 65
+
+
+def add_uids(doctree, condition):
+ """Add a unique id to every node in the `doctree` which matches the
+ condition and yield the nodes.
+
+ :param doctree:
+ A :class:`docutils.nodes.document` instance.
+
+ :param condition:
+ A callable which returns either ``True`` or ``False`` for a given node.
+ """
+ for node in doctree.traverse(condition):
+ node.uid = uuid4().hex
+ yield node
+
+
+def merge_doctrees(old, new, condition):
+ """Merge the `old` doctree with the `new` one while looking at nodes
+ matching the `condition`.
+
+ Each node which replaces another one or has been added to the `new` doctree
+ will be yielded.
+
+ :param condition:
+ A callable which returns either ``True`` or ``False`` for a given node.
+ """
+ old_iter = old.traverse(condition)
+ new_iter = new.traverse(condition)
+ old_nodes = []
+ new_nodes = []
+ ratios = {}
+ seen = set()
+ # compare the nodes each doctree in order
+ for old_node, new_node in zip_longest(old_iter, new_iter):
+ if old_node is None:
+ new_nodes.append(new_node)
+ continue
+ if new_node is None:
+ old_nodes.append(old_node)
+ continue
+ ratio = get_ratio(old_node.rawsource, new_node.rawsource)
+ if ratio == 0:
+ new_node.uid = old_node.uid
+ seen.add(new_node)
+ else:
+ ratios[old_node, new_node] = ratio
+ old_nodes.append(old_node)
+ new_nodes.append(new_node)
+ # calculate the ratios for each unequal pair of nodes, should we stumble
+ # on a pair which is equal we set the uid and add it to the seen ones
+ for old_node, new_node in product(old_nodes, new_nodes):
+ if new_node in seen or (old_node, new_node) in ratios:
+ continue
+ ratio = get_ratio(old_node.rawsource, new_node.rawsource)
+ if ratio == 0:
+ new_node.uid = old_node.uid
+ seen.add(new_node)
+ else:
+ ratios[old_node, new_node] = ratio
+ # choose the old node with the best ratio for each new node and set the uid
+ # as long as the ratio is under a certain value, in which case we consider
+ # them not changed but different
+ ratios = sorted(ratios.iteritems(), key=itemgetter(1))
+ for (old_node, new_node), ratio in ratios:
+ if new_node in seen:
+ continue
+ else:
+ seen.add(new_node)
+ if ratio < VERSIONING_RATIO:
+ new_node.uid = old_node.uid
+ else:
+ new_node.uid = uuid4().hex
+ yield new_node
+ # create new uuids for any new node we left out earlier, this happens
+ # if one or more nodes are simply added.
+ for new_node in set(new_nodes) - seen:
+ new_node.uid = uuid4().hex
+ yield new_node
+
+
+def get_ratio(old, new):
+ """Return a "similiarity ratio" (in percent) representing the similarity
+ between the two strings where 0 is equal and anything above less than equal.
+ """
+ if not all([old, new]):
+ return VERSIONING_RATIO
+ return levenshtein_distance(old, new) / (len(old) / 100.0)
+
+
+def levenshtein_distance(a, b):
+ """Return the Levenshtein edit distance between two strings *a* and *b*."""
+ if a == b:
+ return 0
+ if len(a) < len(b):
+ a, b = b, a
+ if not a:
+ return len(b)
+ previous_row = xrange(len(b) + 1)
+ for i, column1 in enumerate(a):
+ current_row = [i + 1]
+ for j, column2 in enumerate(b):
+ insertions = previous_row[j + 1] + 1
+ deletions = current_row[j] + 1
+ substitutions = previous_row[j] + (column1 != column2)
+ current_row.append(min(insertions, deletions, substitutions))
+ previous_row = current_row
+ return previous_row[-1]
diff --git a/sphinx/websupport/__init__.py b/sphinx/websupport/__init__.py
new file mode 100644
index 0000000..0e9131d
--- /dev/null
+++ b/sphinx/websupport/__init__.py
@@ -0,0 +1,458 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport
+ ~~~~~~~~~~~~~~~~~
+
+ Base Module for web support functions.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import cPickle as pickle
+import posixpath
+from os import path
+
+from jinja2 import Environment, FileSystemLoader
+
+from docutils.core import publish_parts
+
+from sphinx.application import Sphinx
+from sphinx.locale import _
+from sphinx.util.osutil import ensuredir
+from sphinx.util.jsonimpl import dumps as dump_json
+from sphinx.util.pycompat import htmlescape
+from sphinx.websupport import errors
+from sphinx.websupport.search import BaseSearch, SEARCH_ADAPTERS
+from sphinx.websupport.storage import StorageBackend
+
+
+class WebSupport(object):
+ """The main API class for the web support package. All interactions
+ with the web support package should occur through this class.
+ """
+ def __init__(self,
+ srcdir=None, # only required for building
+ builddir='', # the dir with data/static/doctrees subdirs
+ datadir=None, # defaults to builddir/data
+ staticdir=None, # defaults to builddir/static
+ doctreedir=None, # defaults to builddir/doctrees
+ search=None, # defaults to no search
+ storage=None, # defaults to SQLite in datadir
+ status=sys.stdout,
+ warning=sys.stderr,
+ moderation_callback=None,
+ allow_anonymous_comments=True,
+ docroot='',
+ staticroot='static',
+ ):
+ # directories
+ self.srcdir = srcdir
+ self.builddir = builddir
+ self.outdir = path.join(builddir, 'data')
+ self.datadir = datadir or self.outdir
+ self.staticdir = staticdir or path.join(self.builddir, 'static')
+ self.doctreedir = staticdir or path.join(self.builddir, 'doctrees')
+ # web server virtual paths
+ self.staticroot = staticroot.strip('/')
+ self.docroot = docroot.strip('/')
+
+ self.status = status
+ self.warning = warning
+ self.moderation_callback = moderation_callback
+ self.allow_anonymous_comments = allow_anonymous_comments
+
+ self._init_templating()
+ self._init_search(search)
+ self._init_storage(storage)
+
+ self._globalcontext = None
+
+ self._make_base_comment_options()
+
+ def _init_storage(self, storage):
+ if isinstance(storage, StorageBackend):
+ self.storage = storage
+ else:
+ # If a StorageBackend isn't provided, use the default
+ # SQLAlchemy backend.
+ from sphinx.websupport.storage.sqlalchemystorage \
+ import SQLAlchemyStorage
+ if not storage:
+ # no explicit DB path given; create default sqlite database
+ db_path = path.join(self.datadir, 'db', 'websupport.db')
+ ensuredir(path.dirname(db_path))
+ storage = 'sqlite:///' + db_path
+ self.storage = SQLAlchemyStorage(storage)
+
+ def _init_templating(self):
+ import sphinx
+ template_path = path.join(sphinx.package_dir,
+ 'themes', 'basic')
+ loader = FileSystemLoader(template_path)
+ self.template_env = Environment(loader=loader)
+
+ def _init_search(self, search):
+ if isinstance(search, BaseSearch):
+ self.search = search
+ else:
+ mod, cls = SEARCH_ADAPTERS[search or 'null']
+ mod = 'sphinx.websupport.search.' + mod
+ SearchClass = getattr(__import__(mod, None, None, [cls]), cls)
+ search_path = path.join(self.datadir, 'search')
+ self.search = SearchClass(search_path)
+ self.results_template = \
+ self.template_env.get_template('searchresults.html')
+
+ def build(self):
+ """Build the documentation. Places the data into the `outdir`
+ directory. Use it like this::
+
+ support = WebSupport(srcdir, builddir, search='xapian')
+ support.build()
+
+ This will read reStructured text files from `srcdir`. Then it will
+ build the pickles and search index, placing them into `builddir`.
+ It will also save node data to the database.
+ """
+ if not self.srcdir:
+ raise RuntimeError('No srcdir associated with WebSupport object')
+ app = Sphinx(self.srcdir, self.srcdir, self.outdir, self.doctreedir,
+ 'websupport', status=self.status, warning=self.warning)
+ app.builder.set_webinfo(self.staticdir, self.staticroot,
+ self.search, self.storage)
+
+ self.storage.pre_build()
+ app.build()
+ self.storage.post_build()
+
+ def get_globalcontext(self):
+ """Load and return the "global context" pickle."""
+ if not self._globalcontext:
+ infilename = path.join(self.datadir, 'globalcontext.pickle')
+ f = open(infilename, 'rb')
+ try:
+ self._globalcontext = pickle.load(f)
+ finally:
+ f.close()
+ return self._globalcontext
+
+ def get_document(self, docname, username='', moderator=False):
+ """Load and return a document from a pickle. The document will
+ be a dict object which can be used to render a template::
+
+ support = WebSupport(datadir=datadir)
+ support.get_document('index', username, moderator)
+
+ In most cases `docname` will be taken from the request path and
+ passed directly to this function. In Flask, that would be something
+ like this::
+
+ @app.route('/<path:docname>')
+ def index(docname):
+ username = g.user.name if g.user else ''
+ moderator = g.user.moderator if g.user else False
+ try:
+ document = support.get_document(docname, username,
+ moderator)
+ except DocumentNotFoundError:
+ abort(404)
+ render_template('doc.html', document=document)
+
+ The document dict that is returned contains the following items
+ to be used during template rendering.
+
+ * **body**: The main body of the document as HTML
+ * **sidebar**: The sidebar of the document as HTML
+ * **relbar**: A div containing links to related documents
+ * **title**: The title of the document
+ * **css**: Links to css files used by Sphinx
+ * **script**: Javascript containing comment options
+
+ This raises :class:`~sphinx.websupport.errors.DocumentNotFoundError`
+ if a document matching `docname` is not found.
+
+ :param docname: the name of the document to load.
+ """
+ docpath = path.join(self.datadir, 'pickles', docname)
+ if path.isdir(docpath):
+ infilename = docpath + '/index.fpickle'
+ if not docname:
+ docname = 'index'
+ else:
+ docname += '/index'
+ else:
+ infilename = docpath + '.fpickle'
+
+ try:
+ f = open(infilename, 'rb')
+ except IOError:
+ raise errors.DocumentNotFoundError(
+ 'The document "%s" could not be found' % docname)
+ try:
+ document = pickle.load(f)
+ finally:
+ f.close()
+
+ comment_opts = self._make_comment_options(username, moderator)
+ comment_meta = self._make_metadata(
+ self.storage.get_metadata(docname, moderator))
+
+ document['script'] = comment_opts + comment_meta + document['script']
+ return document
+
+ def get_search_results(self, q):
+ """Perform a search for the query `q`, and create a set
+ of search results. Then render the search results as html and
+ return a context dict like the one created by
+ :meth:`get_document`::
+
+ document = support.get_search_results(q)
+
+ :param q: the search query
+ """
+ results = self.search.query(q)
+ ctx = {
+ 'q': q,
+ 'search_performed': True,
+ 'search_results': results,
+ 'docroot': '../', # XXX
+ '_': _,
+ }
+ document = {
+ 'body': self.results_template.render(ctx),
+ 'title': 'Search Results',
+ 'sidebar': '',
+ 'relbar': ''
+ }
+ return document
+
+ def get_data(self, node_id, username=None, moderator=False):
+ """Get the comments and source associated with `node_id`. If
+ `username` is given vote information will be included with the
+ returned comments. The default CommentBackend returns a dict with
+ two keys, *source*, and *comments*. *source* is raw source of the
+ node and is used as the starting point for proposals a user can
+ add. *comments* is a list of dicts that represent a comment, each
+ having the following items:
+
+ ============= ======================================================
+ Key Contents
+ ============= ======================================================
+ text The comment text.
+ username The username that was stored with the comment.
+ id The comment's unique identifier.
+ rating The comment's current rating.
+ age The time in seconds since the comment was added.
+ time A dict containing time information. It contains the
+ following keys: year, month, day, hour, minute, second,
+ iso, and delta. `iso` is the time formatted in ISO
+ 8601 format. `delta` is a printable form of how old
+ the comment is (e.g. "3 hours ago").
+ vote If `user_id` was given, this will be an integer
+ representing the vote. 1 for an upvote, -1 for a
+ downvote, or 0 if unvoted.
+ node The id of the node that the comment is attached to.
+ If the comment's parent is another comment rather than
+ a node, this will be null.
+ parent The id of the comment that this comment is attached
+ to if it is not attached to a node.
+ children A list of all children, in this format.
+ proposal_diff An HTML representation of the differences between the
+ the current source and the user's proposed source.
+ ============= ======================================================
+
+ :param node_id: the id of the node to get comments for.
+ :param username: the username of the user viewing the comments.
+ :param moderator: whether the user is a moderator.
+ """
+ return self.storage.get_data(node_id, username, moderator)
+
+ def delete_comment(self, comment_id, username='', moderator=False):
+ """Delete a comment.
+
+ If `moderator` is True, the comment and all descendants will be deleted
+ from the database, and the function returns ``True``.
+
+ If `moderator` is False, the comment will be marked as deleted (but not
+ removed from the database so as not to leave any comments orphaned), but
+ only if the `username` matches the `username` on the comment. The
+ username and text files are replaced with "[deleted]" . In this case,
+ the function returns ``False``.
+
+ This raises :class:`~sphinx.websupport.errors.UserNotAuthorizedError`
+ if moderator is False and `username` doesn't match username on the
+ comment.
+
+ :param comment_id: the id of the comment to delete.
+ :param username: the username requesting the deletion.
+ :param moderator: whether the requestor is a moderator.
+ """
+ return self.storage.delete_comment(comment_id, username, moderator)
+
+ def add_comment(self, text, node_id='', parent_id='', displayed=True,
+ username=None, time=None, proposal=None,
+ moderator=False):
+ """Add a comment to a node or another comment. Returns the comment
+ in the same format as :meth:`get_comments`. If the comment is being
+ attached to a node, pass in the node's id (as a string) with the
+ node keyword argument::
+
+ comment = support.add_comment(text, node_id=node_id)
+
+ If the comment is the child of another comment, provide the parent's
+ id (as a string) with the parent keyword argument::
+
+ comment = support.add_comment(text, parent_id=parent_id)
+
+ If you would like to store a username with the comment, pass
+ in the optional `username` keyword argument::
+
+ comment = support.add_comment(text, node=node_id,
+ username=username)
+
+ :param parent_id: the prefixed id of the comment's parent.
+ :param text: the text of the comment.
+ :param displayed: for moderation purposes
+ :param username: the username of the user making the comment.
+ :param time: the time the comment was created, defaults to now.
+ """
+ if username is None:
+ if self.allow_anonymous_comments:
+ username = 'Anonymous'
+ else:
+ raise errors.UserNotAuthorizedError()
+ parsed = self._parse_comment_text(text)
+ comment = self.storage.add_comment(parsed, displayed, username,
+ time, proposal, node_id,
+ parent_id, moderator)
+ comment['original_text'] = text
+ if not displayed and self.moderation_callback:
+ self.moderation_callback(comment)
+ return comment
+
+ def process_vote(self, comment_id, username, value):
+ """Process a user's vote. The web support package relies
+ on the API user to perform authentication. The API user will
+ typically receive a comment_id and value from a form, and then
+ make sure the user is authenticated. A unique username must be
+ passed in, which will also be used to retrieve the user's past
+ voting data. An example, once again in Flask::
+
+ @app.route('/docs/process_vote', methods=['POST'])
+ def process_vote():
+ if g.user is None:
+ abort(401)
+ comment_id = request.form.get('comment_id')
+ value = request.form.get('value')
+ if value is None or comment_id is None:
+ abort(400)
+ support.process_vote(comment_id, g.user.name, value)
+ return "success"
+
+ :param comment_id: the comment being voted on
+ :param username: the unique username of the user voting
+ :param value: 1 for an upvote, -1 for a downvote, 0 for an unvote.
+ """
+ value = int(value)
+ if not -1 <= value <= 1:
+ raise ValueError('vote value %s out of range (-1, 1)' % value)
+ self.storage.process_vote(comment_id, username, value)
+
+ def update_username(self, old_username, new_username):
+ """To remain decoupled from a webapp's authentication system, the
+ web support package stores a user's username with each of their
+ comments and votes. If the authentication system allows a user to
+ change their username, this can lead to stagnate data in the web
+ support system. To avoid this, each time a username is changed, this
+ method should be called.
+
+ :param old_username: The original username.
+ :param new_username: The new username.
+ """
+ self.storage.update_username(old_username, new_username)
+
+ def accept_comment(self, comment_id, moderator=False):
+ """Accept a comment that is pending moderation.
+
+ This raises :class:`~sphinx.websupport.errors.UserNotAuthorizedError`
+ if moderator is False.
+
+ :param comment_id: The id of the comment that was accepted.
+ :param moderator: Whether the user making the request is a moderator.
+ """
+ if not moderator:
+ raise errors.UserNotAuthorizedError()
+ self.storage.accept_comment(comment_id)
+
+ def _make_base_comment_options(self):
+ """Helper method to create the part of the COMMENT_OPTIONS javascript
+ that remains the same throughout the lifetime of the
+ :class:`~sphinx.websupport.WebSupport` object.
+ """
+ self.base_comment_opts = {}
+
+ if self.docroot != '':
+ comment_urls = [
+ ('addCommentURL', '_add_comment'),
+ ('getCommentsURL', '_get_comments'),
+ ('processVoteURL', '_process_vote'),
+ ('acceptCommentURL', '_accept_comment'),
+ ('deleteCommentURL', '_delete_comment')
+ ]
+ for key, value in comment_urls:
+ self.base_comment_opts[key] = \
+ '/' + posixpath.join(self.docroot, value)
+ if self.staticroot != 'static':
+ static_urls = [
+ ('commentImage', 'comment.png'),
+ ('closeCommentImage', 'comment-close.png'),
+ ('loadingImage', 'ajax-loader.gif'),
+ ('commentBrightImage', 'comment-bright.png'),
+ ('upArrow', 'up.png'),
+ ('upArrowPressed', 'up-pressed.png'),
+ ('downArrow', 'down.png'),
+ ('downArrowPressed', 'down-pressed.png')
+ ]
+ for key, value in static_urls:
+ self.base_comment_opts[key] = \
+ '/' + posixpath.join(self.staticroot, '_static', value)
+
+ def _make_comment_options(self, username, moderator):
+ """Helper method to create the parts of the COMMENT_OPTIONS
+ javascript that are unique to each request.
+
+ :param username: The username of the user making the request.
+ :param moderator: Whether the user making the request is a moderator.
+ """
+ rv = self.base_comment_opts.copy()
+ if username:
+ rv.update({
+ 'voting': True,
+ 'username': username,
+ 'moderator': moderator,
+ })
+ return '''\
+ <script type="text/javascript">
+ var COMMENT_OPTIONS = %s;
+ </script>
+ ''' % dump_json(rv)
+
+ def _make_metadata(self, data):
+ return '''\
+ <script type="text/javascript">
+ var COMMENT_METADATA = %s;
+ </script>
+ ''' % dump_json(data)
+
+ def _parse_comment_text(self, text):
+ settings = {'file_insertion_enabled': False,
+ 'raw_enabled': False,
+ 'output_encoding': 'unicode'}
+ try:
+ ret = publish_parts(text, writer_name='html',
+ settings_overrides=settings)['fragment']
+ except Exception:
+ ret = htmlescape(text)
+ return ret
diff --git a/sphinx/websupport/errors.py b/sphinx/websupport/errors.py
new file mode 100644
index 0000000..c401e8d
--- /dev/null
+++ b/sphinx/websupport/errors.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.errors
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Contains Error classes for the web support package.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+
+class DocumentNotFoundError(Exception):
+ pass
+
+
+class UserNotAuthorizedError(Exception):
+ pass
+
+
+class CommentNotAllowedError(Exception):
+ pass
+
+
+class NullSearchException(Exception):
+ pass
diff --git a/sphinx/websupport/search/__init__.py b/sphinx/websupport/search/__init__.py
new file mode 100644
index 0000000..45068d2
--- /dev/null
+++ b/sphinx/websupport/search/__init__.py
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.search
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Server side search support for the web support package.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+
+class BaseSearch(object):
+ def __init__(self, path):
+ pass
+
+ def init_indexing(self, changed=[]):
+ """Called by the builder to initialize the search indexer. `changed`
+ is a list of pagenames that will be reindexed. You may want to remove
+ these from the search index before indexing begins.
+
+ :param changed: a list of pagenames that will be re-indexed
+ """
+ pass
+
+ def finish_indexing(self):
+ """Called by the builder when writing has been completed. Use this
+ to perform any finalization or cleanup actions after indexing is
+ complete.
+ """
+ pass
+
+ def feed(self, pagename, title, doctree):
+ """Called by the builder to add a doctree to the index. Converts the
+ `doctree` to text and passes it to :meth:`add_document`. You probably
+ won't want to override this unless you need access to the `doctree`.
+ Override :meth:`add_document` instead.
+
+ :param pagename: the name of the page to be indexed
+ :param title: the title of the page to be indexed
+ :param doctree: is the docutils doctree representation of the page
+ """
+ self.add_document(pagename, title, doctree.astext())
+
+ def add_document(self, pagename, title, text):
+ """Called by :meth:`feed` to add a document to the search index.
+ This method should should do everything necessary to add a single
+ document to the search index.
+
+ `pagename` is name of the page being indexed. It is the combination
+ of the source files relative path and filename,
+ minus the extension. For example, if the source file is
+ "ext/builders.rst", the `pagename` would be "ext/builders". This
+ will need to be returned with search results when processing a
+ query.
+
+ :param pagename: the name of the page being indexed
+ :param title: the page's title
+ :param text: the full text of the page
+ """
+ raise NotImplementedError()
+
+ def query(self, q):
+ """Called by the web support api to get search results. This method
+ compiles the regular expression to be used when :meth:`extracting
+ context <extract_context>`, then calls :meth:`handle_query`. You
+ won't want to override this unless you don't want to use the included
+ :meth:`extract_context` method. Override :meth:`handle_query` instead.
+
+ :param q: the search query string.
+ """
+ self.context_re = re.compile('|'.join(q.split()), re.I)
+ return self.handle_query(q)
+
+ def handle_query(self, q):
+ """Called by :meth:`query` to retrieve search results for a search
+ query `q`. This should return an iterable containing tuples of the
+ following format::
+
+ (<path>, <title>, <context>)
+
+ `path` and `title` are the same values that were passed to
+ :meth:`add_document`, and `context` should be a short text snippet
+ of the text surrounding the search query in the document.
+
+ The :meth:`extract_context` method is provided as a simple way
+ to create the `context`.
+
+ :param q: the search query
+ """
+ raise NotImplementedError()
+
+ def extract_context(self, text, length=240):
+ """Extract the context for the search query from the document's
+ full `text`.
+
+ :param text: the full text of the document to create the context for
+ :param length: the length of the context snippet to return.
+ """
+ res = self.context_re.search(text)
+ if res is None:
+ return ''
+ context_start = max(res.start() - int(length/2), 0)
+ context_end = context_start + length
+ context = ''.join([context_start > 0 and '...' or '',
+ text[context_start:context_end],
+ context_end < len(text) and '...' or ''])
+
+ try:
+ return unicode(context, errors='ignore')
+ except TypeError:
+ return context
+
+ def context_for_searchtool(self):
+ """Required by the HTML builder."""
+ return {}
+
+
+# The built-in search adapters.
+SEARCH_ADAPTERS = {
+ 'xapian': ('xapiansearch', 'XapianSearch'),
+ 'whoosh': ('whooshsearch', 'WhooshSearch'),
+ 'null': ('nullsearch', 'NullSearch'),
+}
diff --git a/sphinx/websupport/search/nullsearch.py b/sphinx/websupport/search/nullsearch.py
new file mode 100644
index 0000000..e842356
--- /dev/null
+++ b/sphinx/websupport/search/nullsearch.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.search.nullsearch
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The default search adapter, does nothing.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.websupport.search import BaseSearch
+from sphinx.websupport.errors import NullSearchException
+
+
+class NullSearch(BaseSearch):
+ """A search adapter that does nothing. Used when no search adapter
+ is specified.
+ """
+ def feed(self, pagename, title, doctree):
+ pass
+
+ def query(self, q):
+ raise NullSearchException('No search adapter specified.')
diff --git a/sphinx/websupport/search/whooshsearch.py b/sphinx/websupport/search/whooshsearch.py
new file mode 100644
index 0000000..6d1f9de
--- /dev/null
+++ b/sphinx/websupport/search/whooshsearch.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.search.whooshsearch
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Whoosh search adapter.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from whoosh import index
+from whoosh.fields import Schema, ID, TEXT
+from whoosh.qparser import QueryParser
+from whoosh.analysis import StemmingAnalyzer
+
+from sphinx.util.osutil import ensuredir
+from sphinx.websupport.search import BaseSearch
+
+
+class WhooshSearch(BaseSearch):
+ """The whoosh search adapter for sphinx web support."""
+
+ # Define the Whoosh Schema for the search index.
+ schema = Schema(path=ID(stored=True, unique=True),
+ title=TEXT(field_boost=2.0, stored=True),
+ text=TEXT(analyzer=StemmingAnalyzer(), stored=True))
+
+ def __init__(self, db_path):
+ ensuredir(db_path)
+ if index.exists_in(db_path):
+ self.index = index.open_dir(db_path)
+ else:
+ self.index = index.create_in(db_path, schema=self.schema)
+ self.qparser = QueryParser('text', self.schema)
+
+ def init_indexing(self, changed=[]):
+ for changed_path in changed:
+ self.index.delete_by_term('path', changed_path)
+ self.index_writer = self.index.writer()
+
+ def finish_indexing(self):
+ self.index_writer.commit()
+
+ def add_document(self, pagename, title, text):
+ self.index_writer.add_document(path=unicode(pagename),
+ title=title,
+ text=text)
+
+ def handle_query(self, q):
+ searcher = self.index.searcher()
+ whoosh_results = searcher.search(self.qparser.parse(q))
+ results = []
+ for result in whoosh_results:
+ context = self.extract_context(result['text'])
+ results.append((result['path'],
+ result.get('title', ''),
+ context))
+ return results
diff --git a/sphinx/websupport/search/xapiansearch.py b/sphinx/websupport/search/xapiansearch.py
new file mode 100644
index 0000000..bd24879
--- /dev/null
+++ b/sphinx/websupport/search/xapiansearch.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.search.xapiansearch
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Xapian search adapter.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import xapian
+
+from sphinx.util.osutil import ensuredir
+from sphinx.websupport.search import BaseSearch
+
+
+class XapianSearch(BaseSearch):
+ # Adapted from the GSOC 2009 webapp project.
+
+ # Xapian metadata constants
+ DOC_PATH = 0
+ DOC_TITLE = 1
+
+ def __init__(self, db_path):
+ self.db_path = db_path
+
+ def init_indexing(self, changed=[]):
+ ensuredir(self.db_path)
+ self.database = xapian.WritableDatabase(self.db_path,
+ xapian.DB_CREATE_OR_OPEN)
+ self.indexer = xapian.TermGenerator()
+ stemmer = xapian.Stem("english")
+ self.indexer.set_stemmer(stemmer)
+
+ def finish_indexing(self):
+ # Ensure the db lock is removed.
+ del self.database
+
+ def add_document(self, path, title, text):
+ self.database.begin_transaction()
+ # sphinx_page_path is used to easily retrieve documents by path.
+ sphinx_page_path = '"sphinxpagepath%s"' % path.replace('/', '_')
+ # Delete the old document if it exists.
+ self.database.delete_document(sphinx_page_path)
+
+ doc = xapian.Document()
+ doc.set_data(text)
+ doc.add_value(self.DOC_PATH, path)
+ doc.add_value(self.DOC_TITLE, title)
+ self.indexer.set_document(doc)
+ self.indexer.index_text(text)
+ doc.add_term(sphinx_page_path)
+ for word in text.split():
+ doc.add_posting(word, 1)
+ self.database.add_document(doc)
+ self.database.commit_transaction()
+
+ def handle_query(self, q):
+ database = xapian.Database(self.db_path)
+ enquire = xapian.Enquire(database)
+ qp = xapian.QueryParser()
+ stemmer = xapian.Stem("english")
+ qp.set_stemmer(stemmer)
+ qp.set_database(database)
+ qp.set_stemming_strategy(xapian.QueryParser.STEM_SOME)
+ query = qp.parse_query(q)
+
+ # Find the top 100 results for the query.
+ enquire.set_query(query)
+ matches = enquire.get_mset(0, 100)
+
+ results = []
+
+ for m in matches:
+ context = self.extract_context(m.document.get_data())
+ results.append((m.document.get_value(self.DOC_PATH),
+ m.document.get_value(self.DOC_TITLE),
+ ''.join(context) ))
+
+ return results
diff --git a/sphinx/websupport/storage/__init__.py b/sphinx/websupport/storage/__init__.py
new file mode 100644
index 0000000..d9937d8
--- /dev/null
+++ b/sphinx/websupport/storage/__init__.py
@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.storage
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Storage for the websupport package.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+class StorageBackend(object):
+ def pre_build(self):
+ """Called immediately before the build process begins. Use this
+ to prepare the StorageBackend for the addition of nodes.
+ """
+ pass
+
+ def has_node(self, id):
+ """Check to see if a node exists.
+
+ :param id: the id to check for.
+ """
+ raise NotImplementedError()
+
+ def add_node(self, id, document, source):
+ """Add a node to the StorageBackend.
+
+ :param id: a unique id for the comment.
+ :param document: the name of the document the node belongs to.
+ :param source: the source files name.
+ """
+ raise NotImplementedError()
+
+ def post_build(self):
+ """Called after a build has completed. Use this to finalize the
+ addition of nodes if needed.
+ """
+ pass
+
+ def add_comment(self, text, displayed, username, time,
+ proposal, node_id, parent_id, moderator):
+ """Called when a comment is being added.
+
+ :param text: the text of the comment
+ :param displayed: whether the comment should be displayed
+ :param username: the name of the user adding the comment
+ :param time: a date object with the time the comment was added
+ :param proposal: the text of the proposal the user made
+ :param node_id: the id of the node that the comment is being added to
+ :param parent_id: the id of the comment's parent comment.
+ :param moderator: whether the user adding the comment is a moderator
+ """
+ raise NotImplementedError()
+
+ def delete_comment(self, comment_id, username, moderator):
+ """Delete a comment.
+
+ Raises :class:`~sphinx.websupport.errors.UserNotAuthorizedError`
+ if moderator is False and `username` doesn't match the username
+ on the comment.
+
+ :param comment_id: The id of the comment being deleted.
+ :param username: The username of the user requesting the deletion.
+ :param moderator: Whether the user is a moderator.
+ """
+ raise NotImplementedError()
+
+ def get_metadata(self, docname, moderator):
+ """Get metadata for a document. This is currently just a dict
+ of node_id's with associated comment counts.
+
+ :param docname: the name of the document to get metadata for.
+ :param moderator: whether the requester is a moderator.
+ """
+ raise NotImplementedError()
+
+ def get_data(self, node_id, username, moderator):
+ """Called to retrieve all data for a node. This should return a
+ dict with two keys, *source* and *comments* as described by
+ :class:`~sphinx.websupport.WebSupport`'s
+ :meth:`~sphinx.websupport.WebSupport.get_data` method.
+
+ :param node_id: The id of the node to get data for.
+ :param username: The name of the user requesting the data.
+ :param moderator: Whether the requestor is a moderator.
+ """
+ raise NotImplementedError()
+
+ def process_vote(self, comment_id, username, value):
+ """Process a vote that is being cast. `value` will be either -1, 0,
+ or 1.
+
+ :param comment_id: The id of the comment being voted on.
+ :param username: The username of the user casting the vote.
+ :param value: The value of the vote being cast.
+ """
+ raise NotImplementedError()
+
+ def update_username(self, old_username, new_username):
+ """If a user is allowed to change their username this method should
+ be called so that there is not stagnate data in the storage system.
+
+ :param old_username: The username being changed.
+ :param new_username: What the username is being changed to.
+ """
+ raise NotImplementedError()
+
+ def accept_comment(self, comment_id):
+ """Called when a moderator accepts a comment. After the method is
+ called the comment should be displayed to all users.
+
+ :param comment_id: The id of the comment being accepted.
+ """
+ raise NotImplementedError()
diff --git a/sphinx/websupport/storage/differ.py b/sphinx/websupport/storage/differ.py
new file mode 100644
index 0000000..c6966a7
--- /dev/null
+++ b/sphinx/websupport/storage/differ.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.storage.differ
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ A differ for creating an HTML representations of proposal diffs
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+from difflib import Differ
+
+from sphinx.util.pycompat import htmlescape
+
+
+class CombinedHtmlDiff(object):
+ """Create an HTML representation of the differences between two pieces
+ of text.
+ """
+ highlight_regex = re.compile(r'([\+\-\^]+)')
+
+ def __init__(self, source, proposal):
+ proposal = htmlescape(proposal)
+
+ differ = Differ()
+ self.diff = list(differ.compare(source.splitlines(1),
+ proposal.splitlines(1)))
+
+ def make_text(self):
+ return '\n'.join(self.diff)
+
+ def make_html(self):
+ """Return the HTML representation of the differences between
+ `source` and `proposal`.
+
+ :param source: the original text
+ :param proposal: the proposed text
+ """
+ html = []
+ diff = self.diff[:]
+ line = diff.pop(0)
+ next = diff.pop(0)
+ while True:
+ html.append(self._handle_line(line, next))
+ line = next
+ try:
+ next = diff.pop(0)
+ except IndexError:
+ html.append(self._handle_line(line))
+ break
+ return ''.join(html).rstrip()
+
+ def _handle_line(self, line, next=None):
+ """Handle an individual line in a diff."""
+ prefix = line[0]
+ text = line[2:]
+
+ if prefix == ' ':
+ return text
+ elif prefix == '?':
+ return ''
+
+ if next is not None and next[0] == '?':
+ tag = prefix == '+' and 'ins' or 'del'
+ text = self._highlight_text(text, next, tag)
+ css_class = prefix == '+' and 'prop-added' or 'prop-removed'
+
+ return '<span class="%s">%s</span>\n' % (css_class, text.rstrip())
+
+ def _highlight_text(self, text, next, tag):
+ """Highlight the specific changes made to a line by adding
+ <ins> and <del> tags.
+ """
+ next = next[2:]
+ new_text = []
+ start = 0
+ for match in self.highlight_regex.finditer(next):
+ new_text.append(text[start:match.start()])
+ new_text.append('<%s>' % tag)
+ new_text.append(text[match.start():match.end()])
+ new_text.append('</%s>' % tag)
+ start = match.end()
+ new_text.append(text[start:])
+ return ''.join(new_text)
diff --git a/sphinx/websupport/storage/sqlalchemy_db.py b/sphinx/websupport/storage/sqlalchemy_db.py
new file mode 100644
index 0000000..7baf883
--- /dev/null
+++ b/sphinx/websupport/storage/sqlalchemy_db.py
@@ -0,0 +1,222 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.storage.sqlalchemy_db
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ SQLAlchemy table and mapper definitions used by the
+ :class:`sphinx.websupport.storage.sqlalchemystorage.SQLAlchemyStorage`.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from datetime import datetime
+
+from sqlalchemy import Column, Integer, Text, String, Boolean, \
+ ForeignKey, DateTime
+from sqlalchemy.orm import relation, sessionmaker, aliased
+from sqlalchemy.ext.declarative import declarative_base
+
+Base = declarative_base()
+Session = sessionmaker()
+
+db_prefix = 'sphinx_'
+
+
+class Node(Base):
+ """Data about a Node in a doctree."""
+ __tablename__ = db_prefix + 'nodes'
+
+ id = Column(String(32), primary_key=True)
+ document = Column(String(256), nullable=False)
+ source = Column(Text, nullable=False)
+
+ def nested_comments(self, username, moderator):
+ """Create a tree of comments. First get all comments that are
+ descendants of this node, then convert them to a tree form.
+
+ :param username: the name of the user to get comments for.
+ :param moderator: whether the user is moderator.
+ """
+ session = Session()
+
+ if username:
+ # If a username is provided, create a subquery to retrieve all
+ # votes by this user. We will outerjoin with the comment query
+ # with this subquery so we have a user's voting information.
+ sq = session.query(CommentVote).\
+ filter(CommentVote.username == username).subquery()
+ cvalias = aliased(CommentVote, sq)
+ q = session.query(Comment, cvalias.value).outerjoin(cvalias)
+ else:
+ # If a username is not provided, we don't need to join with
+ # CommentVote.
+ q = session.query(Comment)
+
+ # Filter out all comments not descending from this node.
+ q = q.filter(Comment.path.like(str(self.id) + '.%'))
+
+ # Filter out all comments that are not moderated yet.
+ if not moderator:
+ q = q.filter(Comment.displayed == True)
+
+ # Retrieve all results. Results must be ordered by Comment.path
+ # so that we can easily transform them from a flat list to a tree.
+ results = q.order_by(Comment.path).all()
+ session.close()
+
+ return self._nest_comments(results, username)
+
+ def _nest_comments(self, results, username):
+ """Given the flat list of results, convert the list into a
+ tree.
+
+ :param results: the flat list of comments
+ :param username: the name of the user requesting the comments.
+ """
+ comments = []
+ list_stack = [comments]
+ for r in results:
+ if username:
+ comment, vote = r
+ else:
+ comment, vote = (r, 0)
+
+ inheritance_chain = comment.path.split('.')[1:]
+
+ if len(inheritance_chain) == len(list_stack) + 1:
+ parent = list_stack[-1][-1]
+ list_stack.append(parent['children'])
+ elif len(inheritance_chain) < len(list_stack):
+ while len(inheritance_chain) < len(list_stack):
+ list_stack.pop()
+
+ list_stack[-1].append(comment.serializable(vote=vote))
+
+ return comments
+
+ def __init__(self, id, document, source):
+ self.id = id
+ self.document = document
+ self.source = source
+
+
+class CommentVote(Base):
+ """A vote a user has made on a Comment."""
+ __tablename__ = db_prefix + 'commentvote'
+
+ username = Column(String(64), primary_key=True)
+ comment_id = Column(Integer, ForeignKey(db_prefix + 'comments.id'),
+ primary_key=True)
+ # -1 if downvoted, +1 if upvoted, 0 if voted then unvoted.
+ value = Column(Integer, nullable=False)
+
+ def __init__(self, comment_id, username, value):
+ self.comment_id = comment_id
+ self.username = username
+ self.value = value
+
+
+class Comment(Base):
+ """An individual Comment being stored."""
+ __tablename__ = db_prefix + 'comments'
+
+ id = Column(Integer, primary_key=True)
+ rating = Column(Integer, nullable=False)
+ time = Column(DateTime, nullable=False)
+ text = Column(Text, nullable=False)
+ displayed = Column(Boolean, index=True, default=False)
+ username = Column(String(64))
+ proposal = Column(Text)
+ proposal_diff = Column(Text)
+ path = Column(String(256), index=True)
+
+ node_id = Column(String, ForeignKey(db_prefix + 'nodes.id'))
+ node = relation(Node, backref="comments")
+
+ votes = relation(CommentVote, backref="comment",
+ cascade="all")
+
+ def __init__(self, text, displayed, username, rating, time,
+ proposal, proposal_diff):
+ self.text = text
+ self.displayed = displayed
+ self.username = username
+ self.rating = rating
+ self.time = time
+ self.proposal = proposal
+ self.proposal_diff = proposal_diff
+
+ def set_path(self, node_id, parent_id):
+ """Set the materialized path for this comment."""
+ # This exists because the path can't be set until the session has
+ # been flushed and this Comment has an id.
+ if node_id:
+ self.node_id = node_id
+ self.path = '%s.%s' % (node_id, self.id)
+ else:
+ session = Session()
+ parent_path = session.query(Comment.path).\
+ filter(Comment.id == parent_id).one().path
+ session.close()
+ self.node_id = parent_path.split('.')[0]
+ self.path = '%s.%s' % (parent_path, self.id)
+
+ def serializable(self, vote=0):
+ """Creates a serializable representation of the comment. This is
+ converted to JSON, and used on the client side.
+ """
+ delta = datetime.now() - self.time
+
+ time = {'year': self.time.year,
+ 'month': self.time.month,
+ 'day': self.time.day,
+ 'hour': self.time.hour,
+ 'minute': self.time.minute,
+ 'second': self.time.second,
+ 'iso': self.time.isoformat(),
+ 'delta': self.pretty_delta(delta)}
+
+ path = self.path.split('.')
+ node = path[0]
+ if len(path) > 2:
+ parent = path[-2]
+ else:
+ parent = None
+
+ return {'text': self.text,
+ 'username': self.username or 'Anonymous',
+ 'id': self.id,
+ 'node': node,
+ 'parent': parent,
+ 'rating': self.rating,
+ 'displayed': self.displayed,
+ 'age': delta.seconds,
+ 'time': time,
+ 'vote': vote or 0,
+ 'proposal_diff': self.proposal_diff,
+ 'children': []}
+
+ def pretty_delta(self, delta):
+ """Create a pretty representation of the Comment's age.
+ (e.g. 2 minutes).
+ """
+ days = delta.days
+ seconds = delta.seconds
+ hours = seconds / 3600
+ minutes = seconds / 60
+
+ if days == 0:
+ if hours == 0:
+ dt = (minutes, 'minute')
+ else:
+ dt = (hours, 'hour')
+ else:
+ dt = (days, 'day')
+
+ if dt[0] == 1:
+ ret = '%s %s ago' % dt
+ else:
+ ret = '%s %ss ago' % dt
+
+ return ret
diff --git a/sphinx/websupport/storage/sqlalchemystorage.py b/sphinx/websupport/storage/sqlalchemystorage.py
new file mode 100644
index 0000000..354c710
--- /dev/null
+++ b/sphinx/websupport/storage/sqlalchemystorage.py
@@ -0,0 +1,177 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.storage.sqlalchemystorage
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ An SQLAlchemy storage backend.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from datetime import datetime
+
+import sqlalchemy
+from sqlalchemy.orm import aliased
+from sqlalchemy.sql import func
+
+if sqlalchemy.__version__[:3] < '0.5':
+ raise ImportError('SQLAlchemy version 0.5 or greater is required for this '
+ 'storage backend; you have version %s' % sqlalchemy.__version__)
+
+from sphinx.websupport.errors import CommentNotAllowedError, \
+ UserNotAuthorizedError
+from sphinx.websupport.storage import StorageBackend
+from sphinx.websupport.storage.sqlalchemy_db import Base, Node, \
+ Comment, CommentVote, Session
+from sphinx.websupport.storage.differ import CombinedHtmlDiff
+
+
+class SQLAlchemyStorage(StorageBackend):
+ """
+ A :class:`.StorageBackend` using SQLAlchemy.
+ """
+
+ def __init__(self, uri):
+ self.engine = sqlalchemy.create_engine(uri)
+ Base.metadata.bind = self.engine
+ Base.metadata.create_all()
+ Session.configure(bind=self.engine)
+
+ def pre_build(self):
+ self.build_session = Session()
+
+ def has_node(self, id):
+ session = Session()
+ node = session.query(Node).filter(Node.id == id).first()
+ session.close()
+ return bool(node)
+
+ def add_node(self, id, document, source):
+ node = Node(id, document, source)
+ self.build_session.add(node)
+ self.build_session.flush()
+
+ def post_build(self):
+ self.build_session.commit()
+ self.build_session.close()
+
+ def add_comment(self, text, displayed, username, time,
+ proposal, node_id, parent_id, moderator):
+ session = Session()
+ proposal_diff = None
+ proposal_diff_text = None
+
+ if node_id and proposal:
+ node = session.query(Node).filter(Node.id == node_id).one()
+ differ = CombinedHtmlDiff(node.source, proposal)
+ proposal_diff = differ.make_html()
+ proposal_diff_text = differ.make_text()
+ elif parent_id:
+ parent = session.query(Comment.displayed).\
+ filter(Comment.id == parent_id).one()
+ if not parent.displayed:
+ raise CommentNotAllowedError(
+ "Can't add child to a parent that is not displayed")
+
+ comment = Comment(text, displayed, username, 0,
+ time or datetime.now(), proposal, proposal_diff)
+ session.add(comment)
+ session.flush()
+ # We have to flush the session before setting the path so the
+ # Comment has an id.
+ comment.set_path(node_id, parent_id)
+ session.commit()
+ d = comment.serializable()
+ d['document'] = comment.node.document
+ d['proposal_diff_text'] = proposal_diff_text
+ session.close()
+ return d
+
+ def delete_comment(self, comment_id, username, moderator):
+ session = Session()
+ comment = session.query(Comment).\
+ filter(Comment.id == comment_id).one()
+ if moderator:
+ # moderator mode: delete the comment and all descendants
+ # find descendants via path
+ session.query(Comment).filter(
+ Comment.path.like(comment.path + '.%')).delete(False)
+ session.delete(comment)
+ session.commit()
+ session.close()
+ return True
+ elif comment.username == username:
+ # user mode: do not really delete, but remove text and proposal
+ comment.username = '[deleted]'
+ comment.text = '[deleted]'
+ comment.proposal = ''
+ session.commit()
+ session.close()
+ return False
+ else:
+ session.close()
+ raise UserNotAuthorizedError()
+
+ def get_metadata(self, docname, moderator):
+ session = Session()
+ subquery = session.query(
+ Comment.node_id,
+ func.count('*').label('comment_count')).group_by(
+ Comment.node_id).subquery()
+ nodes = session.query(Node.id, subquery.c.comment_count).outerjoin(
+ (subquery, Node.id==subquery.c.node_id)).filter(
+ Node.document==docname)
+ session.close()
+ session.commit()
+ return dict([(k, v or 0) for k, v in nodes])
+
+ def get_data(self, node_id, username, moderator):
+ session = Session()
+ node = session.query(Node).filter(Node.id == node_id).one()
+ session.close()
+ comments = node.nested_comments(username, moderator)
+ return {'source': node.source,
+ 'comments': comments}
+
+ def process_vote(self, comment_id, username, value):
+ session = Session()
+
+ subquery = session.query(CommentVote).filter(
+ CommentVote.username == username).subquery()
+ vote_alias = aliased(CommentVote, subquery)
+ q = session.query(Comment, vote_alias).outerjoin(vote_alias).filter(
+ Comment.id == comment_id)
+ comment, vote = q.one()
+
+ if vote is None:
+ vote = CommentVote(comment_id, username, value)
+ comment.rating += value
+ else:
+ comment.rating += value - vote.value
+ vote.value = value
+
+ session.add(vote)
+ session.commit()
+ session.close()
+
+ def update_username(self, old_username, new_username):
+ session = Session()
+
+ session.query(Comment).filter(Comment.username == old_username).\
+ update({Comment.username: new_username})
+ session.query(CommentVote).\
+ filter(CommentVote.username == old_username).\
+ update({CommentVote.username: new_username})
+
+ session.commit()
+ session.close()
+
+ def accept_comment(self, comment_id):
+ session = Session()
+ session.query(Comment).filter(Comment.id == comment_id).update(
+ {Comment.displayed: True}
+ )
+
+ session.commit()
+ session.close()
diff --git a/sphinx/writers/__init__.py b/sphinx/writers/__init__.py
new file mode 100644
index 0000000..a7541b2
--- /dev/null
+++ b/sphinx/writers/__init__.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.writers
+ ~~~~~~~~~~~~~~
+
+ Custom docutils writers.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py
new file mode 100644
index 0000000..c69c2e0
--- /dev/null
+++ b/sphinx/writers/html.py
@@ -0,0 +1,656 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.writers.html
+ ~~~~~~~~~~~~~~~~~~~
+
+ docutils writers handling Sphinx' custom nodes.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import posixpath
+import os
+import copy
+
+from docutils import nodes
+from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator
+
+from sphinx import addnodes
+from sphinx.locale import admonitionlabels, _
+from sphinx.util.smartypants import sphinx_smarty_pants
+
+try:
+ from PIL import Image # check for the Python Imaging Library
+except ImportError:
+ try:
+ import Image
+ except ImportError:
+ Image = None
+
+# A good overview of the purpose behind these classes can be found here:
+# http://www.arnebrodowski.de/blog/write-your-own-restructuredtext-writer.html
+
+class HTMLWriter(Writer):
+
+ # override embed-stylesheet default value to 0.
+ settings_spec = copy.deepcopy(Writer.settings_spec)
+ for _setting in settings_spec[2]:
+ if '--embed-stylesheet' in _setting[1]:
+ _setting[2]['default'] = 0
+
+ def __init__(self, builder):
+ Writer.__init__(self)
+ self.builder = builder
+
+ def translate(self):
+ # sadly, this is mostly copied from parent class
+ self.visitor = visitor = self.builder.translator_class(self.builder,
+ self.document)
+ self.document.walkabout(visitor)
+ self.output = visitor.astext()
+ for attr in ('head_prefix', 'stylesheet', 'head', 'body_prefix',
+ 'body_pre_docinfo', 'docinfo', 'body', 'fragment',
+ 'body_suffix', 'meta', 'title', 'subtitle', 'header',
+ 'footer', 'html_prolog', 'html_head', 'html_title',
+ 'html_subtitle', 'html_body', ):
+ setattr(self, attr, getattr(visitor, attr, None))
+ self.clean_meta = ''.join(visitor.meta[2:])
+
+
+class HTMLTranslator(BaseTranslator):
+ """
+ Our custom HTML translator.
+ """
+
+ def __init__(self, builder, *args, **kwds):
+ BaseTranslator.__init__(self, *args, **kwds)
+ self.highlighter = builder.highlighter
+ self.no_smarty = 0
+ self.builder = builder
+ self.highlightlang = builder.config.highlight_language
+ self.highlightlinenothreshold = sys.maxint
+ self.protect_literal_text = 0
+ self.permalink_text = builder.config.html_add_permalinks
+ # support backwards-compatible setting to a bool
+ if not isinstance(self.permalink_text, basestring):
+ self.permalink_text = self.permalink_text and u'\u00B6' or ''
+ self.permalink_text = self.encode(self.permalink_text)
+ self.secnumber_suffix = builder.config.html_secnumber_suffix
+ self.param_separator = ''
+ self.optional_param_level = 0
+ self._table_row_index = 0
+
+ def visit_start_of_file(self, node):
+ # only occurs in the single-file builder
+ self.body.append('<span id="document-%s"></span>' % node['docname'])
+ def depart_start_of_file(self, node):
+ pass
+
+ def visit_desc(self, node):
+ self.body.append(self.starttag(node, 'dl', CLASS=node['objtype']))
+ def depart_desc(self, node):
+ self.body.append('</dl>\n\n')
+
+ def visit_desc_signature(self, node):
+ # the id is set automatically
+ self.body.append(self.starttag(node, 'dt'))
+ # anchor for per-desc interactive data
+ if node.parent['objtype'] != 'describe' \
+ and node['ids'] and node['first']:
+ self.body.append('<!--[%s]-->' % node['ids'][0])
+ def depart_desc_signature(self, node):
+ if node['ids'] and self.permalink_text and self.builder.add_permalinks:
+ self.body.append(u'<a class="headerlink" href="#%s" '
+ % node['ids'][0] +
+ u'title="%s">%s</a>' % (
+ _('Permalink to this definition'),
+ self.permalink_text))
+ self.body.append('</dt>\n')
+
+ def visit_desc_addname(self, node):
+ self.body.append(self.starttag(node, 'tt', '', CLASS='descclassname'))
+ def depart_desc_addname(self, node):
+ self.body.append('</tt>')
+
+ def visit_desc_type(self, node):
+ pass
+ def depart_desc_type(self, node):
+ pass
+
+ def visit_desc_returns(self, node):
+ self.body.append(' → ')
+ def depart_desc_returns(self, node):
+ pass
+
+ def visit_desc_name(self, node):
+ self.body.append(self.starttag(node, 'tt', '', CLASS='descname'))
+ def depart_desc_name(self, node):
+ self.body.append('</tt>')
+
+ def visit_desc_parameterlist(self, node):
+ self.body.append('<big>(</big>')
+ self.first_param = 1
+ self.optional_param_level = 0
+ # How many required parameters are left.
+ self.required_params_left = sum([isinstance(c, addnodes.desc_parameter)
+ for c in node.children])
+ self.param_separator = node.child_text_separator
+ def depart_desc_parameterlist(self, node):
+ self.body.append('<big>)</big>')
+
+ # If required parameters are still to come, then put the comma after
+ # the parameter. Otherwise, put the comma before. This ensures that
+ # signatures like the following render correctly (see issue #1001):
+ #
+ # foo([a, ]b, c[, d])
+ #
+ def visit_desc_parameter(self, node):
+ if self.first_param:
+ self.first_param = 0
+ elif not self.required_params_left:
+ self.body.append(self.param_separator)
+ if self.optional_param_level == 0:
+ self.required_params_left -= 1
+ if not node.hasattr('noemph'):
+ self.body.append('<em>')
+ def depart_desc_parameter(self, node):
+ if not node.hasattr('noemph'):
+ self.body.append('</em>')
+ if self.required_params_left:
+ self.body.append(self.param_separator)
+
+ def visit_desc_optional(self, node):
+ self.optional_param_level += 1
+ self.body.append('<span class="optional">[</span>')
+ def depart_desc_optional(self, node):
+ self.optional_param_level -= 1
+ self.body.append('<span class="optional">]</span>')
+
+ def visit_desc_annotation(self, node):
+ self.body.append(self.starttag(node, 'em', '', CLASS='property'))
+ def depart_desc_annotation(self, node):
+ self.body.append('</em>')
+
+ def visit_desc_content(self, node):
+ self.body.append(self.starttag(node, 'dd', ''))
+ def depart_desc_content(self, node):
+ self.body.append('</dd>')
+
+ def visit_versionmodified(self, node):
+ self.body.append(self.starttag(node, 'div', CLASS=node['type']))
+ def depart_versionmodified(self, node):
+ self.body.append('</div>\n')
+
+ # overwritten
+ def visit_reference(self, node):
+ atts = {'class': 'reference'}
+ if node.get('internal') or 'refuri' not in node:
+ atts['class'] += ' internal'
+ else:
+ atts['class'] += ' external'
+ if 'refuri' in node:
+ atts['href'] = node['refuri']
+ if self.settings.cloak_email_addresses and \
+ atts['href'].startswith('mailto:'):
+ atts['href'] = self.cloak_mailto(atts['href'])
+ self.in_mailto = 1
+ else:
+ assert 'refid' in node, \
+ 'References must have "refuri" or "refid" attribute.'
+ atts['href'] = '#' + node['refid']
+ if not isinstance(node.parent, nodes.TextElement):
+ assert len(node) == 1 and isinstance(node[0], nodes.image)
+ atts['class'] += ' image-reference'
+ if 'reftitle' in node:
+ atts['title'] = node['reftitle']
+ self.body.append(self.starttag(node, 'a', '', **atts))
+
+ if node.get('secnumber'):
+ self.body.append(('%s' + self.secnumber_suffix) %
+ '.'.join(map(str, node['secnumber'])))
+
+ # overwritten -- we don't want source comments to show up in the HTML
+ def visit_comment(self, node):
+ raise nodes.SkipNode
+
+ # overwritten
+ def visit_admonition(self, node, name=''):
+ self.body.append(self.starttag(
+ node, 'div', CLASS=('admonition ' + name)))
+ if name:
+ node.insert(0, nodes.title(name, admonitionlabels[name]))
+ self.set_first_last(node)
+
+ def visit_seealso(self, node):
+ self.visit_admonition(node, 'seealso')
+ def depart_seealso(self, node):
+ self.depart_admonition(node)
+
+ def add_secnumber(self, node):
+ if node.get('secnumber'):
+ self.body.append('.'.join(map(str, node['secnumber'])) +
+ self.secnumber_suffix)
+ elif isinstance(node.parent, nodes.section):
+ anchorname = '#' + node.parent['ids'][0]
+ if anchorname not in self.builder.secnumbers:
+ anchorname = '' # try first heading which has no anchor
+ if self.builder.secnumbers.get(anchorname):
+ numbers = self.builder.secnumbers[anchorname]
+ self.body.append('.'.join(map(str, numbers)) +
+ self.secnumber_suffix)
+
+ # overwritten to avoid emitting empty <ul></ul>
+ def visit_bullet_list(self, node):
+ if len(node) == 1 and node[0].tagname == 'toctree':
+ raise nodes.SkipNode
+ BaseTranslator.visit_bullet_list(self, node)
+
+ # overwritten
+ def visit_title(self, node):
+ BaseTranslator.visit_title(self, node)
+ self.add_secnumber(node)
+
+ # overwritten
+ def visit_literal_block(self, node):
+ if node.rawsource != node.astext():
+ # most probably a parsed-literal block -- don't highlight
+ return BaseTranslator.visit_literal_block(self, node)
+ lang = self.highlightlang
+ linenos = node.rawsource.count('\n') >= \
+ self.highlightlinenothreshold - 1
+ highlight_args = node.get('highlight_args', {})
+ if node.has_key('language'):
+ # code-block directives
+ lang = node['language']
+ highlight_args['force'] = True
+ if node.has_key('linenos'):
+ linenos = node['linenos']
+ def warner(msg):
+ self.builder.warn(msg, (self.builder.current_docname, node.line))
+ highlighted = self.highlighter.highlight_block(
+ node.rawsource, lang, warn=warner, linenos=linenos,
+ **highlight_args)
+ starttag = self.starttag(node, 'div', suffix='',
+ CLASS='highlight-%s' % lang)
+ self.body.append(starttag + highlighted + '</div>\n')
+ raise nodes.SkipNode
+
+ def visit_doctest_block(self, node):
+ self.visit_literal_block(node)
+
+ # overwritten to add the <div> (for XHTML compliance)
+ def visit_block_quote(self, node):
+ self.body.append(self.starttag(node, 'blockquote') + '<div>')
+ def depart_block_quote(self, node):
+ self.body.append('</div></blockquote>\n')
+
+ # overwritten
+ def visit_literal(self, node):
+ self.body.append(self.starttag(node, 'tt', '',
+ CLASS='docutils literal'))
+ self.protect_literal_text += 1
+ def depart_literal(self, node):
+ self.protect_literal_text -= 1
+ self.body.append('</tt>')
+
+ def visit_productionlist(self, node):
+ self.body.append(self.starttag(node, 'pre'))
+ names = []
+ for production in node:
+ names.append(production['tokenname'])
+ maxlen = max(len(name) for name in names)
+ lastname = None
+ for production in node:
+ if production['tokenname']:
+ lastname = production['tokenname'].ljust(maxlen)
+ self.body.append(self.starttag(production, 'strong', ''))
+ self.body.append(lastname + '</strong> ::= ')
+ elif lastname is not None:
+ self.body.append('%s ' % (' '*len(lastname)))
+ production.walkabout(self)
+ self.body.append('\n')
+ self.body.append('</pre>\n')
+ raise nodes.SkipNode
+ def depart_productionlist(self, node):
+ pass
+
+ def visit_production(self, node):
+ pass
+ def depart_production(self, node):
+ pass
+
+ def visit_centered(self, node):
+ self.body.append(self.starttag(node, 'p', CLASS="centered")
+ + '<strong>')
+ def depart_centered(self, node):
+ self.body.append('</strong></p>')
+
+ # overwritten
+ def should_be_compact_paragraph(self, node):
+ """Determine if the <p> tags around paragraph can be omitted."""
+ if isinstance(node.parent, addnodes.desc_content):
+ # Never compact desc_content items.
+ return False
+ if isinstance(node.parent, addnodes.versionmodified):
+ # Never compact versionmodified nodes.
+ return False
+ return BaseTranslator.should_be_compact_paragraph(self, node)
+
+ def visit_compact_paragraph(self, node):
+ pass
+ def depart_compact_paragraph(self, node):
+ pass
+
+ def visit_highlightlang(self, node):
+ self.highlightlang = node['lang']
+ self.highlightlinenothreshold = node['linenothreshold']
+ def depart_highlightlang(self, node):
+ pass
+
+ def visit_download_reference(self, node):
+ if node.hasattr('filename'):
+ self.body.append(
+ '<a class="reference download internal" href="%s">' %
+ posixpath.join(self.builder.dlpath, node['filename']))
+ self.context.append('</a>')
+ else:
+ self.context.append('')
+ def depart_download_reference(self, node):
+ self.body.append(self.context.pop())
+
+ # overwritten
+ def visit_image(self, node):
+ olduri = node['uri']
+ # rewrite the URI if the environment knows about it
+ if olduri in self.builder.images:
+ node['uri'] = posixpath.join(self.builder.imgpath,
+ self.builder.images[olduri])
+
+ if node['uri'].lower().endswith('svg') or \
+ node['uri'].lower().endswith('svgz'):
+ atts = {'src': node['uri']}
+ if node.has_key('width'):
+ atts['width'] = node['width']
+ if node.has_key('height'):
+ atts['height'] = node['height']
+ if node.has_key('alt'):
+ atts['alt'] = node['alt']
+ if node.has_key('align'):
+ self.body.append('<div align="%s" class="align-%s">' %
+ (node['align'], node['align']))
+ self.context.append('</div>\n')
+ else:
+ self.context.append('')
+ self.body.append(self.emptytag(node, 'img', '', **atts))
+ return
+
+ if node.has_key('scale'):
+ # Try to figure out image height and width. Docutils does that too,
+ # but it tries the final file name, which does not necessarily exist
+ # yet at the time the HTML file is written.
+ if Image and not (node.has_key('width')
+ and node.has_key('height')):
+ try:
+ im = Image.open(os.path.join(self.builder.srcdir, olduri))
+ except (IOError, # Source image can't be found or opened
+ UnicodeError): # PIL doesn't like Unicode paths.
+ pass
+ else:
+ if not node.has_key('width'):
+ node['width'] = str(im.size[0])
+ if not node.has_key('height'):
+ node['height'] = str(im.size[1])
+ try:
+ im.fp.close()
+ except Exception:
+ pass
+ BaseTranslator.visit_image(self, node)
+
+ def visit_toctree(self, node):
+ # this only happens when formatting a toc from env.tocs -- in this
+ # case we don't want to include the subtree
+ raise nodes.SkipNode
+
+ def visit_index(self, node):
+ raise nodes.SkipNode
+
+ def visit_tabular_col_spec(self, node):
+ raise nodes.SkipNode
+
+ def visit_glossary(self, node):
+ pass
+ def depart_glossary(self, node):
+ pass
+
+ def visit_acks(self, node):
+ pass
+ def depart_acks(self, node):
+ pass
+
+ def visit_hlist(self, node):
+ self.body.append('<table class="hlist"><tr>')
+ def depart_hlist(self, node):
+ self.body.append('</tr></table>\n')
+
+ def visit_hlistcol(self, node):
+ self.body.append('<td>')
+ def depart_hlistcol(self, node):
+ self.body.append('</td>')
+
+ def bulk_text_processor(self, text):
+ return text
+
+ # overwritten
+ def visit_Text(self, node):
+ text = node.astext()
+ encoded = self.encode(text)
+ if self.protect_literal_text:
+ # moved here from base class's visit_literal to support
+ # more formatting in literal nodes
+ for token in self.words_and_spaces.findall(encoded):
+ if token.strip():
+ # protect literal text from line wrapping
+ self.body.append('<span class="pre">%s</span>' % token)
+ elif token in ' \n':
+ # allow breaks at whitespace
+ self.body.append(token)
+ else:
+ # protect runs of multiple spaces; the last one can wrap
+ self.body.append(' ' * (len(token)-1) + ' ')
+ else:
+ if self.in_mailto and self.settings.cloak_email_addresses:
+ encoded = self.cloak_email(encoded)
+ else:
+ encoded = self.bulk_text_processor(encoded)
+ self.body.append(encoded)
+
+ def visit_note(self, node):
+ self.visit_admonition(node, 'note')
+ def depart_note(self, node):
+ self.depart_admonition(node)
+
+ def visit_warning(self, node):
+ self.visit_admonition(node, 'warning')
+ def depart_warning(self, node):
+ self.depart_admonition(node)
+
+ def visit_attention(self, node):
+ self.visit_admonition(node, 'attention')
+
+ def depart_attention(self, node):
+ self.depart_admonition()
+
+ def visit_caution(self, node):
+ self.visit_admonition(node, 'caution')
+ def depart_caution(self, node):
+ self.depart_admonition()
+
+ def visit_danger(self, node):
+ self.visit_admonition(node, 'danger')
+ def depart_danger(self, node):
+ self.depart_admonition()
+
+ def visit_error(self, node):
+ self.visit_admonition(node, 'error')
+ def depart_error(self, node):
+ self.depart_admonition()
+
+ def visit_hint(self, node):
+ self.visit_admonition(node, 'hint')
+ def depart_hint(self, node):
+ self.depart_admonition()
+
+ def visit_important(self, node):
+ self.visit_admonition(node, 'important')
+ def depart_important(self, node):
+ self.depart_admonition()
+
+ def visit_tip(self, node):
+ self.visit_admonition(node, 'tip')
+ def depart_tip(self, node):
+ self.depart_admonition()
+
+ # these are only handled specially in the SmartyPantsHTMLTranslator
+ def visit_literal_emphasis(self, node):
+ return self.visit_emphasis(node)
+ def depart_literal_emphasis(self, node):
+ return self.depart_emphasis(node)
+
+ def visit_abbreviation(self, node):
+ attrs = {}
+ if node.hasattr('explanation'):
+ attrs['title'] = node['explanation']
+ self.body.append(self.starttag(node, 'abbr', '', **attrs))
+ def depart_abbreviation(self, node):
+ self.body.append('</abbr>')
+
+ def visit_termsep(self, node):
+ self.body.append('<br />')
+ raise nodes.SkipNode
+
+ def depart_title(self, node):
+ close_tag = self.context[-1]
+ if (self.permalink_text and self.builder.add_permalinks and
+ node.parent.hasattr('ids') and node.parent['ids']):
+ aname = node.parent['ids'][0]
+ # add permalink anchor
+ if close_tag.startswith('</h'):
+ self.body.append(u'<a class="headerlink" href="#%s" ' % aname +
+ u'title="%s">%s</a>' % (
+ _('Permalink to this headline'),
+ self.permalink_text))
+ elif close_tag.startswith('</a></h'):
+ self.body.append(u'</a><a class="headerlink" href="#%s" ' %
+ aname +
+ u'title="%s">%s' % (
+ _('Permalink to this headline'),
+ self.permalink_text))
+
+ BaseTranslator.depart_title(self, node)
+
+ # overwritten to add even/odd classes
+
+ def visit_table(self, node):
+ self._table_row_index = 0
+ return BaseTranslator.visit_table(self, node)
+
+ def visit_row(self, node):
+ self._table_row_index += 1
+ if self._table_row_index % 2 == 0:
+ node['classes'].append('row-even')
+ else:
+ node['classes'].append('row-odd')
+ self.body.append(self.starttag(node, 'tr', ''))
+ node.column = 0
+
+ def visit_field_list(self, node):
+ self._fieldlist_row_index = 0
+ return BaseTranslator.visit_field_list(self, node)
+
+ def visit_field(self, node):
+ self._fieldlist_row_index += 1
+ if self._fieldlist_row_index % 2 == 0:
+ node['classes'].append('field-even')
+ else:
+ node['classes'].append('field-odd')
+ self.body.append(self.starttag(node, 'tr', '', CLASS='field'))
+
+ def visit_math(self, node, math_env=''):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html',
+ (self.builder.current_docname, node.line))
+ raise nodes.SkipNode
+
+ def unknown_visit(self, node):
+ raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
+
+
+class SmartyPantsHTMLTranslator(HTMLTranslator):
+ """
+ Handle ordinary text via smartypants, converting quotes and dashes
+ to the correct entities.
+ """
+
+ def __init__(self, *args, **kwds):
+ self.no_smarty = 0
+ HTMLTranslator.__init__(self, *args, **kwds)
+
+ def visit_literal(self, node):
+ self.no_smarty += 1
+ try:
+ # this raises SkipNode
+ HTMLTranslator.visit_literal(self, node)
+ finally:
+ self.no_smarty -= 1
+
+ def visit_literal_block(self, node):
+ self.no_smarty += 1
+ try:
+ HTMLTranslator.visit_literal_block(self, node)
+ except nodes.SkipNode:
+ # HTMLTranslator raises SkipNode for simple literal blocks,
+ # but not for parsed literal blocks
+ self.no_smarty -= 1
+ raise
+
+ def depart_literal_block(self, node):
+ HTMLTranslator.depart_literal_block(self, node)
+ self.no_smarty -= 1
+
+ def visit_literal_emphasis(self, node):
+ self.no_smarty += 1
+ self.visit_emphasis(node)
+
+ def depart_literal_emphasis(self, node):
+ self.depart_emphasis(node)
+ self.no_smarty -= 1
+
+ def visit_desc_signature(self, node):
+ self.no_smarty += 1
+ HTMLTranslator.visit_desc_signature(self, node)
+
+ def depart_desc_signature(self, node):
+ self.no_smarty -= 1
+ HTMLTranslator.depart_desc_signature(self, node)
+
+ def visit_productionlist(self, node):
+ self.no_smarty += 1
+ try:
+ HTMLTranslator.visit_productionlist(self, node)
+ finally:
+ self.no_smarty -= 1
+
+ def visit_option(self, node):
+ self.no_smarty += 1
+ HTMLTranslator.visit_option(self, node)
+ def depart_option(self, node):
+ self.no_smarty -= 1
+ HTMLTranslator.depart_option(self, node)
+
+ def bulk_text_processor(self, text):
+ if self.no_smarty <= 0:
+ return sphinx_smarty_pants(text)
+ return text
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
new file mode 100644
index 0000000..8c9b1f5
--- /dev/null
+++ b/sphinx/writers/latex.py
@@ -0,0 +1,1545 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.writers.latex
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Custom docutils writer for LaTeX.
+
+ Much of this code is adapted from Dave Kuhlman's "docpy" writer from his
+ docutils sandbox.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import sys
+from os import path
+
+from docutils import nodes, writers
+from docutils.writers.latex2e import Babel
+
+from sphinx import addnodes
+from sphinx import highlighting
+from sphinx.errors import SphinxError
+from sphinx.locale import admonitionlabels, _
+from sphinx.util import split_into
+from sphinx.util.osutil import ustrftime
+from sphinx.util.pycompat import any
+from sphinx.util.texescape import tex_escape_map, tex_replace_map
+from sphinx.util.smartypants import educate_quotes_latex
+
+HEADER = r'''%% Generated by Sphinx.
+\def\sphinxdocclass{%(docclass)s}
+\documentclass[%(papersize)s,%(pointsize)s%(classoptions)s]{%(wrapperclass)s}
+%(inputenc)s
+%(utf8extra)s
+%(cmappkg)s
+%(fontenc)s
+%(babel)s
+%(fontpkg)s
+%(fncychap)s
+%(longtable)s
+\usepackage{sphinx}
+\usepackage{multirow}
+%(preamble)s
+
+\title{%(title)s}
+\date{%(date)s}
+\release{%(release)s}
+\author{%(author)s}
+\newcommand{\sphinxlogo}{%(logo)s}
+\renewcommand{\releasename}{%(releasename)s}
+%(makeindex)s
+'''
+
+BEGIN_DOC = r'''
+\begin{document}
+%(shorthandoff)s
+%(maketitle)s
+%(tableofcontents)s
+'''
+
+FOOTER = r'''
+\renewcommand{\indexname}{%(indexname)s}
+%(printindex)s
+\end{document}
+'''
+
+class collected_footnote(nodes.footnote):
+ """Footnotes that are collected are assigned this class."""
+
+class UnsupportedError(SphinxError):
+ category = 'Markup is unsupported in LaTeX'
+
+
+class LaTeXWriter(writers.Writer):
+
+ supported = ('sphinxlatex',)
+
+ settings_spec = ('LaTeX writer options', '', (
+ ('Document name', ['--docname'], {'default': ''}),
+ ('Document class', ['--docclass'], {'default': 'manual'}),
+ ('Author', ['--author'], {'default': ''}),
+ ))
+ settings_defaults = {}
+
+ output = None
+
+ def __init__(self, builder):
+ writers.Writer.__init__(self)
+ self.builder = builder
+
+ def translate(self):
+ visitor = LaTeXTranslator(self.document, self.builder)
+ self.document.walkabout(visitor)
+ self.output = visitor.astext()
+
+
+# Helper classes
+
+class ExtBabel(Babel):
+ def get_shorthandoff(self):
+ shortlang = self.language.split('_')[0]
+ if shortlang in ('de', 'ngerman', 'sl', 'slovene', 'pt', 'portuges',
+ 'es', 'spanish', 'nl', 'dutch', 'pl', 'polish', 'it',
+ 'italian'):
+ return '\\shorthandoff{"}'
+ return ''
+
+ def uses_cyrillic(self):
+ shortlang = self.language.split('_')[0]
+ return shortlang in ('bg','bulgarian', 'kk','kazakh',
+ 'mn','mongolian', 'ru','russian',
+ 'uk','ukrainian')
+
+# in latest trunk, the attribute is called Babel.language_codes and already
+# includes Slovene
+if hasattr(Babel, '_ISO639_TO_BABEL'):
+ Babel._ISO639_TO_BABEL['sl'] = 'slovene'
+
+
+class Table(object):
+ def __init__(self):
+ self.col = 0
+ self.colcount = 0
+ self.colspec = None
+ self.rowcount = 0
+ self.had_head = False
+ self.has_problematic = False
+ self.has_verbatim = False
+ self.caption = None
+ self.longtable = False
+
+
+class LaTeXTranslator(nodes.NodeVisitor):
+ sectionnames = ["part", "chapter", "section", "subsection",
+ "subsubsection", "paragraph", "subparagraph"]
+
+ ignore_missing_images = False
+
+ default_elements = {
+ 'papersize': 'letterpaper',
+ 'pointsize': '10pt',
+ 'classoptions': '',
+ 'extraclassoptions': '',
+ 'inputenc': '\\usepackage[utf8]{inputenc}',
+ 'utf8extra': '\\DeclareUnicodeCharacter{00A0}{\\nobreakspace}',
+ 'cmappkg': '\\usepackage{cmap}',
+ 'fontenc': '\\usepackage[T1]{fontenc}',
+ 'babel': '\\usepackage{babel}',
+ 'fontpkg': '\\usepackage{times}',
+ 'fncychap': '\\usepackage[Bjarne]{fncychap}',
+ 'longtable': '\\usepackage{longtable}',
+ 'preamble': '',
+ 'title': '',
+ 'date': '',
+ 'release': '',
+ 'author': '',
+ 'logo': '',
+ 'releasename': 'Release',
+ 'makeindex': '\\makeindex',
+ 'shorthandoff': '',
+ 'maketitle': '\\maketitle',
+ 'tableofcontents': '\\tableofcontents',
+ 'footer': '',
+ 'printindex': '\\printindex',
+ 'transition': '\n\n\\bigskip\\hrule{}\\bigskip\n\n',
+ }
+
+ # sphinx specific document classes
+ docclasses = ('howto', 'manual')
+
+ def __init__(self, document, builder):
+ nodes.NodeVisitor.__init__(self, document)
+ self.builder = builder
+ self.body = []
+
+ # sort out some elements
+ papersize = builder.config.latex_paper_size + 'paper'
+ if papersize == 'paper': # e.g. command line "-D latex_paper_size="
+ papersize = 'letterpaper'
+
+ self.elements = self.default_elements.copy()
+ self.elements.update({
+ 'wrapperclass': self.format_docclass(document.settings.docclass),
+ 'papersize': papersize,
+ 'pointsize': builder.config.latex_font_size,
+ # if empty, the title is set to the first section title
+ 'title': document.settings.title,
+ 'release': builder.config.release,
+ 'author': document.settings.author,
+ 'releasename': _('Release'),
+ 'preamble': builder.config.latex_preamble,
+ 'indexname': _('Index'),
+ })
+ if document.settings.docclass == 'howto':
+ docclass = builder.config.latex_docclass.get('howto', 'article')
+ else:
+ docclass = builder.config.latex_docclass.get('manual', 'report')
+ self.elements['docclass'] = docclass
+ if builder.config.today:
+ self.elements['date'] = builder.config.today
+ else:
+ self.elements['date'] = ustrftime(builder.config.today_fmt
+ or _('%B %d, %Y'))
+ if builder.config.latex_logo:
+ self.elements['logo'] = '\\includegraphics{%s}\\par' % \
+ path.basename(builder.config.latex_logo)
+ if builder.config.language:
+ babel = ExtBabel(builder.config.language)
+ lang = babel.get_language()
+ if lang:
+ self.elements['classoptions'] += ',' + babel.get_language()
+ else:
+ self.builder.warn('no Babel option known for language %r' %
+ builder.config.language)
+ self.elements['shorthandoff'] = babel.get_shorthandoff()
+ self.elements['fncychap'] = '\\usepackage[Sonny]{fncychap}'
+
+ # Times fonts don't work with Cyrillic languages
+ if babel.uses_cyrillic():
+ self.elements['fontpkg'] = ''
+
+ # pTeX (Japanese TeX) for support
+ if builder.config.language == 'ja':
+ # use dvipdfmx as default class option in Japanese
+ self.elements['classoptions'] = ',dvipdfmx'
+ # disable babel which has not publishing quality in Japanese
+ self.elements['babel'] = ''
+ # disable fncychap in Japanese documents
+ self.elements['fncychap'] = ''
+ else:
+ self.elements['classoptions'] += ',english'
+ # allow the user to override them all
+ self.elements.update(builder.config.latex_elements)
+ if self.elements['extraclassoptions']:
+ self.elements['classoptions'] += ',' + \
+ self.elements['extraclassoptions']
+
+ self.highlighter = highlighting.PygmentsBridge('latex',
+ builder.config.pygments_style, builder.config.trim_doctest_flags)
+ self.context = []
+ self.descstack = []
+ self.bibitems = []
+ self.table = None
+ self.next_table_colspec = None
+ # stack of [language, linenothreshold] settings per file
+ # the first item here is the default and must not be changed
+ # the second item is the default for the master file and can be changed
+ # by .. highlight:: directive in the master file
+ self.hlsettingstack = 2 * [[builder.config.highlight_language,
+ sys.maxint]]
+ self.footnotestack = []
+ self.curfilestack = []
+ self.handled_abbrs = set()
+ if document.settings.docclass == 'howto':
+ self.top_sectionlevel = 2
+ else:
+ if builder.config.latex_use_parts:
+ self.top_sectionlevel = 0
+ else:
+ self.top_sectionlevel = 1
+ self.next_section_ids = set()
+ self.next_figure_ids = set()
+ self.next_table_ids = set()
+ # flags
+ self.in_title = 0
+ self.in_production_list = 0
+ self.in_footnote = 0
+ self.in_caption = 0
+ self.first_document = 1
+ self.this_is_the_title = 1
+ self.literal_whitespace = 0
+ self.no_contractions = 0
+ self.compact_list = 0
+ self.first_param = 0
+ self.previous_spanning_row = 0
+ self.previous_spanning_column = 0
+ self.remember_multirow = {}
+
+ def format_docclass(self, docclass):
+ """ prepends prefix to sphinx document classes
+ """
+ if docclass in self.docclasses:
+ docclass = 'sphinx' + docclass
+ return docclass
+
+ def astext(self):
+ return (HEADER % self.elements +
+ self.highlighter.get_stylesheet() +
+ u''.join(self.body) +
+ '\n' + self.elements['footer'] + '\n' +
+ self.generate_indices() +
+ FOOTER % self.elements)
+
+ def hypertarget(self, id, withdoc=True, anchor=True):
+ if withdoc:
+ id = self.curfilestack[-1] + ':' + id
+ return (anchor and '\\phantomsection' or '') + \
+ '\\label{%s}' % self.idescape(id)
+
+ def hyperlink(self, id):
+ return '{\\hyperref[%s]{' % self.idescape(id)
+
+ def hyperpageref(self, id):
+ return '\\autopageref*{%s}' % self.idescape(id)
+
+ def idescape(self, id):
+ return unicode(id).translate(tex_replace_map).\
+ encode('ascii', 'backslashreplace').decode('ascii').\
+ replace('\\', '_')
+
+ def generate_indices(self):
+ def generate(content, collapsed):
+ ret.append('\\begin{theindex}\n')
+ ret.append('\\def\\bigletter#1{{\\Large\\sffamily#1}'
+ '\\nopagebreak\\vspace{1mm}}\n')
+ for i, (letter, entries) in enumerate(content):
+ if i > 0:
+ ret.append('\\indexspace\n')
+ ret.append('\\bigletter{%s}\n' %
+ unicode(letter).translate(tex_escape_map))
+ for entry in entries:
+ if not entry[3]:
+ continue
+ ret.append('\\item {\\texttt{%s}}' % self.encode(entry[0]))
+ if entry[4]:
+ # add "extra" info
+ ret.append(' \\emph{(%s)}' % self.encode(entry[4]))
+ ret.append(', \\pageref{%s:%s}\n' %
+ (entry[2], self.idescape(entry[3])))
+ ret.append('\\end{theindex}\n')
+
+ ret = []
+ # latex_domain_indices can be False/True or a list of index names
+ indices_config = self.builder.config.latex_domain_indices
+ if indices_config:
+ for domain in self.builder.env.domains.itervalues():
+ for indexcls in domain.indices:
+ indexname = '%s-%s' % (domain.name, indexcls.name)
+ if isinstance(indices_config, list):
+ if indexname not in indices_config:
+ continue
+ # deprecated config value
+ if indexname == 'py-modindex' and \
+ not self.builder.config.latex_use_modindex:
+ continue
+ content, collapsed = indexcls(domain).generate(
+ self.builder.docnames)
+ if not content:
+ continue
+ ret.append(u'\\renewcommand{\\indexname}{%s}\n' %
+ indexcls.localname)
+ generate(content, collapsed)
+
+ return ''.join(ret)
+
+ def visit_document(self, node):
+ self.footnotestack.append(self.collect_footnotes(node))
+ self.curfilestack.append(node.get('docname', ''))
+ if self.first_document == 1:
+ # the first document is all the regular content ...
+ self.body.append(BEGIN_DOC % self.elements)
+ self.first_document = 0
+ elif self.first_document == 0:
+ # ... and all others are the appendices
+ self.body.append(u'\n\\appendix\n')
+ self.first_document = -1
+ if 'docname' in node:
+ self.body.append(self.hypertarget(':doc'))
+ # "- 1" because the level is increased before the title is visited
+ self.sectionlevel = self.top_sectionlevel - 1
+ def depart_document(self, node):
+ if self.bibitems:
+ widest_label = ""
+ for bi in self.bibitems:
+ if len(widest_label) < len(bi[0]):
+ widest_label = bi[0]
+ self.body.append(u'\n\\begin{thebibliography}{%s}\n' % widest_label)
+ for bi in self.bibitems:
+ target = self.hypertarget(bi[2] + ':' + bi[3],
+ withdoc=False)
+ self.body.append(u'\\bibitem[%s]{%s}{%s %s}\n' %
+ (bi[0], self.idescape(bi[0]), target, bi[1]))
+ self.body.append(u'\\end{thebibliography}\n')
+ self.bibitems = []
+
+ def visit_start_of_file(self, node):
+ # collect new footnotes
+ self.footnotestack.append(self.collect_footnotes(node))
+ # also add a document target
+ self.next_section_ids.add(':doc')
+ self.curfilestack.append(node['docname'])
+ # use default highlight settings for new file
+ self.hlsettingstack.append(self.hlsettingstack[0])
+
+ def collect_footnotes(self, node):
+ fnotes = {}
+ def footnotes_under(n):
+ if isinstance(n, nodes.footnote):
+ yield n
+ else:
+ for c in n.children:
+ if isinstance(c, addnodes.start_of_file):
+ continue
+ for k in footnotes_under(c):
+ yield k
+ for fn in footnotes_under(node):
+ num = fn.children[0].astext().strip()
+ fnotes[num] = [collected_footnote(*fn.children), False]
+ return fnotes
+
+ def depart_start_of_file(self, node):
+ self.footnotestack.pop()
+ self.curfilestack.pop()
+ self.hlsettingstack.pop()
+
+ def visit_highlightlang(self, node):
+ self.hlsettingstack[-1] = [node['lang'], node['linenothreshold']]
+ raise nodes.SkipNode
+
+ def visit_section(self, node):
+ if not self.this_is_the_title:
+ self.sectionlevel += 1
+ self.body.append('\n\n')
+ if node.get('ids'):
+ self.next_section_ids.update(node['ids'])
+ def depart_section(self, node):
+ self.sectionlevel = max(self.sectionlevel - 1,
+ self.top_sectionlevel - 1)
+
+ def visit_problematic(self, node):
+ self.body.append(r'{\color{red}\bfseries{}')
+ def depart_problematic(self, node):
+ self.body.append('}')
+
+ def visit_topic(self, node):
+ self.body.append('\\setbox0\\vbox{\n'
+ '\\begin{minipage}{0.95\\linewidth}\n')
+ def depart_topic(self, node):
+ self.body.append('\\end{minipage}}\n'
+ '\\begin{center}\\setlength{\\fboxsep}{5pt}'
+ '\\shadowbox{\\box0}\\end{center}\n')
+ visit_sidebar = visit_topic
+ depart_sidebar = depart_topic
+
+ def visit_glossary(self, node):
+ pass
+ def depart_glossary(self, node):
+ pass
+
+ def visit_productionlist(self, node):
+ self.body.append('\n\n\\begin{productionlist}\n')
+ self.in_production_list = 1
+ def depart_productionlist(self, node):
+ self.body.append('\\end{productionlist}\n\n')
+ self.in_production_list = 0
+
+ def visit_production(self, node):
+ if node['tokenname']:
+ tn = node['tokenname']
+ self.body.append(self.hypertarget('grammar-token-' + tn))
+ self.body.append('\\production{%s}{' % self.encode(tn))
+ else:
+ self.body.append('\\productioncont{')
+ def depart_production(self, node):
+ self.body.append('}\n')
+
+ def visit_transition(self, node):
+ self.body.append(self.elements['transition'])
+ def depart_transition(self, node):
+ pass
+
+ def visit_title(self, node):
+ parent = node.parent
+ if isinstance(parent, addnodes.seealso):
+ # the environment already handles this
+ raise nodes.SkipNode
+ elif self.this_is_the_title:
+ if len(node.children) != 1 and not isinstance(node.children[0],
+ nodes.Text):
+ self.builder.warn('document title is not a single Text node',
+ (self.curfilestack[-1], node.line))
+ if not self.elements['title']:
+ # text needs to be escaped since it is inserted into
+ # the output literally
+ self.elements['title'] = node.astext().translate(tex_escape_map)
+ self.this_is_the_title = 0
+ raise nodes.SkipNode
+ elif isinstance(parent, nodes.section):
+ try:
+ self.body.append(r'\%s{' % self.sectionnames[self.sectionlevel])
+ except IndexError:
+ # just use "subparagraph", it's not numbered anyway
+ self.body.append(r'\%s{' % self.sectionnames[-1])
+ self.context.append('}\n')
+
+ if self.next_section_ids:
+ for id in self.next_section_ids:
+ self.context[-1] += self.hypertarget(id, anchor=False)
+ self.next_section_ids.clear()
+
+ elif isinstance(parent, (nodes.topic, nodes.sidebar)):
+ self.body.append(r'\textbf{')
+ self.context.append('}\n\n\medskip\n\n')
+ elif isinstance(parent, nodes.Admonition):
+ self.body.append('{')
+ self.context.append('}\n')
+ elif isinstance(parent, nodes.table):
+ self.table.caption = self.encode(node.astext())
+ raise nodes.SkipNode
+ else:
+ self.builder.warn(
+ 'encountered title node not in section, topic, table, '
+ 'admonition or sidebar',
+ (self.curfilestack[-1], node.line or ''))
+ self.body.append('\\textbf{')
+ self.context.append('}\n')
+ self.in_title = 1
+ def depart_title(self, node):
+ self.in_title = 0
+ self.body.append(self.context.pop())
+
+ def visit_subtitle(self, node):
+ if isinstance(node.parent, nodes.sidebar):
+ self.body.append('~\\\\\n\\textbf{')
+ self.context.append('}\n\\smallskip\n')
+ else:
+ self.context.append('')
+ def depart_subtitle(self, node):
+ self.body.append(self.context.pop())
+
+ def visit_desc(self, node):
+ self.body.append('\n\n\\begin{fulllineitems}\n')
+ if self.table:
+ self.table.has_problematic = True
+ def depart_desc(self, node):
+ self.body.append('\n\\end{fulllineitems}\n\n')
+
+ def visit_desc_signature(self, node):
+ if node.parent['objtype'] != 'describe' and node['ids']:
+ hyper = self.hypertarget(node['ids'][0])
+ else:
+ hyper = ''
+ self.body.append(hyper)
+ for child in node:
+ if isinstance(child, addnodes.desc_parameterlist):
+ self.body.append(r'\pysiglinewithargsret{')
+ break
+ else:
+ self.body.append(r'\pysigline{')
+ def depart_desc_signature(self, node):
+ self.body.append('}')
+
+ def visit_desc_addname(self, node):
+ self.body.append(r'\code{')
+ self.literal_whitespace += 1
+ def depart_desc_addname(self, node):
+ self.body.append('}')
+ self.literal_whitespace -= 1
+
+ def visit_desc_type(self, node):
+ pass
+ def depart_desc_type(self, node):
+ pass
+
+ def visit_desc_returns(self, node):
+ self.body.append(r'{ $\rightarrow$ ')
+ def depart_desc_returns(self, node):
+ self.body.append(r'}')
+
+ def visit_desc_name(self, node):
+ self.body.append(r'\bfcode{')
+ self.no_contractions += 1
+ self.literal_whitespace += 1
+ def depart_desc_name(self, node):
+ self.body.append('}')
+ self.literal_whitespace -= 1
+ self.no_contractions -= 1
+
+ def visit_desc_parameterlist(self, node):
+ # close name, open parameterlist
+ self.body.append('}{')
+ self.first_param = 1
+ def depart_desc_parameterlist(self, node):
+ # close parameterlist, open return annotation
+ self.body.append('}{')
+
+ def visit_desc_parameter(self, node):
+ if not self.first_param:
+ self.body.append(', ')
+ else:
+ self.first_param = 0
+ if not node.hasattr('noemph'):
+ self.body.append(r'\emph{')
+ def depart_desc_parameter(self, node):
+ if not node.hasattr('noemph'):
+ self.body.append('}')
+
+ def visit_desc_optional(self, node):
+ self.body.append(r'\optional{')
+ def depart_desc_optional(self, node):
+ self.body.append('}')
+
+ def visit_desc_annotation(self, node):
+ self.body.append(r'\strong{')
+ def depart_desc_annotation(self, node):
+ self.body.append('}')
+
+ def visit_desc_content(self, node):
+ if node.children and not isinstance(node.children[0], nodes.paragraph):
+ # avoid empty desc environment which causes a formatting bug
+ self.body.append('~')
+ def depart_desc_content(self, node):
+ pass
+
+ def visit_seealso(self, node):
+ self.body.append(u'\n\n\\strong{%s:}\n\n' % admonitionlabels['seealso'])
+ def depart_seealso(self, node):
+ self.body.append("\n\n")
+
+ def visit_rubric(self, node):
+ if len(node.children) == 1 and node.children[0].astext() in \
+ ('Footnotes', _('Footnotes')):
+ raise nodes.SkipNode
+ self.body.append('\\paragraph{')
+ self.context.append('}\n')
+ def depart_rubric(self, node):
+ self.body.append(self.context.pop())
+
+ def visit_footnote(self, node):
+ raise nodes.SkipNode
+
+ def visit_collected_footnote(self, node):
+ self.in_footnote += 1
+ self.body.append('\\footnote{')
+ def depart_collected_footnote(self, node):
+ self.body.append('}')
+ self.in_footnote -= 1
+
+ def visit_label(self, node):
+ if isinstance(node.parent, nodes.citation):
+ self.bibitems[-1][0] = node.astext()
+ self.bibitems[-1][2] = self.curfilestack[-1]
+ self.bibitems[-1][3] = node.parent['ids'][0]
+ raise nodes.SkipNode
+
+ def visit_tabular_col_spec(self, node):
+ self.next_table_colspec = node['spec']
+ raise nodes.SkipNode
+
+ def visit_table(self, node):
+ if self.table:
+ raise UnsupportedError(
+ '%s:%s: nested tables are not yet implemented.' %
+ (self.curfilestack[-1], node.line or ''))
+ self.table = Table()
+ self.table.longtable = 'longtable' in node['classes']
+ self.tablebody = []
+ self.tableheaders = []
+ # Redirect body output until table is finished.
+ self._body = self.body
+ self.body = self.tablebody
+ def depart_table(self, node):
+ if self.table.rowcount > 30:
+ self.table.longtable = True
+ self.body = self._body
+ if not self.table.longtable and self.table.caption is not None:
+ self.body.append(u'\n\n\\begin{threeparttable}\n'
+ u'\\capstart\\caption{%s}\n' % self.table.caption)
+ if self.table.longtable:
+ self.body.append('\n\\begin{longtable}')
+ endmacro = '\\end{longtable}\n\n'
+ elif self.table.has_verbatim:
+ self.body.append('\n\\begin{tabular}')
+ endmacro = '\\end{tabular}\n\n'
+ elif self.table.has_problematic and not self.table.colspec:
+ # if the user has given us tabularcolumns, accept them and use
+ # tabulary nevertheless
+ self.body.append('\n\\begin{tabular}')
+ endmacro = '\\end{tabular}\n\n'
+ else:
+ self.body.append('\n\\begin{tabulary}{\\linewidth}')
+ endmacro = '\\end{tabulary}\n\n'
+ if self.table.colspec:
+ self.body.append(self.table.colspec)
+ else:
+ if self.table.has_problematic:
+ colwidth = 0.95 / self.table.colcount
+ colspec = ('p{%.3f\\linewidth}|' % colwidth) * \
+ self.table.colcount
+ self.body.append('{|' + colspec + '}\n')
+ elif self.table.longtable:
+ self.body.append('{|' + ('l|' * self.table.colcount) + '}\n')
+ else:
+ self.body.append('{|' + ('L|' * self.table.colcount) + '}\n')
+ if self.table.longtable and self.table.caption is not None:
+ self.body.append(u'\\caption{%s} \\\\\n' % self.table.caption)
+ if self.table.caption is not None:
+ for id in self.next_table_ids:
+ self.body.append(self.hypertarget(id, anchor=False))
+ self.next_table_ids.clear()
+ if self.table.longtable:
+ self.body.append('\\hline\n')
+ self.body.extend(self.tableheaders)
+ self.body.append('\\endfirsthead\n\n')
+ self.body.append('\\multicolumn{%s}{c}%%\n' % self.table.colcount)
+ self.body.append(r'{{\textsf{\tablename\ \thetable{} -- %s}}} \\'
+ % _('continued from previous page'))
+ self.body.append('\n\\hline\n')
+ self.body.extend(self.tableheaders)
+ self.body.append('\\endhead\n\n')
+ self.body.append(ur'\hline \multicolumn{%s}{|r|}{{\textsf{%s}}} \\ \hline'
+ % (self.table.colcount,
+ _('Continued on next page')))
+ self.body.append('\n\\endfoot\n\n')
+ self.body.append('\\endlastfoot\n\n')
+ else:
+ self.body.append('\\hline\n')
+ self.body.extend(self.tableheaders)
+ self.body.extend(self.tablebody)
+ self.body.append(endmacro)
+ if not self.table.longtable and self.table.caption is not None:
+ self.body.append('\\end{threeparttable}\n\n')
+ self.table = None
+ self.tablebody = None
+
+ def visit_colspec(self, node):
+ self.table.colcount += 1
+ def depart_colspec(self, node):
+ pass
+
+ def visit_tgroup(self, node):
+ pass
+ def depart_tgroup(self, node):
+ pass
+
+ def visit_thead(self, node):
+ self.table.had_head = True
+ if self.next_table_colspec:
+ self.table.colspec = '{%s}\n' % self.next_table_colspec
+ self.next_table_colspec = None
+ # Redirect head output until header is finished. see visit_tbody.
+ self.body = self.tableheaders
+ def depart_thead(self, node):
+ self.body.append('\\hline')
+
+ def visit_tbody(self, node):
+ if not self.table.had_head:
+ self.visit_thead(node)
+ self.body = self.tablebody
+ def depart_tbody(self, node):
+ self.body.append('\\hline')
+
+ def visit_row(self, node):
+ self.table.col = 0
+ def depart_row(self, node):
+ if self.previous_spanning_row == 1:
+ self.previous_spanning_row = 0
+ self.body.append('\\\\\n')
+ self.table.rowcount += 1
+
+ def visit_entry(self, node):
+ if self.table.col > 0:
+ self.body.append(' & ')
+ elif self.remember_multirow.get(1, 0) > 1:
+ self.remember_multirow[1] -= 1
+ self.body.append(' & ')
+ self.table.col += 1
+ context = ''
+ if 'morerows' in node:
+ self.body.append(' \multirow{')
+ self.previous_spanning_row = 1
+ self.body.append(str(node.get('morerows') + 1))
+ self.body.append('}{*}{')
+ context += '}'
+ self.remember_multirow[self.table.col] = node.get('morerows') + 1
+ if 'morecols' in node:
+ self.body.append(' \multicolumn{')
+ self.body.append(str(node.get('morecols') + 1))
+ if self.table.col == 1:
+ self.body.append('}{|l|}{')
+ else:
+ self.body.append('}{l|}{')
+ context += '}'
+ if isinstance(node.parent.parent, nodes.thead):
+ self.body.append('\\textsf{\\relax ')
+ context += '}'
+ if self.remember_multirow.get(self.table.col + 1, 0) > 1:
+ self.remember_multirow[self.table.col + 1] -= 1
+ context += ' & '
+ self.context.append(context)
+ def depart_entry(self, node):
+ self.body.append(self.context.pop()) # header
+
+ def visit_acks(self, node):
+ # this is a list in the source, but should be rendered as a
+ # comma-separated list here
+ self.body.append('\n\n')
+ self.body.append(', '.join(n.astext()
+ for n in node.children[0].children) + '.')
+ self.body.append('\n\n')
+ raise nodes.SkipNode
+
+ def visit_bullet_list(self, node):
+ if not self.compact_list:
+ self.body.append('\\begin{itemize}\n' )
+ if self.table:
+ self.table.has_problematic = True
+ def depart_bullet_list(self, node):
+ if not self.compact_list:
+ self.body.append('\\end{itemize}\n' )
+
+ def visit_enumerated_list(self, node):
+ self.body.append('\\begin{enumerate}\n' )
+ if 'start' in node:
+ self.body.append('\\setcounter{enumi}{%d}\n' % (node['start'] - 1))
+ if self.table:
+ self.table.has_problematic = True
+ def depart_enumerated_list(self, node):
+ self.body.append('\\end{enumerate}\n' )
+
+ def visit_list_item(self, node):
+ # Append "{}" in case the next character is "[", which would break
+ # LaTeX's list environment (no numbering and the "[" is not printed).
+ self.body.append(r'\item {} ')
+ def depart_list_item(self, node):
+ self.body.append('\n')
+
+ def visit_definition_list(self, node):
+ self.body.append('\\begin{description}\n')
+ if self.table:
+ self.table.has_problematic = True
+ def depart_definition_list(self, node):
+ self.body.append('\\end{description}\n')
+
+ def visit_definition_list_item(self, node):
+ pass
+ def depart_definition_list_item(self, node):
+ pass
+
+ def visit_term(self, node):
+ ctx = '}] \\leavevmode'
+ if node.get('ids'):
+ ctx += self.hypertarget(node['ids'][0])
+ self.body.append('\\item[{')
+ self.context.append(ctx)
+ def depart_term(self, node):
+ self.body.append(self.context.pop())
+
+ def visit_termsep(self, node):
+ self.body.append(', ')
+ raise nodes.SkipNode
+
+ def visit_classifier(self, node):
+ self.body.append('{[}')
+ def depart_classifier(self, node):
+ self.body.append('{]}')
+
+ def visit_definition(self, node):
+ pass
+ def depart_definition(self, node):
+ self.body.append('\n')
+
+ def visit_field_list(self, node):
+ self.body.append('\\begin{quote}\\begin{description}\n')
+ if self.table:
+ self.table.has_problematic = True
+ def depart_field_list(self, node):
+ self.body.append('\\end{description}\\end{quote}\n')
+
+ def visit_field(self, node):
+ pass
+ def depart_field(self, node):
+ pass
+
+ visit_field_name = visit_term
+ depart_field_name = depart_term
+
+ visit_field_body = visit_definition
+ depart_field_body = depart_definition
+
+ def visit_paragraph(self, node):
+ self.body.append('\n')
+ def depart_paragraph(self, node):
+ self.body.append('\n')
+
+ def visit_centered(self, node):
+ self.body.append('\n\\begin{center}')
+ if self.table:
+ self.table.has_problematic = True
+ def depart_centered(self, node):
+ self.body.append('\n\\end{center}')
+
+ def visit_hlist(self, node):
+ # for now, we don't support a more compact list format
+ # don't add individual itemize environments, but one for all columns
+ self.compact_list += 1
+ self.body.append('\\begin{itemize}\\setlength{\\itemsep}{0pt}'
+ '\\setlength{\\parskip}{0pt}\n')
+ if self.table:
+ self.table.has_problematic = True
+ def depart_hlist(self, node):
+ self.compact_list -= 1
+ self.body.append('\\end{itemize}\n')
+
+ def visit_hlistcol(self, node):
+ pass
+ def depart_hlistcol(self, node):
+ pass
+
+ def latex_image_length(self, width_str):
+ match = re.match('(\d*\.?\d*)\s*(\S*)', width_str)
+ if not match:
+ # fallback
+ return width_str
+ res = width_str
+ amount, unit = match.groups()[:2]
+ if not unit or unit == "px":
+ # pixels: let LaTeX alone
+ return None
+ elif unit == "%":
+ res = "%.3f\\linewidth" % (float(amount) / 100.0)
+ return res
+
+ def is_inline(self, node):
+ """Check whether a node represents an inline element."""
+ return isinstance(node.parent, nodes.TextElement)
+
+ def visit_image(self, node):
+ attrs = node.attributes
+ pre = [] # in reverse order
+ post = []
+ include_graphics_options = []
+ is_inline = self.is_inline(node)
+ if 'scale' in attrs:
+ # Could also be done with ``scale`` option to
+ # ``\includegraphics``; doing it this way for consistency.
+ pre.append('\\scalebox{%f}{' % (attrs['scale'] / 100.0,))
+ post.append('}')
+ if 'width' in attrs:
+ w = self.latex_image_length(attrs['width'])
+ if w:
+ include_graphics_options.append('width=%s' % w)
+ if 'height' in attrs:
+ h = self.latex_image_length(attrs['height'])
+ if h:
+ include_graphics_options.append('height=%s' % h)
+ if 'align' in attrs:
+ align_prepost = {
+ # By default latex aligns the top of an image.
+ (1, 'top'): ('', ''),
+ (1, 'middle'): ('\\raisebox{-0.5\\height}{', '}'),
+ (1, 'bottom'): ('\\raisebox{-\\height}{', '}'),
+ (0, 'center'): ('{\\hfill', '\\hfill}'),
+ # These 2 don't exactly do the right thing. The image should
+ # be floated alongside the paragraph. See
+ # http://www.w3.org/TR/html4/struct/objects.html#adef-align-IMG
+ (0, 'left'): ('{', '\\hfill}'),
+ (0, 'right'): ('{\\hfill', '}'),}
+ try:
+ pre.append(align_prepost[is_inline, attrs['align']][0])
+ post.append(align_prepost[is_inline, attrs['align']][1])
+ except KeyError:
+ pass
+ if not is_inline:
+ pre.append('\n')
+ post.append('\n')
+ pre.reverse()
+ if node['uri'] in self.builder.images:
+ uri = self.builder.images[node['uri']]
+ else:
+ # missing image!
+ if self.ignore_missing_images:
+ return
+ uri = node['uri']
+ if uri.find('://') != -1:
+ # ignore remote images
+ return
+ self.body.extend(pre)
+ options = ''
+ if include_graphics_options:
+ options = '[%s]' % ','.join(include_graphics_options)
+ self.body.append('\\includegraphics%s{%s}' % (options, uri))
+ self.body.extend(post)
+ def depart_image(self, node):
+ pass
+
+ def visit_figure(self, node):
+ ids = ''
+ for id in self.next_figure_ids:
+ ids += self.hypertarget(id, anchor=False)
+ self.next_figure_ids.clear()
+ if 'width' in node and node.get('align', '') in ('left', 'right'):
+ self.body.append('\\begin{wrapfigure}{%s}{%s}\n\\centering' %
+ (node['align'] == 'right' and 'r' or 'l',
+ node['width']))
+ self.context.append(ids + '\\end{wrapfigure}\n')
+ else:
+ if (not 'align' in node.attributes or
+ node.attributes['align'] == 'center'):
+ # centering does not add vertical space like center.
+ align = '\n\\centering'
+ align_end = ''
+ else:
+ # TODO non vertical space for other alignments.
+ align = '\\begin{flush%s}' % node.attributes['align']
+ align_end = '\\end{flush%s}' % node.attributes['align']
+ self.body.append('\\begin{figure}[htbp]%s\n' % align)
+ if any(isinstance(child, nodes.caption) for child in node):
+ self.body.append('\\capstart\n')
+ self.context.append(ids + align_end + '\\end{figure}\n')
+ def depart_figure(self, node):
+ self.body.append(self.context.pop())
+
+ def visit_caption(self, node):
+ self.in_caption += 1
+ self.body.append('\\caption{')
+ def depart_caption(self, node):
+ self.body.append('}')
+ self.in_caption -= 1
+
+ def visit_legend(self, node):
+ self.body.append('{\\small ')
+ def depart_legend(self, node):
+ self.body.append('}')
+
+ def visit_admonition(self, node):
+ self.body.append('\n\\begin{notice}{note}')
+ def depart_admonition(self, node):
+ self.body.append('\\end{notice}\n')
+
+ def _make_visit_admonition(name):
+ def visit_admonition(self, node):
+ self.body.append(u'\n\\begin{notice}{%s}{%s:}' %
+ (name, admonitionlabels[name]))
+ return visit_admonition
+ def _depart_named_admonition(self, node):
+ self.body.append('\\end{notice}\n')
+
+ visit_attention = _make_visit_admonition('attention')
+ depart_attention = _depart_named_admonition
+ visit_caution = _make_visit_admonition('caution')
+ depart_caution = _depart_named_admonition
+ visit_danger = _make_visit_admonition('danger')
+ depart_danger = _depart_named_admonition
+ visit_error = _make_visit_admonition('error')
+ depart_error = _depart_named_admonition
+ visit_hint = _make_visit_admonition('hint')
+ depart_hint = _depart_named_admonition
+ visit_important = _make_visit_admonition('important')
+ depart_important = _depart_named_admonition
+ visit_note = _make_visit_admonition('note')
+ depart_note = _depart_named_admonition
+ visit_tip = _make_visit_admonition('tip')
+ depart_tip = _depart_named_admonition
+ visit_warning = _make_visit_admonition('warning')
+ depart_warning = _depart_named_admonition
+
+ def visit_versionmodified(self, node):
+ pass
+ def depart_versionmodified(self, node):
+ pass
+
+ def visit_target(self, node):
+ def add_target(id):
+ # indexing uses standard LaTeX index markup, so the targets
+ # will be generated differently
+ if id.startswith('index-'):
+ return
+ # do not generate \phantomsection in \section{}
+ anchor = not self.in_title
+ self.body.append(self.hypertarget(id, anchor=anchor))
+
+ # postpone the labels until after the sectioning command
+ parindex = node.parent.index(node)
+ try:
+ try:
+ next = node.parent[parindex+1]
+ except IndexError:
+ # last node in parent, look at next after parent
+ # (for section of equal level) if it exists
+ if node.parent.parent is not None:
+ next = node.parent.parent[
+ node.parent.parent.index(node.parent)]
+ else:
+ raise
+ if isinstance(next, nodes.section):
+ if node.get('refid'):
+ self.next_section_ids.add(node['refid'])
+ self.next_section_ids.update(node['ids'])
+ return
+ elif isinstance(next, nodes.figure):
+ # labels for figures go in the figure body, not before
+ if node.get('refid'):
+ self.next_figure_ids.add(node['refid'])
+ self.next_figure_ids.update(node['ids'])
+ return
+ elif isinstance(next, nodes.table):
+ # same for tables, but only if they have a caption
+ for n in node:
+ if isinstance(n, nodes.title):
+ if node.get('refid'):
+ self.next_table_ids.add(node['refid'])
+ self.next_table_ids.update(node['ids'])
+ return
+ except IndexError:
+ pass
+ if 'refuri' in node:
+ return
+ if node.get('refid'):
+ add_target(node['refid'])
+ for id in node['ids']:
+ add_target(id)
+ def depart_target(self, node):
+ pass
+
+ def visit_attribution(self, node):
+ self.body.append('\n\\begin{flushright}\n')
+ self.body.append('---')
+ def depart_attribution(self, node):
+ self.body.append('\n\\end{flushright}\n')
+
+ def visit_index(self, node, scre=re.compile(r';\s*')):
+ if not node.get('inline', True):
+ self.body.append('\n')
+ entries = node['entries']
+ for type, string, tid, ismain in entries:
+ m = ''
+ if ismain:
+ m = '|textbf'
+ try:
+ if type == 'single':
+ p = scre.sub('!', self.encode(string))
+ self.body.append(r'\index{%s%s}' % (p, m))
+ elif type == 'pair':
+ p1, p2 = map(self.encode, split_into(2, 'pair', string))
+ self.body.append(r'\index{%s!%s%s}\index{%s!%s%s}' %
+ (p1, p2, m, p2, p1, m))
+ elif type == 'triple':
+ p1, p2, p3 = map(self.encode,
+ split_into(3, 'triple', string))
+ self.body.append(
+ r'\index{%s!%s %s%s}\index{%s!%s, %s%s}'
+ r'\index{%s!%s %s%s}' %
+ (p1, p2, p3, m, p2, p3, p1, m, p3, p1, p2, m))
+ elif type == 'see':
+ p1, p2 = map(self.encode, split_into(2, 'see', string))
+ self.body.append(r'\index{%s|see{%s}}' % (p1, p2))
+ elif type == 'seealso':
+ p1, p2 = map(self.encode, split_into(2, 'seealso', string))
+ self.body.append(r'\index{%s|see{%s}}' % (p1, p2))
+ else:
+ self.builder.warn(
+ 'unknown index entry type %s found' % type)
+ except ValueError, err:
+ self.builder.warn(str(err))
+ raise nodes.SkipNode
+
+ def visit_raw(self, node):
+ if 'latex' in node.get('format', '').split():
+ self.body.append(node.astext())
+ raise nodes.SkipNode
+
+ def visit_reference(self, node):
+ uri = node.get('refuri', '')
+ if not uri and node.get('refid'):
+ uri = '%' + self.curfilestack[-1] + '#' + node['refid']
+ if self.in_title or not uri:
+ self.context.append('')
+ elif uri.startswith('mailto:') or uri.startswith('http:') or \
+ uri.startswith('https:') or uri.startswith('ftp:'):
+ self.body.append('\\href{%s}{' % self.encode_uri(uri))
+ # if configured, put the URL after the link
+ show_urls = self.builder.config.latex_show_urls
+ if node.astext() != uri and show_urls and show_urls != 'no':
+ if uri.startswith('mailto:'):
+ uri = uri[7:]
+ if show_urls == 'footnote' and not \
+ (self.in_footnote or self.in_caption):
+ # obviously, footnotes in footnotes are not going to work
+ self.context.append(
+ r'}\footnote{%s}' % self.encode_uri(uri))
+ else: # all other true values (b/w compat)
+ self.context.append('} (%s)' % self.encode_uri(uri))
+ else:
+ self.context.append('}')
+ elif uri.startswith('#'):
+ # references to labels in the same document
+ id = self.curfilestack[-1] + ':' + uri[1:]
+ self.body.append(self.hyperlink(id))
+ if self.builder.config.latex_show_pagerefs and not \
+ self.in_production_list:
+ self.context.append('}} (%s)' % self.hyperpageref(id))
+ else:
+ self.context.append('}}')
+ elif uri.startswith('%'):
+ # references to documents or labels inside documents
+ hashindex = uri.find('#')
+ if hashindex == -1:
+ # reference to the document
+ id = uri[1:] + '::doc'
+ else:
+ # reference to a label
+ id = uri[1:].replace('#', ':')
+ self.body.append(self.hyperlink(id))
+ if len(node) and hasattr(node[0], 'attributes') and \
+ 'std-term' in node[0].get('classes', []):
+ # don't add a pageref for glossary terms
+ self.context.append('}}')
+ else:
+ if self.builder.config.latex_show_pagerefs:
+ self.context.append('}} (%s)' % self.hyperpageref(id))
+ else:
+ self.context.append('}}')
+ else:
+ self.builder.warn('unusable reference target found: %s' % uri,
+ (self.curfilestack[-1], node.line))
+ self.context.append('')
+ def depart_reference(self, node):
+ self.body.append(self.context.pop())
+
+ def visit_download_reference(self, node):
+ pass
+ def depart_download_reference(self, node):
+ pass
+
+ def visit_pending_xref(self, node):
+ pass
+ def depart_pending_xref(self, node):
+ pass
+
+ def visit_emphasis(self, node):
+ self.body.append(r'\emph{')
+ def depart_emphasis(self, node):
+ self.body.append('}')
+
+ def visit_literal_emphasis(self, node):
+ self.body.append(r'\emph{\texttt{')
+ self.no_contractions += 1
+ def depart_literal_emphasis(self, node):
+ self.body.append('}}')
+ self.no_contractions -= 1
+
+ def visit_strong(self, node):
+ self.body.append(r'\textbf{')
+ def depart_strong(self, node):
+ self.body.append('}')
+
+ def visit_abbreviation(self, node):
+ abbr = node.astext()
+ self.body.append(r'\textsc{')
+ # spell out the explanation once
+ if node.hasattr('explanation') and abbr not in self.handled_abbrs:
+ self.context.append('} (%s)' % self.encode(node['explanation']))
+ self.handled_abbrs.add(abbr)
+ else:
+ self.context.append('}')
+ def depart_abbreviation(self, node):
+ self.body.append(self.context.pop())
+
+ def visit_title_reference(self, node):
+ self.body.append(r'\emph{')
+ def depart_title_reference(self, node):
+ self.body.append('}')
+
+ def visit_citation(self, node):
+ # TODO maybe use cite bibitems
+ # bibitem: [citelabel, citetext, docname, citeid]
+ self.bibitems.append(['', '', '', ''])
+ self.context.append(len(self.body))
+ def depart_citation(self, node):
+ size = self.context.pop()
+ text = ''.join(self.body[size:])
+ del self.body[size:]
+ self.bibitems[-1][1] = text
+
+ def visit_citation_reference(self, node):
+ # This is currently never encountered, since citation_reference nodes
+ # are already replaced by pending_xref nodes in the environment.
+ self.body.append('\\cite{%s}' % self.idescape(node.astext()))
+ raise nodes.SkipNode
+
+ def visit_literal(self, node):
+ self.no_contractions += 1
+ if self.in_title:
+ self.body.append(r'\texttt{')
+ else:
+ self.body.append(r'\code{')
+ def depart_literal(self, node):
+ self.no_contractions -= 1
+ self.body.append('}')
+
+ def visit_footnote_reference(self, node):
+ num = node.astext().strip()
+ try:
+ footnode, used = self.footnotestack[-1][num]
+ except (KeyError, IndexError):
+ raise nodes.SkipNode
+ # if a footnote has been inserted once, it shouldn't be repeated
+ # by the next reference
+ if used:
+ self.body.append('\\footnotemark[%s]' % num)
+ else:
+ if self.in_caption:
+ raise UnsupportedError('%s:%s: footnotes in float captions '
+ 'are not supported by LaTeX' %
+ (self.curfilestack[-1], node.line))
+ footnode.walkabout(self)
+ self.footnotestack[-1][num][1] = True
+ raise nodes.SkipChildren
+ def depart_footnote_reference(self, node):
+ pass
+
+ def visit_literal_block(self, node):
+ if self.in_footnote:
+ raise UnsupportedError('%s:%s: literal blocks in footnotes are '
+ 'not supported by LaTeX' %
+ (self.curfilestack[-1], node.line))
+ if node.rawsource != node.astext():
+ # most probably a parsed-literal block -- don't highlight
+ self.body.append('\\begin{alltt}\n')
+ else:
+ code = node.astext().rstrip('\n')
+ lang = self.hlsettingstack[-1][0]
+ linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
+ highlight_args = node.get('highlight_args', {})
+ if 'language' in node:
+ # code-block directives
+ lang = node['language']
+ highlight_args['force'] = True
+ if 'linenos' in node:
+ linenos = node['linenos']
+ def warner(msg):
+ self.builder.warn(msg, (self.curfilestack[-1], node.line))
+ hlcode = self.highlighter.highlight_block(code, lang, warn=warner,
+ linenos=linenos, **highlight_args)
+ # workaround for Unicode issue
+ hlcode = hlcode.replace(u'€', u'@texteuro[]')
+ # must use original Verbatim environment and "tabular" environment
+ if self.table:
+ hlcode = hlcode.replace('\\begin{Verbatim}',
+ '\\begin{OriginalVerbatim}')
+ self.table.has_problematic = True
+ self.table.has_verbatim = True
+ # get consistent trailer
+ hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim}
+ hlcode = hlcode.rstrip() + '\n'
+ self.body.append('\n' + hlcode + '\\end{%sVerbatim}\n' %
+ (self.table and 'Original' or ''))
+ raise nodes.SkipNode
+ def depart_literal_block(self, node):
+ self.body.append('\n\\end{alltt}\n')
+ visit_doctest_block = visit_literal_block
+ depart_doctest_block = depart_literal_block
+
+ def visit_line(self, node):
+ self.body.append('\item[] ')
+ def depart_line(self, node):
+ self.body.append('\n')
+
+ def visit_line_block(self, node):
+ if isinstance(node.parent, nodes.line_block):
+ self.body.append('\\item[]\n'
+ '\\begin{DUlineblock}{\\DUlineblockindent}\n')
+ else:
+ self.body.append('\n\\begin{DUlineblock}{0em}\n')
+ if self.table:
+ self.table.has_problematic = True
+ def depart_line_block(self, node):
+ self.body.append('\\end{DUlineblock}\n')
+
+ def visit_block_quote(self, node):
+ # If the block quote contains a single object and that object
+ # is a list, then generate a list not a block quote.
+ # This lets us indent lists.
+ done = 0
+ if len(node.children) == 1:
+ child = node.children[0]
+ if isinstance(child, nodes.bullet_list) or \
+ isinstance(child, nodes.enumerated_list):
+ done = 1
+ if not done:
+ self.body.append('\\begin{quote}\n')
+ if self.table:
+ self.table.has_problematic = True
+ def depart_block_quote(self, node):
+ done = 0
+ if len(node.children) == 1:
+ child = node.children[0]
+ if isinstance(child, nodes.bullet_list) or \
+ isinstance(child, nodes.enumerated_list):
+ done = 1
+ if not done:
+ self.body.append('\\end{quote}\n')
+
+ # option node handling copied from docutils' latex writer
+
+ def visit_option(self, node):
+ if self.context[-1]:
+ # this is not the first option
+ self.body.append(', ')
+ def depart_option(self, node):
+ # flag that the first option is done.
+ self.context[-1] += 1
+
+ def visit_option_argument(self, node):
+ """The delimiter betweeen an option and its argument."""
+ self.body.append(node.get('delimiter', ' '))
+ def depart_option_argument(self, node):
+ pass
+
+ def visit_option_group(self, node):
+ self.body.append('\\item [')
+ # flag for first option
+ self.context.append(0)
+ def depart_option_group(self, node):
+ self.context.pop() # the flag
+ self.body.append('] ')
+
+ def visit_option_list(self, node):
+ self.body.append('\\begin{optionlist}{3cm}\n')
+ if self.table:
+ self.table.has_problematic = True
+ def depart_option_list(self, node):
+ self.body.append('\\end{optionlist}\n')
+
+ def visit_option_list_item(self, node):
+ pass
+ def depart_option_list_item(self, node):
+ pass
+
+ def visit_option_string(self, node):
+ ostring = node.astext()
+ self.no_contractions += 1
+ self.body.append(self.encode(ostring))
+ self.no_contractions -= 1
+ raise nodes.SkipNode
+
+ def visit_description(self, node):
+ self.body.append(' ')
+ def depart_description(self, node):
+ pass
+
+ def visit_superscript(self, node):
+ self.body.append('$^{\\text{')
+ def depart_superscript(self, node):
+ self.body.append('}}$')
+
+ def visit_subscript(self, node):
+ self.body.append('$_{\\text{')
+ def depart_subscript(self, node):
+ self.body.append('}}$')
+
+ def visit_substitution_definition(self, node):
+ raise nodes.SkipNode
+
+ def visit_substitution_reference(self, node):
+ raise nodes.SkipNode
+
+ def visit_inline(self, node):
+ classes = node.get('classes', [])
+ self.body.append(r'\DUspan{%s}{' % ','.join(classes))
+ def depart_inline(self, node):
+ self.body.append('}')
+
+ def visit_generated(self, node):
+ pass
+ def depart_generated(self, node):
+ pass
+
+ def visit_compound(self, node):
+ pass
+ def depart_compound(self, node):
+ pass
+
+ def visit_container(self, node):
+ pass
+ def depart_container(self, node):
+ pass
+
+ def visit_decoration(self, node):
+ pass
+ def depart_decoration(self, node):
+ pass
+
+ # docutils-generated elements that we don't support
+
+ def visit_header(self, node):
+ raise nodes.SkipNode
+
+ def visit_footer(self, node):
+ raise nodes.SkipNode
+
+ def visit_docinfo(self, node):
+ raise nodes.SkipNode
+
+ # text handling
+
+ def encode(self, text):
+ text = unicode(text).translate(tex_escape_map)
+ if self.literal_whitespace:
+ # Insert a blank before the newline, to avoid
+ # ! LaTeX Error: There's no line here to end.
+ text = text.replace(u'\n', u'~\\\\\n').replace(u' ', u'~')
+ if self.no_contractions:
+ text = text.replace('--', u'-{-}')
+ text = text.replace("''", u"'{'}")
+ return text
+
+ def encode_uri(self, text):
+ # in \href, the tilde is allowed and must be represented literally
+ return self.encode(text).replace('\\textasciitilde{}', '~')
+
+ def visit_Text(self, node):
+ text = self.encode(node.astext())
+ if not self.no_contractions:
+ text = educate_quotes_latex(text)
+ self.body.append(text)
+ def depart_Text(self, node):
+ pass
+
+ def visit_comment(self, node):
+ raise nodes.SkipNode
+
+ def visit_meta(self, node):
+ # only valid for HTML
+ raise nodes.SkipNode
+
+ def visit_system_message(self, node):
+ pass
+ def depart_system_message(self, node):
+ self.body.append('\n')
+
+ def visit_math(self, node):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html',
+ (self.curfilestack[-1], node.line))
+ raise nodes.SkipNode
+
+ visit_math_block = visit_math
+
+ def unknown_visit(self, node):
+ raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py
new file mode 100644
index 0000000..4b51588
--- /dev/null
+++ b/sphinx/writers/manpage.py
@@ -0,0 +1,354 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.writers.manpage
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Manual page writer, extended for Sphinx custom nodes.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+try:
+ from docutils.writers.manpage import MACRO_DEF, Writer, \
+ Translator as BaseTranslator
+ has_manpage_writer = True
+except ImportError:
+ # define the classes in any case, sphinx.application needs it
+ Writer = BaseTranslator = object
+ has_manpage_writer = False
+
+from sphinx import addnodes
+from sphinx.locale import admonitionlabels, _
+from sphinx.util.osutil import ustrftime
+from sphinx.util.compat import docutils_version
+
+
+class ManualPageWriter(Writer):
+ def __init__(self, builder):
+ Writer.__init__(self)
+ self.builder = builder
+
+ def translate(self):
+ visitor = ManualPageTranslator(self.builder, self.document)
+ self.visitor = visitor
+ self.document.walkabout(visitor)
+ self.output = visitor.astext()
+
+
+class ManualPageTranslator(BaseTranslator):
+ """
+ Custom translator.
+ """
+
+ def __init__(self, builder, *args, **kwds):
+ BaseTranslator.__init__(self, *args, **kwds)
+ self.builder = builder
+
+ self.in_productionlist = 0
+
+ # first title is the manpage title
+ self.section_level = -1
+
+ # docinfo set by man_pages config value
+ self._docinfo['title'] = self.document.settings.title
+ self._docinfo['subtitle'] = self.document.settings.subtitle
+ if self.document.settings.authors:
+ # don't set it if no author given
+ self._docinfo['author'] = self.document.settings.authors
+ self._docinfo['manual_section'] = self.document.settings.section
+
+ # docinfo set by other config values
+ self._docinfo['title_upper'] = self._docinfo['title'].upper()
+ if builder.config.today:
+ self._docinfo['date'] = builder.config.today
+ else:
+ self._docinfo['date'] = ustrftime(builder.config.today_fmt
+ or _('%B %d, %Y'))
+ self._docinfo['copyright'] = builder.config.copyright
+ self._docinfo['version'] = builder.config.version
+ self._docinfo['manual_group'] = builder.config.project
+
+ # In docutils < 0.11 self.append_header() was never called
+ if docutils_version < (0, 11):
+ self.body.append(MACRO_DEF)
+
+ # Overwrite admonition label translations with our own
+ for label, translation in admonitionlabels.items():
+ self.language.labels[label] = self.deunicode(translation)
+
+
+ # overwritten -- added quotes around all .TH arguments
+ def header(self):
+ tmpl = (".TH \"%(title_upper)s\" \"%(manual_section)s\""
+ " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n"
+ ".SH NAME\n"
+ "%(title)s \- %(subtitle)s\n")
+ return tmpl % self._docinfo
+
+ def visit_start_of_file(self, node):
+ pass
+ def depart_start_of_file(self, node):
+ pass
+
+ def visit_desc(self, node):
+ self.visit_definition_list(node)
+ def depart_desc(self, node):
+ self.depart_definition_list(node)
+
+ def visit_desc_signature(self, node):
+ self.visit_definition_list_item(node)
+ self.visit_term(node)
+ def depart_desc_signature(self, node):
+ self.depart_term(node)
+
+ def visit_desc_addname(self, node):
+ pass
+ def depart_desc_addname(self, node):
+ pass
+
+ def visit_desc_type(self, node):
+ pass
+ def depart_desc_type(self, node):
+ pass
+
+ def visit_desc_returns(self, node):
+ self.body.append(' -> ')
+ def depart_desc_returns(self, node):
+ pass
+
+ def visit_desc_name(self, node):
+ pass
+ def depart_desc_name(self, node):
+ pass
+
+ def visit_desc_parameterlist(self, node):
+ self.body.append('(')
+ self.first_param = 1
+ def depart_desc_parameterlist(self, node):
+ self.body.append(')')
+
+ def visit_desc_parameter(self, node):
+ if not self.first_param:
+ self.body.append(', ')
+ else:
+ self.first_param = 0
+ def depart_desc_parameter(self, node):
+ pass
+
+ def visit_desc_optional(self, node):
+ self.body.append('[')
+ def depart_desc_optional(self, node):
+ self.body.append(']')
+
+ def visit_desc_annotation(self, node):
+ pass
+ def depart_desc_annotation(self, node):
+ pass
+
+ def visit_desc_content(self, node):
+ self.visit_definition(node)
+ def depart_desc_content(self, node):
+ self.depart_definition(node)
+
+ def visit_versionmodified(self, node):
+ self.visit_paragraph(node)
+ def depart_versionmodified(self, node):
+ self.depart_paragraph(node)
+
+ def visit_termsep(self, node):
+ self.body.append(', ')
+ raise nodes.SkipNode
+
+ # overwritten -- we don't want source comments to show up
+ def visit_comment(self, node):
+ raise nodes.SkipNode
+
+ # overwritten -- added ensure_eol()
+ def visit_footnote(self, node):
+ self.ensure_eol()
+ BaseTranslator.visit_footnote(self, node)
+
+ # overwritten -- handle footnotes rubric
+ def visit_rubric(self, node):
+ self.ensure_eol()
+ if len(node.children) == 1:
+ rubtitle = node.children[0].astext()
+ if rubtitle in ('Footnotes', _('Footnotes')):
+ self.body.append('.SH ' + self.deunicode(rubtitle).upper() +
+ '\n')
+ raise nodes.SkipNode
+ else:
+ self.body.append('.sp\n')
+ def depart_rubric(self, node):
+ pass
+
+ def visit_seealso(self, node):
+ self.visit_admonition(node, 'seealso')
+ def depart_seealso(self, node):
+ self.depart_admonition(node)
+
+ def visit_productionlist(self, node):
+ self.ensure_eol()
+ names = []
+ self.in_productionlist += 1
+ self.body.append('.sp\n.nf\n')
+ for production in node:
+ names.append(production['tokenname'])
+ maxlen = max(len(name) for name in names)
+ lastname = None
+ for production in node:
+ if production['tokenname']:
+ lastname = production['tokenname'].ljust(maxlen)
+ self.body.append(self.defs['strong'][0])
+ self.body.append(self.deunicode(lastname))
+ self.body.append(self.defs['strong'][1])
+ self.body.append(' ::= ')
+ elif lastname is not None:
+ self.body.append('%s ' % (' '*len(lastname)))
+ production.walkabout(self)
+ self.body.append('\n')
+ self.body.append('\n.fi\n')
+ self.in_productionlist -= 1
+ raise nodes.SkipNode
+
+ def visit_production(self, node):
+ pass
+ def depart_production(self, node):
+ pass
+
+ # overwritten -- don't emit a warning for images
+ def visit_image(self, node):
+ if 'alt' in node.attributes:
+ self.body.append(_('[image: %s]') % node['alt'] + '\n')
+ self.body.append(_('[image]') + '\n')
+ raise nodes.SkipNode
+
+ # overwritten -- don't visit inner marked up nodes
+ def visit_reference(self, node):
+ self.body.append(self.defs['reference'][0])
+ self.visit_Text(node) # avoid repeating escaping code... fine since
+ # visit_Text calls astext() and only works
+ # on that afterwards
+ self.body.append(self.defs['reference'][1])
+
+ uri = node.get('refuri', '')
+ if uri.startswith('mailto:') or uri.startswith('http:') or \
+ uri.startswith('https:') or uri.startswith('ftp:'):
+ # if configured, put the URL after the link
+ if self.builder.config.man_show_urls and \
+ node.astext() != uri:
+ if uri.startswith('mailto:'):
+ uri = uri[7:]
+ self.body.extend([
+ ' <',
+ self.defs['strong'][0], uri, self.defs['strong'][1],
+ '>'])
+ raise nodes.SkipNode
+
+ def visit_centered(self, node):
+ self.ensure_eol()
+ self.body.append('.sp\n.ce\n')
+ def depart_centered(self, node):
+ self.body.append('\n.ce 0\n')
+
+ def visit_compact_paragraph(self, node):
+ pass
+ def depart_compact_paragraph(self, node):
+ pass
+
+ def visit_highlightlang(self, node):
+ pass
+ def depart_highlightlang(self, node):
+ pass
+
+ def visit_download_reference(self, node):
+ pass
+ def depart_download_reference(self, node):
+ pass
+
+ def visit_toctree(self, node):
+ raise nodes.SkipNode
+
+ def visit_index(self, node):
+ raise nodes.SkipNode
+
+ def visit_tabular_col_spec(self, node):
+ raise nodes.SkipNode
+
+ def visit_glossary(self, node):
+ pass
+ def depart_glossary(self, node):
+ pass
+
+ def visit_acks(self, node):
+ self.ensure_eol()
+ self.body.append(', '.join(n.astext()
+ for n in node.children[0].children) + '.')
+ self.body.append('\n')
+ raise nodes.SkipNode
+
+ def visit_hlist(self, node):
+ self.visit_bullet_list(node)
+ def depart_hlist(self, node):
+ self.depart_bullet_list(node)
+
+ def visit_hlistcol(self, node):
+ pass
+ def depart_hlistcol(self, node):
+ pass
+
+ def visit_literal_emphasis(self, node):
+ return self.visit_emphasis(node)
+ def depart_literal_emphasis(self, node):
+ return self.depart_emphasis(node)
+
+ def visit_abbreviation(self, node):
+ pass
+ def depart_abbreviation(self, node):
+ pass
+
+ # overwritten: handle section titles better than in 0.6 release
+ def visit_title(self, node):
+ if isinstance(node.parent, addnodes.seealso):
+ self.body.append('.IP "')
+ return
+ elif isinstance(node.parent, nodes.section):
+ if self.section_level == 0:
+ # skip the document title
+ raise nodes.SkipNode
+ elif self.section_level == 1:
+ self.body.append('.SH %s\n' %
+ self.deunicode(node.astext().upper()))
+ raise nodes.SkipNode
+ return BaseTranslator.visit_title(self, node)
+ def depart_title(self, node):
+ if isinstance(node.parent, addnodes.seealso):
+ self.body.append('"\n')
+ return
+ return BaseTranslator.depart_title(self, node)
+
+ def visit_raw(self, node):
+ if 'manpage' in node.get('format', '').split():
+ self.body.append(node.astext())
+ raise nodes.SkipNode
+
+ def visit_meta(self, node):
+ raise nodes.SkipNode
+
+ def visit_inline(self, node):
+ pass
+ def depart_inline(self, node):
+ pass
+
+ def visit_math(self, node):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html')
+ raise nodes.SkipNode
+
+ visit_math_block = visit_math
+
+ def unknown_visit(self, node):
+ raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py
new file mode 100644
index 0000000..fcfce03
--- /dev/null
+++ b/sphinx/writers/texinfo.py
@@ -0,0 +1,1403 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.writers.texinfo
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Custom docutils writer for Texinfo.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+import string
+import textwrap
+from os import path
+
+from docutils import nodes, writers
+
+from sphinx import addnodes, __version__
+from sphinx.locale import admonitionlabels, _
+from sphinx.util import ustrftime
+from sphinx.writers.latex import collected_footnote
+
+
+COPYING = """\
+ at quotation
+%(project)s %(release)s, %(date)s
+
+%(author)s
+
+Copyright @copyright{} %(copyright)s
+ at end quotation
+"""
+
+TEMPLATE = """\
+\\input texinfo @c -*-texinfo-*-
+ at c %%**start of header
+ at setfilename %(filename)s
+ at documentencoding UTF-8
+ at ifinfo
+@*Generated by Sphinx """ + __version__ + """.@*
+ at end ifinfo
+ at settitle %(title)s
+ at defindex ge
+ at paragraphindent %(paragraphindent)s
+ at exampleindent %(exampleindent)s
+ at finalout
+%(direntry)s
+ at definfoenclose strong,`,'
+ at definfoenclose emph,`,'
+ at c %%**end of header
+
+ at copying
+%(copying)s
+ at end copying
+
+ at titlepage
+ at title %(title)s
+ at insertcopying
+ at end titlepage
+ at contents
+
+ at c %%** start of user preamble
+%(preamble)s
+ at c %%** end of user preamble
+
+ at ifnottex
+ at node Top
+ at top %(title)s
+ at insertcopying
+ at end ifnottex
+
+ at c %%**start of body
+%(body)s
+ at c %%**end of body
+ at bye
+"""
+
+
+def find_subsections(section):
+ """Return a list of subsections for the given ``section``."""
+ result = []
+ for child in section.children:
+ if isinstance(child, nodes.section):
+ result.append(child)
+ continue
+ result.extend(find_subsections(child))
+ return result
+
+
+def smart_capwords(s, sep=None):
+ """Like string.capwords() but does not capitalize words that already
+ contain a capital letter."""
+ words = s.split(sep)
+ for i, word in enumerate(words):
+ if all(x.islower() for x in word):
+ words[i] = word.capitalize()
+ return (sep or ' ').join(words)
+
+
+class TexinfoWriter(writers.Writer):
+ """Texinfo writer for generating Texinfo documents."""
+ supported = ('texinfo', 'texi')
+
+ settings_spec = (
+ 'Texinfo Specific Options', None, (
+ ("Name of the Info file", ['--texinfo-filename'], {'default': ''}),
+ ('Dir entry', ['--texinfo-dir-entry'], {'default': ''}),
+ ('Description', ['--texinfo-dir-description'], {'default': ''}),
+ ('Category', ['--texinfo-dir-category'], {'default':
+ 'Miscellaneous'})))
+
+ settings_defaults = {}
+
+ output = None
+
+ visitor_attributes = ('output', 'fragment')
+
+ def __init__(self, builder):
+ writers.Writer.__init__(self)
+ self.builder = builder
+
+ def translate(self):
+ self.visitor = visitor = TexinfoTranslator(self.document, self.builder)
+ self.document.walkabout(visitor)
+ visitor.finish()
+ for attr in self.visitor_attributes:
+ setattr(self, attr, getattr(visitor, attr))
+
+
+class TexinfoTranslator(nodes.NodeVisitor):
+
+ ignore_missing_images = False
+
+ default_elements = {
+ 'author': '',
+ 'body': '',
+ 'copying': '',
+ 'date': '',
+ 'direntry': '',
+ 'exampleindent': 4,
+ 'filename': '',
+ 'paragraphindent': 0,
+ 'preamble': '',
+ 'project': '',
+ 'release': '',
+ 'title': '',
+ }
+
+ def __init__(self, document, builder):
+ nodes.NodeVisitor.__init__(self, document)
+ self.builder = builder
+ self.init_settings()
+
+ self.written_ids = set() # node names and anchors in output
+ self.referenced_ids = set() # node names and anchors that should
+ # be in output
+ self.indices = [] # (node name, content)
+ self.short_ids = {} # anchors --> short ids
+ self.node_names = {} # node name --> node's name to display
+ self.node_menus = {} # node name --> node's menu entries
+ self.rellinks = {} # node name --> (next, previous, up)
+
+ self.collect_indices()
+ self.collect_node_names()
+ self.collect_node_menus()
+ self.collect_rellinks()
+
+ self.body = []
+ self.context = []
+ self.previous_section = None
+ self.section_level = 0
+ self.seen_title = False
+ self.next_section_ids = set()
+ self.escape_newlines = 0
+ self.escape_hyphens = 0
+ self.curfilestack = []
+ self.footnotestack = []
+ self.in_footnote = 0
+ self.handled_abbrs = set()
+
+ def finish(self):
+ if self.previous_section is None:
+ self.add_menu('Top')
+ for index in self.indices:
+ name, content = index
+ pointers = tuple([name] + self.rellinks[name])
+ self.body.append('\n at node %s,%s,%s,%s\n' % pointers)
+ self.body.append('@unnumbered %s\n\n%s\n' % (name, content))
+
+ while self.referenced_ids:
+ # handle xrefs with missing anchors
+ r = self.referenced_ids.pop()
+ if r not in self.written_ids:
+ self.body.append('@anchor{%s}@w{%s}\n' % (r, ' ' * 30))
+ self.ensure_eol()
+ self.fragment = ''.join(self.body)
+ self.elements['body'] = self.fragment
+ self.output = TEMPLATE % self.elements
+
+ ## Helper routines
+
+ def init_settings(self):
+ settings = self.settings = self.document.settings
+ elements = self.elements = self.default_elements.copy()
+ elements.update({
+ # if empty, the title is set to the first section title
+ 'title': settings.title,
+ 'author': settings.author,
+ # if empty, use basename of input file
+ 'filename': settings.texinfo_filename,
+ 'release': self.escape(self.builder.config.release),
+ 'project': self.escape(self.builder.config.project),
+ 'copyright': self.escape(self.builder.config.copyright),
+ 'date': self.escape(self.builder.config.today or
+ ustrftime(self.builder.config.today_fmt
+ or _('%B %d, %Y')))
+ })
+ # title
+ title = elements['title']
+ if not title:
+ title = self.document.next_node(nodes.title)
+ title = (title and title.astext()) or '<untitled>'
+ elements['title'] = self.escape_id(title) or '<untitled>'
+ # filename
+ if not elements['filename']:
+ elements['filename'] = self.document.get('source') or 'untitled'
+ if elements['filename'][-4:] in ('.txt', '.rst'):
+ elements['filename'] = elements['filename'][:-4]
+ elements['filename'] += '.info'
+ # direntry
+ if settings.texinfo_dir_entry:
+ entry = self.format_menu_entry(
+ self.escape_menu(settings.texinfo_dir_entry),
+ '(%s)' % elements['filename'],
+ self.escape_arg(settings.texinfo_dir_description))
+ elements['direntry'] = ('@dircategory %s\n'
+ '@direntry\n'
+ '%s'
+ '@end direntry\n') % (
+ self.escape_id(settings.texinfo_dir_category), entry)
+ elements['copying'] = COPYING % elements
+ # allow the user to override them all
+ elements.update(settings.texinfo_elements)
+
+ def collect_node_names(self):
+ """Generates a unique id for each section.
+
+ Assigns the attribute ``node_name`` to each section."""
+
+ def add_node_name(name):
+ node_id = self.escape_id(name)
+ nth, suffix = 1, ''
+ while node_id + suffix in self.written_ids or \
+ node_id + suffix in self.node_names:
+ nth += 1
+ suffix = '<%s>' % nth
+ node_id += suffix
+ self.written_ids.add(node_id)
+ self.node_names[node_id] = name
+ return node_id
+
+ # must have a "Top" node
+ self.document['node_name'] = 'Top'
+ add_node_name('Top')
+ add_node_name('top')
+ # each index is a node
+ self.indices = [(add_node_name(name), content)
+ for name, content in self.indices]
+ # each section is also a node
+ for section in self.document.traverse(nodes.section):
+ title = section.next_node(nodes.Titular)
+ name = (title and title.astext()) or '<untitled>'
+ section['node_name'] = add_node_name(name)
+
+ def collect_node_menus(self):
+ """Collect the menu entries for each "node" section."""
+ node_menus = self.node_menus
+ for node in ([self.document] +
+ self.document.traverse(nodes.section)):
+ assert 'node_name' in node and node['node_name']
+ entries = [s['node_name'] for s in find_subsections(node)]
+ node_menus[node['node_name']] = entries
+ # try to find a suitable "Top" node
+ title = self.document.next_node(nodes.title)
+ top = (title and title.parent) or self.document
+ if not isinstance(top, (nodes.document, nodes.section)):
+ top = self.document
+ if top is not self.document:
+ entries = node_menus[top['node_name']]
+ entries += node_menus['Top'][1:]
+ node_menus['Top'] = entries
+ del node_menus[top['node_name']]
+ top['node_name'] = 'Top'
+ # handle the indices
+ for name, content in self.indices:
+ node_menus[name] = ()
+ node_menus['Top'].append(name)
+
+ def collect_rellinks(self):
+ """Collect the relative links (next, previous, up) for each "node"."""
+ rellinks = self.rellinks
+ node_menus = self.node_menus
+ for id, entries in node_menus.items():
+ rellinks[id] = ['', '', '']
+ # up's
+ for id, entries in node_menus.items():
+ for e in entries:
+ rellinks[e][2] = id
+ # next's and prev's
+ for id, entries in node_menus.items():
+ for i, id in enumerate(entries):
+ # First child's prev is empty
+ if i != 0:
+ rellinks[id][1] = entries[i-1]
+ # Last child's next is empty
+ if i != len(entries) - 1:
+ rellinks[id][0] = entries[i+1]
+ # top's next is its first child
+ try:
+ first = node_menus['Top'][0]
+ except IndexError:
+ pass
+ else:
+ rellinks['Top'][0] = first
+ rellinks[first][1] = 'Top'
+
+ ## Escaping
+ # Which characters to escape depends on the context. In some cases,
+ # namely menus and node names, it's not possible to escape certain
+ # characters.
+
+ def escape(self, s):
+ """Return a string with Texinfo command characters escaped."""
+ s = s.replace('@', '@@')
+ s = s.replace('{', '@{')
+ s = s.replace('}', '@}')
+ # prevent `` and '' quote conversion
+ s = s.replace('``', "`@w{`}")
+ s = s.replace("''", "'@w{'}")
+ return s
+
+ def escape_arg(self, s):
+ """Return an escaped string suitable for use as an argument
+ to a Texinfo command."""
+ s = self.escape(s)
+ # commas are the argument delimeters
+ s = s.replace(',', '@comma{}')
+ # normalize white space
+ s = ' '.join(s.split()).strip()
+ return s
+
+ def escape_id(self, s):
+ """Return an escaped string suitable for node names and anchors."""
+ bad_chars = ',:.()'
+ for bc in bad_chars:
+ s = s.replace(bc, ' ')
+ s = ' '.join(s.split()).strip()
+ return self.escape(s)
+
+ def escape_menu(self, s):
+ """Return an escaped string suitable for menu entries."""
+ s = self.escape_arg(s)
+ s = s.replace(':', ';')
+ s = ' '.join(s.split()).strip()
+ return s
+
+ def ensure_eol(self):
+ """Ensure the last line in body is terminated by new line."""
+ if self.body and self.body[-1][-1:] != '\n':
+ self.body.append('\n')
+
+ def format_menu_entry(self, name, node_name, desc):
+ if name == node_name:
+ s = '* %s:: ' % (name,)
+ else:
+ s = '* %s: %s. ' % (name, node_name)
+ offset = max((24, (len(name) + 4) % 78))
+ wdesc = '\n'.join(' ' * offset + l for l in
+ textwrap.wrap(desc, width=78-offset))
+ return s + wdesc.strip() + '\n'
+
+ def add_menu_entries(self, entries, reg=re.compile(r'\s+---?\s+')):
+ for entry in entries:
+ name = self.node_names[entry]
+ # special formatting for entries that are divided by an em-dash
+ try:
+ parts = reg.split(name, 1)
+ except TypeError:
+ # could be a gettext proxy
+ parts = [name]
+ if len(parts) == 2:
+ name, desc = parts
+ else:
+ desc = ''
+ name = self.escape_menu(name)
+ desc = self.escape(desc)
+ self.body.append(self.format_menu_entry(name, entry, desc))
+
+ def add_menu(self, node_name):
+ entries = self.node_menus[node_name]
+ if not entries:
+ return
+ self.body.append('\n at menu\n')
+ self.add_menu_entries(entries)
+ if (node_name != 'Top' or
+ not self.node_menus[entries[0]] or
+ self.builder.config.texinfo_no_detailmenu):
+ self.body.append('\n at end menu\n')
+ return
+
+ def _add_detailed_menu(name):
+ entries = self.node_menus[name]
+ if not entries:
+ return
+ self.body.append('\n%s\n\n' % (self.escape(self.node_names[name],)))
+ self.add_menu_entries(entries)
+ for subentry in entries:
+ _add_detailed_menu(subentry)
+
+ self.body.append('\n at detailmenu\n'
+ ' --- The Detailed Node Listing ---\n')
+ for entry in entries:
+ _add_detailed_menu(entry)
+ self.body.append('\n at end detailmenu\n'
+ '@end menu\n')
+
+ def tex_image_length(self, width_str):
+ match = re.match('(\d*\.?\d*)\s*(\S*)', width_str)
+ if not match:
+ # fallback
+ return width_str
+ res = width_str
+ amount, unit = match.groups()[:2]
+ if not unit or unit == "px":
+ # pixels: let TeX alone
+ return ''
+ elif unit == "%":
+ # a4paper: textwidth=418.25368pt
+ res = "%d.0pt" % (float(amount) * 4.1825368)
+ return res
+
+ def collect_indices(self):
+ def generate(content, collapsed):
+ ret = ['\n at menu\n']
+ for letter, entries in content:
+ for entry in entries:
+ if not entry[3]:
+ continue
+ name = self.escape_menu(entry[0])
+ sid = self.get_short_id('%s:%s' % (entry[2], entry[3]))
+ desc = self.escape_arg(entry[6])
+ me = self.format_menu_entry(name, sid, desc)
+ ret.append(me)
+ ret.append('@end menu\n')
+ return ''.join(ret)
+
+ indices_config = self.builder.config.texinfo_domain_indices
+ if indices_config:
+ for domain in self.builder.env.domains.itervalues():
+ for indexcls in domain.indices:
+ indexname = '%s-%s' % (domain.name, indexcls.name)
+ if isinstance(indices_config, list):
+ if indexname not in indices_config:
+ continue
+ content, collapsed = indexcls(domain).generate(
+ self.builder.docnames)
+ if not content:
+ continue
+ self.indices.append((indexcls.localname,
+ generate(content, collapsed)))
+ # only add the main Index if it's not empty
+ for docname in self.builder.docnames:
+ if self.builder.env.indexentries[docname]:
+ self.indices.append((_('Index'), '\n at printindex ge\n'))
+ break
+
+ # this is copied from the latex writer
+ # TODO: move this to sphinx.util
+
+ def collect_footnotes(self, node):
+ fnotes = {}
+ def footnotes_under(n):
+ if isinstance(n, nodes.footnote):
+ yield n
+ else:
+ for c in n.children:
+ if isinstance(c, addnodes.start_of_file):
+ continue
+ for k in footnotes_under(c):
+ yield k
+ for fn in footnotes_under(node):
+ num = fn.children[0].astext().strip()
+ fnotes[num] = [collected_footnote(*fn.children), False]
+ return fnotes
+
+ ## xref handling
+
+ def get_short_id(self, id):
+ """Return a shorter 'id' associated with ``id``."""
+ # Shorter ids improve paragraph filling in places
+ # that the id is hidden by Emacs.
+ try:
+ sid = self.short_ids[id]
+ except KeyError:
+ sid = hex(len(self.short_ids))[2:]
+ self.short_ids[id] = sid
+ return sid
+
+ def add_anchor(self, id, node):
+ if id.startswith('index-'):
+ return
+ id = self.curfilestack[-1] + ':' + id
+ eid = self.escape_id(id)
+ sid = self.get_short_id(id)
+ for id in (eid, sid):
+ if id not in self.written_ids:
+ self.body.append('@anchor{%s}' % id)
+ self.written_ids.add(id)
+
+ def add_xref(self, id, name, node):
+ name = self.escape_menu(name)
+ sid = self.get_short_id(id)
+ self.body.append('@ref{%s,,%s}' % (sid, name))
+ self.referenced_ids.add(sid)
+ self.referenced_ids.add(self.escape_id(id))
+
+ ## Visiting
+
+ def visit_document(self, node):
+ self.footnotestack.append(self.collect_footnotes(node))
+ self.curfilestack.append(node.get('docname', ''))
+ if 'docname' in node:
+ self.add_anchor(':doc', node)
+ def depart_document(self, node):
+ self.footnotestack.pop()
+ self.curfilestack.pop()
+
+ def visit_Text(self, node):
+ s = self.escape(node.astext())
+ if self.escape_newlines:
+ s = s.replace('\n', ' ')
+ if self.escape_hyphens:
+ # prevent "--" and "---" conversion
+ s = s.replace('-', '@w{-}')
+ self.body.append(s)
+ def depart_Text(self, node):
+ pass
+
+ def visit_section(self, node):
+ self.next_section_ids.update(node.get('ids', []))
+ if not self.seen_title:
+ return
+ if self.previous_section:
+ self.add_menu(self.previous_section['node_name'])
+ else:
+ self.add_menu('Top')
+
+ node_name = node['node_name']
+ pointers = tuple([node_name] + self.rellinks[node_name])
+ self.body.append('\n at node %s,%s,%s,%s\n' % pointers)
+ for id in self.next_section_ids:
+ self.add_anchor(id, node)
+
+ self.next_section_ids.clear()
+ self.previous_section = node
+ self.section_level += 1
+
+ def depart_section(self, node):
+ self.section_level -= 1
+
+ headings = (
+ '@unnumbered',
+ '@chapter',
+ '@section',
+ '@subsection',
+ '@subsubsection',
+ )
+
+ rubrics = (
+ '@heading',
+ '@subheading',
+ '@subsubheading',
+ )
+
+ def visit_title(self, node):
+ if not self.seen_title:
+ self.seen_title = 1
+ raise nodes.SkipNode
+ parent = node.parent
+ if isinstance(parent, nodes.table):
+ return
+ if isinstance(parent, (nodes.Admonition, nodes.sidebar, nodes.topic)):
+ raise nodes.SkipNode
+ elif not isinstance(parent, nodes.section):
+ self.builder.warn(
+ 'encountered title node not in section, topic, table, '
+ 'admonition or sidebar', (self.curfilestack[-1], node.line))
+ self.visit_rubric(node)
+ else:
+ try:
+ heading = self.headings[self.section_level]
+ except IndexError:
+ heading = self.headings[-1]
+ self.body.append('\n%s ' % heading)
+
+ def depart_title(self, node):
+ self.body.append('\n\n')
+
+ def visit_rubric(self, node):
+ if len(node.children) == 1 and node.children[0].astext() in \
+ ('Footnotes', _('Footnotes')):
+ raise nodes.SkipNode
+ try:
+ rubric = self.rubrics[self.section_level]
+ except IndexError:
+ rubric = self.rubrics[-1]
+ self.body.append('\n%s ' % rubric)
+ def depart_rubric(self, node):
+ self.body.append('\n\n')
+
+ def visit_subtitle(self, node):
+ self.body.append('\n\n at noindent\n')
+ def depart_subtitle(self, node):
+ self.body.append('\n\n')
+
+ ## References
+
+ def visit_target(self, node):
+ # postpone the labels until after the sectioning command
+ parindex = node.parent.index(node)
+ try:
+ try:
+ next = node.parent[parindex+1]
+ except IndexError:
+ # last node in parent, look at next after parent
+ # (for section of equal level)
+ next = node.parent.parent[node.parent.parent.index(node.parent)]
+ if isinstance(next, nodes.section):
+ if node.get('refid'):
+ self.next_section_ids.add(node['refid'])
+ self.next_section_ids.update(node['ids'])
+ return
+ except IndexError:
+ pass
+ if 'refuri' in node:
+ return
+ if node.get('refid'):
+ self.add_anchor(node['refid'], node)
+ for id in node['ids']:
+ self.add_anchor(id, node)
+ def depart_target(self, node):
+ pass
+
+ def visit_reference(self, node):
+ # an xref's target is displayed in Info so we ignore a few
+ # cases for the sake of appearance
+ if isinstance(node.parent, (nodes.title, addnodes.desc_type,)):
+ return
+ if isinstance(node[0], nodes.image):
+ return
+ name = node.get('name', node.astext()).strip()
+ uri = node.get('refuri', '')
+ if not uri and node.get('refid'):
+ uri = '%' + self.curfilestack[-1] + '#' + node['refid']
+ if not uri:
+ return
+ if uri.startswith('mailto:'):
+ uri = self.escape_arg(uri[7:])
+ name = self.escape_arg(name)
+ if not name or name == uri:
+ self.body.append('@email{%s}' % uri)
+ else:
+ self.body.append('@email{%s,%s}' % (uri, name))
+ elif uri.startswith('#'):
+ # references to labels in the same document
+ id = self.curfilestack[-1] + ':' + uri[1:]
+ self.add_xref(id, name, node)
+ elif uri.startswith('%'):
+ # references to documents or labels inside documents
+ hashindex = uri.find('#')
+ if hashindex == -1:
+ # reference to the document
+ id = uri[1:] + '::doc'
+ else:
+ # reference to a label
+ id = uri[1:].replace('#', ':')
+ self.add_xref(id, name, node)
+ elif uri.startswith('info:'):
+ # references to an external Info file
+ uri = uri[5:].replace('_', ' ')
+ uri = self.escape_arg(uri)
+ id = 'Top'
+ if '#' in uri:
+ uri, id = uri.split('#', 1)
+ id = self.escape_id(id)
+ name = self.escape_menu(name)
+ if name == id:
+ self.body.append('@ref{%s,,,%s}' % (id, uri))
+ else:
+ self.body.append('@ref{%s,,%s,%s}' % (id, name, uri))
+ else:
+ uri = self.escape_arg(uri)
+ name = self.escape_arg(name)
+ show_urls = self.builder.config.texinfo_show_urls
+ if self.in_footnote:
+ show_urls = 'inline'
+ if not name or uri == name:
+ self.body.append('@indicateurl{%s}' % uri)
+ elif show_urls == 'inline':
+ self.body.append('@uref{%s,%s}' % (uri, name))
+ elif show_urls == 'no':
+ self.body.append('@uref{%s,,%s}' % (uri, name))
+ else:
+ self.body.append('%s at footnote{%s}' % (name, uri))
+ raise nodes.SkipNode
+
+ def depart_reference(self, node):
+ pass
+
+ def visit_title_reference(self, node):
+ text = node.astext()
+ self.body.append('@cite{%s}' % self.escape_arg(text))
+ raise nodes.SkipNode
+
+ ## Blocks
+
+ def visit_paragraph(self, node):
+ self.body.append('\n')
+ def depart_paragraph(self, node):
+ self.body.append('\n')
+
+ def visit_block_quote(self, node):
+ self.body.append('\n at quotation\n')
+ def depart_block_quote(self, node):
+ self.ensure_eol()
+ self.body.append('@end quotation\n')
+
+ def visit_literal_block(self, node):
+ self.body.append('\n at example\n')
+ def depart_literal_block(self, node):
+ self.ensure_eol()
+ self.body.append('@end example\n')
+
+ visit_doctest_block = visit_literal_block
+ depart_doctest_block = depart_literal_block
+
+ def visit_line_block(self, node):
+ if not isinstance(node.parent, nodes.line_block):
+ self.body.append('\n\n')
+ self.body.append('@display\n')
+ def depart_line_block(self, node):
+ self.body.append('@end display\n')
+ if not isinstance(node.parent, nodes.line_block):
+ self.body.append('\n\n')
+
+ def visit_line(self, node):
+ self.escape_newlines += 1
+ def depart_line(self, node):
+ self.body.append('@w{ }\n')
+ self.escape_newlines -= 1
+
+ ## Inline
+
+ def visit_strong(self, node):
+ self.body.append('@strong{')
+ def depart_strong(self, node):
+ self.body.append('}')
+
+ def visit_emphasis(self, node):
+ self.body.append('@emph{')
+ def depart_emphasis(self, node):
+ self.body.append('}')
+
+ def visit_literal(self, node):
+ self.body.append('@code{')
+ def depart_literal(self, node):
+ self.body.append('}')
+
+ def visit_superscript(self, node):
+ self.body.append('@w{^')
+ def depart_superscript(self, node):
+ self.body.append('}')
+
+ def visit_subscript(self, node):
+ self.body.append('@w{[')
+ def depart_subscript(self, node):
+ self.body.append(']}')
+
+ ## Footnotes
+
+ def visit_footnote(self, node):
+ raise nodes.SkipNode
+
+ def visit_collected_footnote(self, node):
+ self.in_footnote += 1
+ self.body.append('@footnote{')
+ def depart_collected_footnote(self, node):
+ self.body.append('}')
+ self.in_footnote -= 1
+
+ def visit_footnote_reference(self, node):
+ num = node.astext().strip()
+ try:
+ footnode, used = self.footnotestack[-1][num]
+ except (KeyError, IndexError):
+ raise nodes.SkipNode
+ # footnotes are repeated for each reference
+ footnode.walkabout(self)
+ raise nodes.SkipChildren
+
+ def visit_citation(self, node):
+ for id in node.get('ids'):
+ self.add_anchor(id, node)
+ def depart_citation(self, node):
+ pass
+
+ def visit_citation_reference(self, node):
+ self.body.append('@w{[')
+ def depart_citation_reference(self, node):
+ self.body.append(']}')
+
+ ## Lists
+
+ def visit_bullet_list(self, node):
+ bullet = node.get('bullet', '*')
+ self.body.append('\n\n at itemize %s\n' % bullet)
+ def depart_bullet_list(self, node):
+ self.ensure_eol()
+ self.body.append('@end itemize\n')
+
+ def visit_enumerated_list(self, node):
+ # doesn't support Roman numerals
+ enum = node.get('enumtype', 'arabic')
+ starters = {'arabic': '',
+ 'loweralpha': 'a',
+ 'upperalpha': 'A',}
+ start = node.get('start', starters.get(enum, ''))
+ self.body.append('\n\n at enumerate %s\n' % start)
+ def depart_enumerated_list(self, node):
+ self.ensure_eol()
+ self.body.append('@end enumerate\n')
+
+ def visit_list_item(self, node):
+ self.body.append('\n at item ')
+ def depart_list_item(self, node):
+ pass
+
+ ## Option List
+
+ def visit_option_list(self, node):
+ self.body.append('\n\n at table @option\n')
+ def depart_option_list(self, node):
+ self.ensure_eol()
+ self.body.append('@end table\n')
+
+ def visit_option_list_item(self, node):
+ pass
+ def depart_option_list_item(self, node):
+ pass
+
+ def visit_option_group(self, node):
+ self.at_item_x = '@item'
+ def depart_option_group(self, node):
+ pass
+
+ def visit_option(self, node):
+ self.escape_hyphens += 1
+ self.body.append('\n%s ' % self.at_item_x)
+ self.at_item_x = '@itemx'
+ def depart_option(self, node):
+ self.escape_hyphens -= 1
+
+ def visit_option_string(self, node):
+ pass
+ def depart_option_string(self, node):
+ pass
+
+ def visit_option_argument(self, node):
+ self.body.append(node.get('delimiter', ' '))
+ def depart_option_argument(self, node):
+ pass
+
+ def visit_description(self, node):
+ self.body.append('\n')
+ def depart_description(self, node):
+ pass
+
+ ## Definitions
+
+ def visit_definition_list(self, node):
+ self.body.append('\n\n at table @asis\n')
+ def depart_definition_list(self, node):
+ self.ensure_eol()
+ self.body.append('@end table\n')
+
+ def visit_definition_list_item(self, node):
+ self.at_item_x = '@item'
+ def depart_definition_list_item(self, node):
+ pass
+
+ def visit_term(self, node):
+ for id in node.get('ids'):
+ self.add_anchor(id, node)
+ # anchors and indexes need to go in front
+ for n in node[::]:
+ if isinstance(n, (addnodes.index, nodes.target)):
+ n.walkabout(self)
+ node.remove(n)
+ self.body.append('\n%s ' % self.at_item_x)
+ self.at_item_x = '@itemx'
+ def depart_term(self, node):
+ pass
+
+ def visit_termsep(self, node):
+ self.body.append('\n%s ' % self.at_item_x)
+ def depart_termsep(self, node):
+ pass
+
+ def visit_classifier(self, node):
+ self.body.append(' : ')
+ def depart_classifier(self, node):
+ pass
+
+ def visit_definition(self, node):
+ self.body.append('\n')
+ def depart_definition(self, node):
+ pass
+
+ ## Tables
+
+ def visit_table(self, node):
+ self.entry_sep = '@item'
+ def depart_table(self, node):
+ self.body.append('\n at end multitable\n\n')
+
+ def visit_tabular_col_spec(self, node):
+ pass
+ def depart_tabular_col_spec(self, node):
+ pass
+
+ def visit_colspec(self, node):
+ self.colwidths.append(node['colwidth'])
+ if len(self.colwidths) != self.n_cols:
+ return
+ self.body.append('\n\n at multitable ')
+ for i, n in enumerate(self.colwidths):
+ self.body.append('{%s} ' %('x' * (n+2)))
+ def depart_colspec(self, node):
+ pass
+
+ def visit_tgroup(self, node):
+ self.colwidths = []
+ self.n_cols = node['cols']
+ def depart_tgroup(self, node):
+ pass
+
+ def visit_thead(self, node):
+ self.entry_sep = '@headitem'
+ def depart_thead(self, node):
+ pass
+
+ def visit_tbody(self, node):
+ pass
+ def depart_tbody(self, node):
+ pass
+
+ def visit_row(self, node):
+ pass
+ def depart_row(self, node):
+ self.entry_sep = '@item'
+
+ def visit_entry(self, node):
+ self.body.append('\n%s\n' % self.entry_sep)
+ self.entry_sep = '@tab'
+ def depart_entry(self, node):
+ for i in xrange(node.get('morecols', 0)):
+ self.body.append('\n at tab\n')
+
+ ## Field Lists
+
+ def visit_field_list(self, node):
+ pass
+ def depart_field_list(self, node):
+ pass
+
+ def visit_field(self, node):
+ self.body.append('\n')
+ def depart_field(self, node):
+ self.body.append('\n')
+
+ def visit_field_name(self, node):
+ self.ensure_eol()
+ self.body.append('@*')
+ def depart_field_name(self, node):
+ self.body.append(': ')
+
+ def visit_field_body(self, node):
+ pass
+ def depart_field_body(self, node):
+ pass
+
+ ## Admonitions
+
+ def visit_admonition(self, node, name=''):
+ if not name:
+ name = self.escape(node[0].astext())
+ self.body.append(u'\n at cartouche\n at quotation %s ' % name)
+ def depart_admonition(self, node):
+ self.ensure_eol()
+ self.body.append('@end quotation\n'
+ '@end cartouche\n')
+
+ def _make_visit_admonition(name):
+ def visit(self, node):
+ self.visit_admonition(node, admonitionlabels[name])
+ return visit
+
+ visit_attention = _make_visit_admonition('attention')
+ depart_attention = depart_admonition
+ visit_caution = _make_visit_admonition('caution')
+ depart_caution = depart_admonition
+ visit_danger = _make_visit_admonition('danger')
+ depart_danger = depart_admonition
+ visit_error = _make_visit_admonition('error')
+ depart_error = depart_admonition
+ visit_hint = _make_visit_admonition('hint')
+ depart_hint = depart_admonition
+ visit_important = _make_visit_admonition('important')
+ depart_important = depart_admonition
+ visit_note = _make_visit_admonition('note')
+ depart_note = depart_admonition
+ visit_tip = _make_visit_admonition('tip')
+ depart_tip = depart_admonition
+ visit_warning = _make_visit_admonition('warning')
+ depart_warning = depart_admonition
+
+ ## Misc
+
+ def visit_docinfo(self, node):
+ raise nodes.SkipNode
+
+ def visit_generated(self, node):
+ raise nodes.SkipNode
+
+ def visit_header(self, node):
+ raise nodes.SkipNode
+
+ def visit_footer(self, node):
+ raise nodes.SkipNode
+
+ def visit_container(self, node):
+ pass
+ def depart_container(self, node):
+ pass
+
+ def visit_decoration(self, node):
+ pass
+ def depart_decoration(self, node):
+ pass
+
+ def visit_topic(self, node):
+ # ignore TOC's since we have to have a "menu" anyway
+ if 'contents' in node.get('classes', []):
+ raise nodes.SkipNode
+ title = node[0]
+ self.visit_rubric(title)
+ self.body.append('%s\n' % self.escape(title.astext()))
+ def depart_topic(self, node):
+ pass
+
+ def visit_transition(self, node):
+ self.body.append('\n\n%s\n\n' % ('_' * 66))
+ def depart_transition(self, node):
+ pass
+
+ def visit_attribution(self, node):
+ self.body.append('\n\n at center --- ')
+ def depart_attribution(self, node):
+ self.body.append('\n\n')
+
+ def visit_raw(self, node):
+ format = node.get('format', '').split()
+ if 'texinfo' in format or 'texi' in format:
+ self.body.append(node.astext())
+ raise nodes.SkipNode
+
+ def visit_figure(self, node):
+ self.body.append('\n\n at float Figure\n')
+ def depart_figure(self, node):
+ self.body.append('\n at end float\n\n')
+
+ def visit_caption(self, node):
+ if not isinstance(node.parent, nodes.figure):
+ self.builder.warn('caption not inside a figure.',
+ (self.curfilestack[-1], node.line))
+ return
+ self.body.append('\n at caption{')
+ def depart_caption(self, node):
+ if isinstance(node.parent, nodes.figure):
+ self.body.append('}\n')
+
+ def visit_image(self, node):
+ if node['uri'] in self.builder.images:
+ uri = self.builder.images[node['uri']]
+ else:
+ # missing image!
+ if self.ignore_missing_images:
+ return
+ uri = node['uri']
+ if uri.find('://') != -1:
+ # ignore remote images
+ return
+ name, ext = path.splitext(uri)
+ attrs = node.attributes
+ # width and height ignored in non-tex output
+ width = self.tex_image_length(attrs.get('width', ''))
+ height = self.tex_image_length(attrs.get('height', ''))
+ alt = self.escape_arg(attrs.get('alt', ''))
+ self.body.append('\n at image{%s,%s,%s,%s,%s}\n' %
+ (name, width, height, alt, ext[1:]))
+ def depart_image(self, node):
+ pass
+
+ def visit_compound(self, node):
+ pass
+ def depart_compound(self, node):
+ pass
+
+ def visit_sidebar(self, node):
+ self.visit_topic(node)
+ def depart_sidebar(self, node):
+ self.depart_topic(node)
+
+ def visit_label(self, node):
+ self.body.append('@w{(')
+ def depart_label(self, node):
+ self.body.append(')} ')
+
+ def visit_legend(self, node):
+ pass
+ def depart_legend(self, node):
+ pass
+
+ def visit_substitution_reference(self, node):
+ pass
+ def depart_substitution_reference(self, node):
+ pass
+
+ def visit_substitution_definition(self, node):
+ raise nodes.SkipNode
+
+ def visit_system_message(self, node):
+ self.body.append('\n at verbatim\n'
+ '<SYSTEM MESSAGE: %s>\n'
+ '@end verbatim\n' % node.astext())
+ raise nodes.SkipNode
+
+ def visit_comment(self, node):
+ self.body.append('\n')
+ for line in node.astext().splitlines():
+ self.body.append('@c %s\n' % line)
+ raise nodes.SkipNode
+
+ def visit_problematic(self, node):
+ self.body.append('>>')
+ def depart_problematic(self, node):
+ self.body.append('<<')
+
+ def unimplemented_visit(self, node):
+ self.builder.warn("unimplemented node type: %r" % node,
+ (self.curfilestack[-1], node.line))
+
+ def unknown_visit(self, node):
+ self.builder.warn("unknown node type: %r" % node,
+ (self.curfilestack[-1], node.line))
+ def unknown_departure(self, node):
+ pass
+
+ ### Sphinx specific
+
+ def visit_productionlist(self, node):
+ self.visit_literal_block(None)
+ names = []
+ for production in node:
+ names.append(production['tokenname'])
+ maxlen = max(len(name) for name in names)
+ for production in node:
+ if production['tokenname']:
+ for id in production.get('ids'):
+ self.add_anchor(id, production)
+ s = production['tokenname'].ljust(maxlen) + ' ::='
+ else:
+ s = '%s ' % (' '*maxlen)
+ self.body.append(self.escape(s))
+ self.body.append(self.escape(production.astext() + '\n'))
+ self.depart_literal_block(None)
+ raise nodes.SkipNode
+
+ def visit_production(self, node):
+ pass
+ def depart_production(self, node):
+ pass
+
+ def visit_literal_emphasis(self, node):
+ self.body.append('@code{')
+ def depart_literal_emphasis(self, node):
+ self.body.append('}')
+
+ def visit_index(self, node):
+ # terminate the line but don't prevent paragraph breaks
+ if isinstance(node.parent, nodes.paragraph):
+ self.ensure_eol()
+ else:
+ self.body.append('\n')
+ for entry in node['entries']:
+ typ, text, tid, text2 = entry
+ text = self.escape_menu(text)
+ self.body.append('@geindex %s\n' % text)
+
+ def visit_versionmodified(self, node):
+ self.body.append('\n')
+ def depart_versionmodified(self, node):
+ self.body.append('\n')
+
+ def visit_start_of_file(self, node):
+ # add a document target
+ self.next_section_ids.add(':doc')
+ self.curfilestack.append(node['docname'])
+ self.footnotestack.append(self.collect_footnotes(node))
+ def depart_start_of_file(self, node):
+ self.curfilestack.pop()
+ self.footnotestack.pop()
+
+ def visit_centered(self, node):
+ txt = self.escape_arg(node.astext())
+ self.body.append('\n\n at center %s\n\n' % txt)
+ raise nodes.SkipNode
+
+ def visit_seealso(self, node):
+ self.body.append(u'\n\n at subsubheading %s\n\n' %
+ admonitionlabels['seealso'])
+ def depart_seealso(self, node):
+ self.body.append('\n')
+
+ def visit_meta(self, node):
+ raise nodes.SkipNode
+
+ def visit_glossary(self, node):
+ pass
+ def depart_glossary(self, node):
+ pass
+
+ def visit_acks(self, node):
+ self.body.append('\n\n')
+ self.body.append(', '.join(n.astext()
+ for n in node.children[0].children) + '.')
+ self.body.append('\n\n')
+ raise nodes.SkipNode
+
+ def visit_highlightlang(self, node):
+ pass
+ def depart_highlightlang(self, node):
+ pass
+
+ ## Desc
+
+ def visit_desc(self, node):
+ self.desc = node
+ self.at_deffnx = '@deffn'
+ def depart_desc(self, node):
+ self.desc = None
+ self.ensure_eol()
+ self.body.append('@end deffn\n')
+
+ def visit_desc_signature(self, node):
+ self.escape_hyphens += 1
+ objtype = node.parent['objtype']
+ if objtype != 'describe':
+ for id in node.get('ids'):
+ self.add_anchor(id, node)
+ # use the full name of the objtype for the category
+ try:
+ domain = self.builder.env.domains[node.parent['domain']]
+ primary = self.builder.config.primary_domain
+ name = domain.get_type_name(domain.object_types[objtype],
+ primary == domain.name)
+ except KeyError:
+ name = objtype
+ # by convention, the deffn category should be capitalized like a title
+ category = self.escape_arg(smart_capwords(name))
+ self.body.append('\n%s {%s} ' % (self.at_deffnx, category))
+ self.at_deffnx = '@deffnx'
+ self.desc_type_name = name
+ def depart_desc_signature(self, node):
+ self.body.append("\n")
+ self.escape_hyphens -= 1
+ self.desc_type_name = None
+
+ def visit_desc_name(self, node):
+ pass
+ def depart_desc_name(self, node):
+ pass
+
+ def visit_desc_addname(self, node):
+ pass
+ def depart_desc_addname(self, node):
+ pass
+
+ def visit_desc_type(self, node):
+ pass
+ def depart_desc_type(self, node):
+ pass
+
+ def visit_desc_returns(self, node):
+ self.body.append(' -> ')
+ def depart_desc_returns(self, node):
+ pass
+
+ def visit_desc_parameterlist(self, node):
+ self.body.append(' (')
+ self.first_param = 1
+ def depart_desc_parameterlist(self, node):
+ self.body.append(')')
+
+ def visit_desc_parameter(self, node):
+ if not self.first_param:
+ self.body.append(', ')
+ else:
+ self.first_param = 0
+ text = self.escape(node.astext())
+ # replace no-break spaces with normal ones
+ text = text.replace(u' ', '@w{ }')
+ self.body.append(text)
+ raise nodes.SkipNode
+
+ def visit_desc_optional(self, node):
+ self.body.append('[')
+ def depart_desc_optional(self, node):
+ self.body.append(']')
+
+ def visit_desc_annotation(self, node):
+ # Try to avoid duplicating info already displayed by the deffn category.
+ # e.g.
+ # @deffn {Class} Foo
+ # -- instead of --
+ # @deffn {Class} class Foo
+ txt = node.astext().strip()
+ if txt == self.desc['desctype'] or \
+ txt == self.desc['objtype'] or \
+ txt in self.desc_type_name.split():
+ raise nodes.SkipNode
+ def depart_desc_annotation(self, node):
+ pass
+
+ def visit_desc_content(self, node):
+ pass
+ def depart_desc_content(self, node):
+ pass
+
+ def visit_inline(self, node):
+ pass
+ def depart_inline(self, node):
+ pass
+
+ def visit_abbreviation(self, node):
+ abbr = node.astext()
+ self.body.append('@abbr{')
+ if node.hasattr('explanation') and abbr not in self.handled_abbrs:
+ self.context.append(',%s}' % self.escape_arg(node['explanation']))
+ self.handled_abbrs.add(abbr)
+ else:
+ self.context.append('}')
+ def depart_abbreviation(self, node):
+ self.body.append(self.context.pop())
+
+ def visit_download_reference(self, node):
+ pass
+ def depart_download_reference(self, node):
+ pass
+
+ def visit_hlist(self, node):
+ self.visit_bullet_list(node)
+ def depart_hlist(self, node):
+ self.depart_bullet_list(node)
+
+ def visit_hlistcol(self, node):
+ pass
+ def depart_hlistcol(self, node):
+ pass
+
+ def visit_pending_xref(self, node):
+ pass
+ def depart_pending_xref(self, node):
+ pass
+
+ def visit_math(self, node):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html')
+ raise nodes.SkipNode
+
+ visit_math_block = visit_math
diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py
new file mode 100644
index 0000000..82b0f45
--- /dev/null
+++ b/sphinx/writers/text.py
@@ -0,0 +1,855 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.writers.text
+ ~~~~~~~~~~~~~~~~~~~
+
+ Custom docutils writer for plain text.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import os
+import re
+import textwrap
+from itertools import groupby, izip_longest
+
+from docutils import nodes, writers
+from docutils.utils import column_width
+
+from sphinx import addnodes
+from sphinx.locale import admonitionlabels, _
+
+
+class TextWrapper(textwrap.TextWrapper):
+ """Custom subclass that uses a different word separator regex."""
+
+ wordsep_re = re.compile(
+ r'(\s+|' # any whitespace
+ r'(?<=\s)(?::[a-z-]+:)?`\S+|' # interpreted text start
+ r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words
+ r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash
+
+ def _wrap_chunks(self, chunks):
+ """_wrap_chunks(chunks : [string]) -> [string]
+
+ The original _wrap_chunks uses len() to calculate width.
+ This method respects wide/fullwidth characters for width adjustment.
+ """
+ drop_whitespace = getattr(self, 'drop_whitespace', True) #py25 compat
+ lines = []
+ if self.width <= 0:
+ raise ValueError("invalid width %r (must be > 0)" % self.width)
+
+ chunks.reverse()
+
+ while chunks:
+ cur_line = []
+ cur_len = 0
+
+ if lines:
+ indent = self.subsequent_indent
+ else:
+ indent = self.initial_indent
+
+ width = self.width - column_width(indent)
+
+ if drop_whitespace and chunks[-1].strip() == '' and lines:
+ del chunks[-1]
+
+ while chunks:
+ l = column_width(chunks[-1])
+
+ if cur_len + l <= width:
+ cur_line.append(chunks.pop())
+ cur_len += l
+
+ else:
+ break
+
+ if chunks and column_width(chunks[-1]) > width:
+ self._handle_long_word(chunks, cur_line, cur_len, width)
+
+ if drop_whitespace and cur_line and cur_line[-1].strip() == '':
+ del cur_line[-1]
+
+ if cur_line:
+ lines.append(indent + ''.join(cur_line))
+
+ return lines
+
+ def _break_word(self, word, space_left):
+ """_break_word(word : string, space_left : int) -> (string, string)
+
+ Break line by unicode width instead of len(word).
+ """
+ total = 0
+ for i,c in enumerate(word):
+ total += column_width(c)
+ if total > space_left:
+ return word[:i-1], word[i-1:]
+ return word, ''
+
+ def _split(self, text):
+ """_split(text : string) -> [string]
+
+ Override original method that only split by 'wordsep_re'.
+ This '_split' split wide-characters into chunk by one character.
+ """
+ split = lambda t: textwrap.TextWrapper._split(self, t)
+ chunks = []
+ for chunk in split(text):
+ for w, g in groupby(chunk, column_width):
+ if w == 1:
+ chunks.extend(split(''.join(g)))
+ else:
+ chunks.extend(list(g))
+ return chunks
+
+ def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
+ """_handle_long_word(chunks : [string],
+ cur_line : [string],
+ cur_len : int, width : int)
+
+ Override original method for using self._break_word() instead of slice.
+ """
+ space_left = max(width - cur_len, 1)
+ if self.break_long_words:
+ l, r = self._break_word(reversed_chunks[-1], space_left)
+ cur_line.append(l)
+ reversed_chunks[-1] = r
+
+ elif not cur_line:
+ cur_line.append(reversed_chunks.pop())
+
+
+MAXWIDTH = 70
+STDINDENT = 3
+
+def my_wrap(text, width=MAXWIDTH, **kwargs):
+ w = TextWrapper(width=width, **kwargs)
+ return w.wrap(text)
+
+
+class TextWriter(writers.Writer):
+ supported = ('text',)
+ settings_spec = ('No options here.', '', ())
+ settings_defaults = {}
+
+ output = None
+
+ def __init__(self, builder):
+ writers.Writer.__init__(self)
+ self.builder = builder
+
+ def translate(self):
+ visitor = TextTranslator(self.document, self.builder)
+ self.document.walkabout(visitor)
+ self.output = visitor.body
+
+
+class TextTranslator(nodes.NodeVisitor):
+ sectionchars = '*=-~"+`'
+
+ def __init__(self, document, builder):
+ nodes.NodeVisitor.__init__(self, document)
+ self.builder = builder
+
+ newlines = builder.config.text_newlines
+ if newlines == 'windows':
+ self.nl = '\r\n'
+ elif newlines == 'native':
+ self.nl = os.linesep
+ else:
+ self.nl = '\n'
+ self.sectionchars = builder.config.text_sectionchars
+ self.states = [[]]
+ self.stateindent = [0]
+ self.list_counter = []
+ self.sectionlevel = 0
+ self.lineblocklevel = 0
+ self.table = None
+
+ def add_text(self, text):
+ self.states[-1].append((-1, text))
+ def new_state(self, indent=STDINDENT):
+ self.states.append([])
+ self.stateindent.append(indent)
+ def end_state(self, wrap=True, end=[''], first=None):
+ content = self.states.pop()
+ maxindent = sum(self.stateindent)
+ indent = self.stateindent.pop()
+ result = []
+ toformat = []
+ def do_format():
+ if not toformat:
+ return
+ if wrap:
+ res = my_wrap(''.join(toformat), width=MAXWIDTH-maxindent)
+ else:
+ res = ''.join(toformat).splitlines()
+ if end:
+ res += end
+ result.append((indent, res))
+ for itemindent, item in content:
+ if itemindent == -1:
+ toformat.append(item)
+ else:
+ do_format()
+ result.append((indent + itemindent, item))
+ toformat = []
+ do_format()
+ if first is not None and result:
+ itemindent, item = result[0]
+ result_rest, result = result[1:], []
+ if item:
+ toformat = [first + ' '.join(item)]
+ do_format() #re-create `result` from `toformat`
+ _dummy, new_item = result[0]
+ result.insert(0, (itemindent - indent, [new_item[0]]))
+ result[1] = (itemindent, new_item[1:])
+ result.extend(result_rest)
+ self.states[-1].extend(result)
+
+ def visit_document(self, node):
+ self.new_state(0)
+ def depart_document(self, node):
+ self.end_state()
+ self.body = self.nl.join(line and (' '*indent + line)
+ for indent, lines in self.states[0]
+ for line in lines)
+ # XXX header/footer?
+
+ def visit_highlightlang(self, node):
+ raise nodes.SkipNode
+
+ def visit_section(self, node):
+ self._title_char = self.sectionchars[self.sectionlevel]
+ self.sectionlevel += 1
+ def depart_section(self, node):
+ self.sectionlevel -= 1
+
+ def visit_topic(self, node):
+ self.new_state(0)
+ def depart_topic(self, node):
+ self.end_state()
+
+ visit_sidebar = visit_topic
+ depart_sidebar = depart_topic
+
+ def visit_rubric(self, node):
+ self.new_state(0)
+ self.add_text('-[ ')
+ def depart_rubric(self, node):
+ self.add_text(' ]-')
+ self.end_state()
+
+ def visit_compound(self, node):
+ pass
+ def depart_compound(self, node):
+ pass
+
+ def visit_glossary(self, node):
+ pass
+ def depart_glossary(self, node):
+ pass
+
+ def visit_title(self, node):
+ if isinstance(node.parent, nodes.Admonition):
+ self.add_text(node.astext()+': ')
+ raise nodes.SkipNode
+ self.new_state(0)
+ def depart_title(self, node):
+ if isinstance(node.parent, nodes.section):
+ char = self._title_char
+ else:
+ char = '^'
+ text = ''.join(x[1] for x in self.states.pop() if x[0] == -1)
+ self.stateindent.pop()
+ self.states[-1].append(
+ (0, ['', text, '%s' % (char * column_width(text)), '']))
+
+ def visit_subtitle(self, node):
+ pass
+ def depart_subtitle(self, node):
+ pass
+
+ def visit_attribution(self, node):
+ self.add_text('-- ')
+ def depart_attribution(self, node):
+ pass
+
+ def visit_desc(self, node):
+ pass
+ def depart_desc(self, node):
+ pass
+
+ def visit_desc_signature(self, node):
+ self.new_state(0)
+ if node.parent['objtype'] in ('class', 'exception'):
+ self.add_text('%s ' % node.parent['objtype'])
+ def depart_desc_signature(self, node):
+ # XXX: wrap signatures in a way that makes sense
+ self.end_state(wrap=False, end=None)
+
+ def visit_desc_name(self, node):
+ pass
+ def depart_desc_name(self, node):
+ pass
+
+ def visit_desc_addname(self, node):
+ pass
+ def depart_desc_addname(self, node):
+ pass
+
+ def visit_desc_type(self, node):
+ pass
+ def depart_desc_type(self, node):
+ pass
+
+ def visit_desc_returns(self, node):
+ self.add_text(' -> ')
+ def depart_desc_returns(self, node):
+ pass
+
+ def visit_desc_parameterlist(self, node):
+ self.add_text('(')
+ self.first_param = 1
+ def depart_desc_parameterlist(self, node):
+ self.add_text(')')
+
+ def visit_desc_parameter(self, node):
+ if not self.first_param:
+ self.add_text(', ')
+ else:
+ self.first_param = 0
+ self.add_text(node.astext())
+ raise nodes.SkipNode
+
+ def visit_desc_optional(self, node):
+ self.add_text('[')
+ def depart_desc_optional(self, node):
+ self.add_text(']')
+
+ def visit_desc_annotation(self, node):
+ pass
+ def depart_desc_annotation(self, node):
+ pass
+
+ def visit_desc_content(self, node):
+ self.new_state()
+ self.add_text(self.nl)
+ def depart_desc_content(self, node):
+ self.end_state()
+
+ def visit_figure(self, node):
+ self.new_state()
+ def depart_figure(self, node):
+ self.end_state()
+
+ def visit_caption(self, node):
+ pass
+ def depart_caption(self, node):
+ pass
+
+ def visit_productionlist(self, node):
+ self.new_state()
+ names = []
+ for production in node:
+ names.append(production['tokenname'])
+ maxlen = max(len(name) for name in names)
+ lastname = None
+ for production in node:
+ if production['tokenname']:
+ self.add_text(production['tokenname'].ljust(maxlen) + ' ::=')
+ lastname = production['tokenname']
+ elif lastname is not None:
+ self.add_text('%s ' % (' '*len(lastname)))
+ self.add_text(production.astext() + self.nl)
+ self.end_state(wrap=False)
+ raise nodes.SkipNode
+
+ def visit_footnote(self, node):
+ self._footnote = node.children[0].astext().strip()
+ self.new_state(len(self._footnote) + 3)
+ def depart_footnote(self, node):
+ self.end_state(first='[%s] ' % self._footnote)
+
+ def visit_citation(self, node):
+ if len(node) and isinstance(node[0], nodes.label):
+ self._citlabel = node[0].astext()
+ else:
+ self._citlabel = ''
+ self.new_state(len(self._citlabel) + 3)
+ def depart_citation(self, node):
+ self.end_state(first='[%s] ' % self._citlabel)
+
+ def visit_label(self, node):
+ raise nodes.SkipNode
+
+ def visit_legend(self, node):
+ pass
+ def depart_legend(self, node):
+ pass
+
+ # XXX: option list could use some better styling
+
+ def visit_option_list(self, node):
+ pass
+ def depart_option_list(self, node):
+ pass
+
+ def visit_option_list_item(self, node):
+ self.new_state(0)
+ def depart_option_list_item(self, node):
+ self.end_state()
+
+ def visit_option_group(self, node):
+ self._firstoption = True
+ def depart_option_group(self, node):
+ self.add_text(' ')
+
+ def visit_option(self, node):
+ if self._firstoption:
+ self._firstoption = False
+ else:
+ self.add_text(', ')
+ def depart_option(self, node):
+ pass
+
+ def visit_option_string(self, node):
+ pass
+ def depart_option_string(self, node):
+ pass
+
+ def visit_option_argument(self, node):
+ self.add_text(node['delimiter'])
+ def depart_option_argument(self, node):
+ pass
+
+ def visit_description(self, node):
+ pass
+ def depart_description(self, node):
+ pass
+
+ def visit_tabular_col_spec(self, node):
+ raise nodes.SkipNode
+
+ def visit_colspec(self, node):
+ self.table[0].append(node['colwidth'])
+ raise nodes.SkipNode
+
+ def visit_tgroup(self, node):
+ pass
+ def depart_tgroup(self, node):
+ pass
+
+ def visit_thead(self, node):
+ pass
+ def depart_thead(self, node):
+ pass
+
+ def visit_tbody(self, node):
+ self.table.append('sep')
+ def depart_tbody(self, node):
+ pass
+
+ def visit_row(self, node):
+ self.table.append([])
+ def depart_row(self, node):
+ pass
+
+ def visit_entry(self, node):
+ if node.has_key('morerows') or node.has_key('morecols'):
+ raise NotImplementedError('Column or row spanning cells are '
+ 'not implemented.')
+ self.new_state(0)
+ def depart_entry(self, node):
+ text = self.nl.join(self.nl.join(x[1]) for x in self.states.pop())
+ self.stateindent.pop()
+ self.table[-1].append(text)
+
+ def visit_table(self, node):
+ if self.table:
+ raise NotImplementedError('Nested tables are not supported.')
+ self.new_state(0)
+ self.table = [[]]
+ def depart_table(self, node):
+ lines = self.table[1:]
+ fmted_rows = []
+ colwidths = self.table[0]
+ realwidths = colwidths[:]
+ separator = 0
+ # don't allow paragraphs in table cells for now
+ for line in lines:
+ if line == 'sep':
+ separator = len(fmted_rows)
+ else:
+ cells = []
+ for i, cell in enumerate(line):
+ par = my_wrap(cell, width=colwidths[i])
+ if par:
+ maxwidth = max(map(column_width, par))
+ else:
+ maxwidth = 0
+ realwidths[i] = max(realwidths[i], maxwidth)
+ cells.append(par)
+ fmted_rows.append(cells)
+
+ def writesep(char='-'):
+ out = ['+']
+ for width in realwidths:
+ out.append(char * (width+2))
+ out.append('+')
+ self.add_text(''.join(out) + self.nl)
+
+ def writerow(row):
+ lines = izip_longest(*row)
+ for line in lines:
+ out = ['|']
+ for i, cell in enumerate(line):
+ if cell:
+ adjust_len = len(cell) - column_width(cell)
+ out.append(' ' + cell.ljust(
+ realwidths[i] + 1 + adjust_len))
+ else:
+ out.append(' ' * (realwidths[i] + 2))
+ out.append('|')
+ self.add_text(''.join(out) + self.nl)
+
+ for i, row in enumerate(fmted_rows):
+ if separator and i == separator:
+ writesep('=')
+ else:
+ writesep('-')
+ writerow(row)
+ writesep('-')
+ self.table = None
+ self.end_state(wrap=False)
+
+ def visit_acks(self, node):
+ self.new_state(0)
+ self.add_text(', '.join(n.astext() for n in node.children[0].children)
+ + '.')
+ self.end_state()
+ raise nodes.SkipNode
+
+ def visit_image(self, node):
+ if 'alt' in node.attributes:
+ self.add_text(_('[image: %s]') % node['alt'])
+ self.add_text(_('[image]'))
+ raise nodes.SkipNode
+
+ def visit_transition(self, node):
+ indent = sum(self.stateindent)
+ self.new_state(0)
+ self.add_text('=' * (MAXWIDTH - indent))
+ self.end_state()
+ raise nodes.SkipNode
+
+ def visit_bullet_list(self, node):
+ self.list_counter.append(-1)
+ def depart_bullet_list(self, node):
+ self.list_counter.pop()
+
+ def visit_enumerated_list(self, node):
+ self.list_counter.append(node.get('start', 1) - 1)
+ def depart_enumerated_list(self, node):
+ self.list_counter.pop()
+
+ def visit_definition_list(self, node):
+ self.list_counter.append(-2)
+ def depart_definition_list(self, node):
+ self.list_counter.pop()
+
+ def visit_list_item(self, node):
+ if self.list_counter[-1] == -1:
+ # bullet list
+ self.new_state(2)
+ elif self.list_counter[-1] == -2:
+ # definition list
+ pass
+ else:
+ # enumerated list
+ self.list_counter[-1] += 1
+ self.new_state(len(str(self.list_counter[-1])) + 2)
+ def depart_list_item(self, node):
+ if self.list_counter[-1] == -1:
+ self.end_state(first='* ')
+ elif self.list_counter[-1] == -2:
+ pass
+ else:
+ self.end_state(first='%s. ' % self.list_counter[-1])
+
+ def visit_definition_list_item(self, node):
+ self._li_has_classifier = len(node) >= 2 and \
+ isinstance(node[1], nodes.classifier)
+ def depart_definition_list_item(self, node):
+ pass
+
+ def visit_term(self, node):
+ self.new_state(0)
+ def depart_term(self, node):
+ if not self._li_has_classifier:
+ self.end_state(end=None)
+
+ def visit_termsep(self, node):
+ self.add_text(', ')
+ raise nodes.SkipNode
+
+ def visit_classifier(self, node):
+ self.add_text(' : ')
+ def depart_classifier(self, node):
+ self.end_state(end=None)
+
+ def visit_definition(self, node):
+ self.new_state()
+ def depart_definition(self, node):
+ self.end_state()
+
+ def visit_field_list(self, node):
+ pass
+ def depart_field_list(self, node):
+ pass
+
+ def visit_field(self, node):
+ pass
+ def depart_field(self, node):
+ pass
+
+ def visit_field_name(self, node):
+ self.new_state(0)
+ def depart_field_name(self, node):
+ self.add_text(':')
+ self.end_state(end=None)
+
+ def visit_field_body(self, node):
+ self.new_state()
+ def depart_field_body(self, node):
+ self.end_state()
+
+ def visit_centered(self, node):
+ pass
+ def depart_centered(self, node):
+ pass
+
+ def visit_hlist(self, node):
+ pass
+ def depart_hlist(self, node):
+ pass
+
+ def visit_hlistcol(self, node):
+ pass
+ def depart_hlistcol(self, node):
+ pass
+
+ def visit_admonition(self, node):
+ self.new_state(0)
+ def depart_admonition(self, node):
+ self.end_state()
+
+ def _visit_admonition(self, node):
+ self.new_state(2)
+ def _make_depart_admonition(name):
+ def depart_admonition(self, node):
+ self.end_state(first=admonitionlabels[name] + ': ')
+ return depart_admonition
+
+ visit_attention = _visit_admonition
+ depart_attention = _make_depart_admonition('attention')
+ visit_caution = _visit_admonition
+ depart_caution = _make_depart_admonition('caution')
+ visit_danger = _visit_admonition
+ depart_danger = _make_depart_admonition('danger')
+ visit_error = _visit_admonition
+ depart_error = _make_depart_admonition('error')
+ visit_hint = _visit_admonition
+ depart_hint = _make_depart_admonition('hint')
+ visit_important = _visit_admonition
+ depart_important = _make_depart_admonition('important')
+ visit_note = _visit_admonition
+ depart_note = _make_depart_admonition('note')
+ visit_tip = _visit_admonition
+ depart_tip = _make_depart_admonition('tip')
+ visit_warning = _visit_admonition
+ depart_warning = _make_depart_admonition('warning')
+ visit_seealso = _visit_admonition
+ depart_seealso = _make_depart_admonition('seealso')
+
+ def visit_versionmodified(self, node):
+ self.new_state(0)
+ def depart_versionmodified(self, node):
+ self.end_state()
+
+ def visit_literal_block(self, node):
+ self.new_state()
+ def depart_literal_block(self, node):
+ self.end_state(wrap=False)
+
+ def visit_doctest_block(self, node):
+ self.new_state(0)
+ def depart_doctest_block(self, node):
+ self.end_state(wrap=False)
+
+ def visit_line_block(self, node):
+ self.new_state()
+ self.lineblocklevel += 1
+ def depart_line_block(self, node):
+ self.lineblocklevel -= 1
+ self.end_state(wrap=False, end=None)
+ if not self.lineblocklevel:
+ self.add_text('\n')
+
+ def visit_line(self, node):
+ pass
+ def depart_line(self, node):
+ self.add_text('\n')
+
+ def visit_block_quote(self, node):
+ self.new_state()
+ def depart_block_quote(self, node):
+ self.end_state()
+
+ def visit_compact_paragraph(self, node):
+ pass
+ def depart_compact_paragraph(self, node):
+ pass
+
+ def visit_paragraph(self, node):
+ if not isinstance(node.parent, nodes.Admonition) or \
+ isinstance(node.parent, addnodes.seealso):
+ self.new_state(0)
+ def depart_paragraph(self, node):
+ if not isinstance(node.parent, nodes.Admonition) or \
+ isinstance(node.parent, addnodes.seealso):
+ self.end_state()
+
+ def visit_target(self, node):
+ raise nodes.SkipNode
+
+ def visit_index(self, node):
+ raise nodes.SkipNode
+
+ def visit_toctree(self, node):
+ raise nodes.SkipNode
+
+ def visit_substitution_definition(self, node):
+ raise nodes.SkipNode
+
+ def visit_pending_xref(self, node):
+ pass
+ def depart_pending_xref(self, node):
+ pass
+
+ def visit_reference(self, node):
+ pass
+ def depart_reference(self, node):
+ pass
+
+ def visit_download_reference(self, node):
+ pass
+ def depart_download_reference(self, node):
+ pass
+
+ def visit_emphasis(self, node):
+ self.add_text('*')
+ def depart_emphasis(self, node):
+ self.add_text('*')
+
+ def visit_literal_emphasis(self, node):
+ self.add_text('*')
+ def depart_literal_emphasis(self, node):
+ self.add_text('*')
+
+ def visit_strong(self, node):
+ self.add_text('**')
+ def depart_strong(self, node):
+ self.add_text('**')
+
+ def visit_abbreviation(self, node):
+ self.add_text('')
+ def depart_abbreviation(self, node):
+ if node.hasattr('explanation'):
+ self.add_text(' (%s)' % node['explanation'])
+
+ def visit_title_reference(self, node):
+ self.add_text('*')
+ def depart_title_reference(self, node):
+ self.add_text('*')
+
+ def visit_literal(self, node):
+ self.add_text('"')
+ def depart_literal(self, node):
+ self.add_text('"')
+
+ def visit_subscript(self, node):
+ self.add_text('_')
+ def depart_subscript(self, node):
+ pass
+
+ def visit_superscript(self, node):
+ self.add_text('^')
+ def depart_superscript(self, node):
+ pass
+
+ def visit_footnote_reference(self, node):
+ self.add_text('[%s]' % node.astext())
+ raise nodes.SkipNode
+
+ def visit_citation_reference(self, node):
+ self.add_text('[%s]' % node.astext())
+ raise nodes.SkipNode
+
+ def visit_Text(self, node):
+ self.add_text(node.astext())
+ def depart_Text(self, node):
+ pass
+
+ def visit_generated(self, node):
+ pass
+ def depart_generated(self, node):
+ pass
+
+ def visit_inline(self, node):
+ pass
+ def depart_inline(self, node):
+ pass
+
+ def visit_container(self, node):
+ pass
+ def depart_container(self, node):
+ pass
+
+ def visit_problematic(self, node):
+ self.add_text('>>')
+ def depart_problematic(self, node):
+ self.add_text('<<')
+
+ def visit_system_message(self, node):
+ self.new_state(0)
+ self.add_text('<SYSTEM MESSAGE: %s>' % node.astext())
+ self.end_state()
+ raise nodes.SkipNode
+
+ def visit_comment(self, node):
+ raise nodes.SkipNode
+
+ def visit_meta(self, node):
+ # only valid for HTML
+ raise nodes.SkipNode
+
+ def visit_raw(self, node):
+ if 'text' in node.get('format', '').split():
+ self.body.append(node.astext())
+ raise nodes.SkipNode
+
+ def visit_math(self, node):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html',
+ (self.builder.current_docname, node.line))
+ raise nodes.SkipNode
+
+ visit_math_block = visit_math
+
+ def unknown_visit(self, node):
+ raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
diff --git a/sphinx/writers/websupport.py b/sphinx/writers/websupport.py
new file mode 100644
index 0000000..bc48c95
--- /dev/null
+++ b/sphinx/writers/websupport.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.writers.websupport
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ sphinx.websupport writer that adds comment-related annotations.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.writers.html import HTMLTranslator
+from sphinx.util.websupport import is_commentable
+
+
+class WebSupportTranslator(HTMLTranslator):
+ """
+ Our custom HTML translator.
+ """
+
+ def __init__(self, builder, *args, **kwargs):
+ HTMLTranslator.__init__(self, builder, *args, **kwargs)
+ self.comment_class = 'sphinx-has-comment'
+
+ def dispatch_visit(self, node):
+ if is_commentable(node) and hasattr(node, 'uid'):
+ self.handle_visit_commentable(node)
+ HTMLTranslator.dispatch_visit(self, node)
+
+ def handle_visit_commentable(self, node):
+ # We will place the node in the HTML id attribute. If the node
+ # already has an id (for indexing purposes) put an empty
+ # span with the existing id directly before this node's HTML.
+ self.add_db_node(node)
+ if node.attributes['ids']:
+ self.body.append('<span id="%s"></span>'
+ % node.attributes['ids'][0])
+ node.attributes['ids'] = ['s%s' % node.uid]
+ node.attributes['classes'].append(self.comment_class)
+
+ def add_db_node(self, node):
+ storage = self.builder.storage
+ if not storage.has_node(node.uid):
+ storage.add_node(id=node.uid,
+ document=self.builder.current_docname,
+ source=node.rawsource or node.astext())
diff --git a/sphinx/writers/xml.py b/sphinx/writers/xml.py
new file mode 100644
index 0000000..cfae484
--- /dev/null
+++ b/sphinx/writers/xml.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.writers.xml
+ ~~~~~~~~~~~~~~~~~~
+
+ Docutils-native XML and pseudo-XML writers.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import writers
+from docutils.writers.docutils_xml import Writer as BaseXMLWriter
+
+
+class XMLWriter(BaseXMLWriter):
+
+ def __init__(self, builder):
+ BaseXMLWriter.__init__(self)
+ self.builder = builder
+
+ def translate(self, *args, **kwargs):
+ self.document.settings.newlines = \
+ self.document.settings.indents = \
+ self.builder.env.config.xml_pretty
+ self.document.settings.xml_declaration = True
+ self.document.settings.doctype_declaration = True
+ return BaseXMLWriter.translate(self)
+
+
+class PseudoXMLWriter(writers.Writer):
+
+ supported = ('pprint', 'pformat', 'pseudoxml')
+ """Formats this writer supports."""
+
+ config_section = 'pseudoxml writer'
+ config_section_dependencies = ('writers',)
+
+ output = None
+ """Final translated form of `document`."""
+
+ def __init__(self, builder):
+ writers.Writer.__init__(self)
+ self.builder = builder
+
+ def translate(self):
+ self.output = self.document.pformat()
+
+ def supports(self, format):
+ """This writer supports all format-specific elements."""
+ return True
diff --git a/tests/coverage.py b/tests/coverage.py
new file mode 100755
index 0000000..95f6f84
--- /dev/null
+++ b/tests/coverage.py
@@ -0,0 +1,1172 @@
+#!/usr/bin/python
+#
+# Perforce Defect Tracking Integration Project
+# <http://www.ravenbrook.com/project/p4dti/>
+#
+# COVERAGE.PY -- COVERAGE TESTING
+#
+# Gareth Rees, Ravenbrook Limited, 2001-12-04
+# Ned Batchelder, 2004-12-12
+# http://nedbatchelder.com/code/modules/coverage.html
+#
+#
+# 1. INTRODUCTION
+#
+# This module provides coverage testing for Python code.
+#
+# The intended readership is all Python developers.
+#
+# This document is not confidential.
+#
+# See [GDR 2001-12-04a] for the command-line interface, programmatic
+# interface and limitations. See [GDR 2001-12-04b] for requirements and
+# design.
+
+r"""Usage:
+
+coverage.py -x [-p] MODULE.py [ARG1 ARG2 ...]
+ Execute module, passing the given command-line arguments, collecting
+ coverage data. With the -p option, write to a temporary file containing
+ the machine name and process ID.
+
+coverage.py -e
+ Erase collected coverage data.
+
+coverage.py -c
+ Collect data from multiple coverage files (as created by -p option above)
+ and store it into a single file representing the union of the coverage.
+
+coverage.py -r [-m] [-o dir1,dir2,...] FILE1 FILE2 ...
+ Report on the statement coverage for the given files. With the -m
+ option, show line numbers of the statements that weren't executed.
+
+coverage.py -a [-d dir] [-o dir1,dir2,...] FILE1 FILE2 ...
+ Make annotated copies of the given files, marking statements that
+ are executed with > and statements that are missed with !. With
+ the -d option, make the copies in that directory. Without the -d
+ option, make each copy in the same directory as the original.
+
+-o dir,dir2,...
+ Omit reporting or annotating files when their filename path starts with
+ a directory listed in the omit list.
+ e.g. python coverage.py -i -r -o c:\python23,lib\enthought\traits
+
+Coverage data is saved in the file .coverage by default. Set the
+COVERAGE_FILE environment variable to save it somewhere else."""
+
+__version__ = "2.85.20080914" # see detailed history at the end of this file.
+
+import compiler
+import compiler.visitor
+import glob
+import os
+import re
+import string
+import symbol
+import sys
+import threading
+import token
+import types
+import zipimport
+from socket import gethostname
+
+# Python version compatibility
+try:
+ strclass = basestring # new to 2.3
+except:
+ strclass = str
+
+# 2. IMPLEMENTATION
+#
+# This uses the "singleton" pattern.
+#
+# The word "morf" means a module object (from which the source file can
+# be deduced by suitable manipulation of the __file__ attribute) or a
+# filename.
+#
+# When we generate a coverage report we have to canonicalize every
+# filename in the coverage dictionary just in case it refers to the
+# module we are reporting on. It seems a shame to throw away this
+# information so the data in the coverage dictionary is transferred to
+# the 'cexecuted' dictionary under the canonical filenames.
+#
+# The coverage dictionary is called "c" and the trace function "t". The
+# reason for these short names is that Python looks up variables by name
+# at runtime and so execution time depends on the length of variables!
+# In the bottleneck of this application it's appropriate to abbreviate
+# names to increase speed.
+
+class StatementFindingAstVisitor(compiler.visitor.ASTVisitor):
+ """ A visitor for a parsed Abstract Syntax Tree which finds executable
+ statements.
+ """
+ def __init__(self, statements, excluded, suite_spots):
+ compiler.visitor.ASTVisitor.__init__(self)
+ self.statements = statements
+ self.excluded = excluded
+ self.suite_spots = suite_spots
+ self.excluding_suite = 0
+
+ def doRecursive(self, node):
+ for n in node.getChildNodes():
+ self.dispatch(n)
+
+ visitStmt = visitModule = doRecursive
+
+ def doCode(self, node):
+ if hasattr(node, 'decorators') and node.decorators:
+ self.dispatch(node.decorators)
+ self.recordAndDispatch(node.code)
+ else:
+ self.doSuite(node, node.code)
+
+ visitFunction = visitClass = doCode
+
+ def getFirstLine(self, node):
+ # Find the first line in the tree node.
+ lineno = node.lineno
+ for n in node.getChildNodes():
+ f = self.getFirstLine(n)
+ if lineno and f:
+ lineno = min(lineno, f)
+ else:
+ lineno = lineno or f
+ return lineno
+
+ def getLastLine(self, node):
+ # Find the first line in the tree node.
+ lineno = node.lineno
+ for n in node.getChildNodes():
+ lineno = max(lineno, self.getLastLine(n))
+ return lineno
+
+ def doStatement(self, node):
+ self.recordLine(self.getFirstLine(node))
+
+ visitAssert = visitAssign = visitAssTuple = visitPrint = \
+ visitPrintnl = visitRaise = visitSubscript = visitDecorators = \
+ doStatement
+
+ def visitPass(self, node):
+ # Pass statements have weird interactions with docstrings. If this
+ # pass statement is part of one of those pairs, claim that the statement
+ # is on the later of the two lines.
+ l = node.lineno
+ if l:
+ lines = self.suite_spots.get(l, [l,l])
+ self.statements[lines[1]] = 1
+
+ def visitDiscard(self, node):
+ # Discard nodes are statements that execute an expression, but then
+ # discard the results. This includes function calls, so we can't
+ # ignore them all. But if the expression is a constant, the statement
+ # won't be "executed", so don't count it now.
+ if node.expr.__class__.__name__ != 'Const':
+ self.doStatement(node)
+
+ def recordNodeLine(self, node):
+ # Stmt nodes often have None, but shouldn't claim the first line of
+ # their children (because the first child might be an ignorable line
+ # like "global a").
+ if node.__class__.__name__ != 'Stmt':
+ return self.recordLine(self.getFirstLine(node))
+ else:
+ return 0
+
+ def recordLine(self, lineno):
+ # Returns a bool, whether the line is included or excluded.
+ if lineno:
+ # Multi-line tests introducing suites have to get charged to their
+ # keyword.
+ if lineno in self.suite_spots:
+ lineno = self.suite_spots[lineno][0]
+ # If we're inside an excluded suite, record that this line was
+ # excluded.
+ if self.excluding_suite:
+ self.excluded[lineno] = 1
+ return 0
+ # If this line is excluded, or suite_spots maps this line to
+ # another line that is exlcuded, then we're excluded.
+ elif self.excluded.has_key(lineno) or \
+ self.suite_spots.has_key(lineno) and \
+ self.excluded.has_key(self.suite_spots[lineno][1]):
+ return 0
+ # Otherwise, this is an executable line.
+ else:
+ self.statements[lineno] = 1
+ return 1
+ return 0
+
+ default = recordNodeLine
+
+ def recordAndDispatch(self, node):
+ self.recordNodeLine(node)
+ self.dispatch(node)
+
+ def doSuite(self, intro, body, exclude=0):
+ exsuite = self.excluding_suite
+ if exclude or (intro and not self.recordNodeLine(intro)):
+ self.excluding_suite = 1
+ self.recordAndDispatch(body)
+ self.excluding_suite = exsuite
+
+ def doPlainWordSuite(self, prevsuite, suite):
+ # Finding the exclude lines for else's is tricky, because they aren't
+ # present in the compiler parse tree. Look at the previous suite,
+ # and find its last line. If any line between there and the else's
+ # first line are excluded, then we exclude the else.
+ lastprev = self.getLastLine(prevsuite)
+ firstelse = self.getFirstLine(suite)
+ for l in range(lastprev+1, firstelse):
+ if self.suite_spots.has_key(l):
+ self.doSuite(None, suite, exclude=self.excluded.has_key(l))
+ break
+ else:
+ self.doSuite(None, suite)
+
+ def doElse(self, prevsuite, node):
+ if node.else_:
+ self.doPlainWordSuite(prevsuite, node.else_)
+
+ def visitFor(self, node):
+ self.doSuite(node, node.body)
+ self.doElse(node.body, node)
+
+ visitWhile = visitFor
+
+ def visitIf(self, node):
+ # The first test has to be handled separately from the rest.
+ # The first test is credited to the line with the "if", but the others
+ # are credited to the line with the test for the elif.
+ self.doSuite(node, node.tests[0][1])
+ for t, n in node.tests[1:]:
+ self.doSuite(t, n)
+ self.doElse(node.tests[-1][1], node)
+
+ def visitTryExcept(self, node):
+ self.doSuite(node, node.body)
+ for i in range(len(node.handlers)):
+ a, b, h = node.handlers[i]
+ if not a:
+ # It's a plain "except:". Find the previous suite.
+ if i > 0:
+ prev = node.handlers[i-1][2]
+ else:
+ prev = node.body
+ self.doPlainWordSuite(prev, h)
+ else:
+ self.doSuite(a, h)
+ self.doElse(node.handlers[-1][2], node)
+
+ def visitTryFinally(self, node):
+ self.doSuite(node, node.body)
+ self.doPlainWordSuite(node.body, node.final)
+
+ def visitWith(self, node):
+ self.doSuite(node, node.body)
+
+ def visitGlobal(self, node):
+ # "global" statements don't execute like others (they don't call the
+ # trace function), so don't record their line numbers.
+ pass
+
+the_coverage = None
+
+class CoverageException(Exception):
+ pass
+
+class coverage:
+ # Name of the cache file (unless environment variable is set).
+ cache_default = ".coverage"
+
+ # Environment variable naming the cache file.
+ cache_env = "COVERAGE_FILE"
+
+ # A dictionary with an entry for (Python source file name, line number
+ # in that file) if that line has been executed.
+ c = {}
+
+ # A map from canonical Python source file name to a dictionary in
+ # which there's an entry for each line number that has been
+ # executed.
+ cexecuted = {}
+
+ # Cache of results of calling the analysis2() method, so that you can
+ # specify both -r and -a without doing double work.
+ analysis_cache = {}
+
+ # Cache of results of calling the canonical_filename() method, to
+ # avoid duplicating work.
+ canonical_filename_cache = {}
+
+ def __init__(self):
+ global the_coverage
+ if the_coverage:
+ raise CoverageException("Only one coverage object allowed.")
+ self.usecache = 1
+ self.cache = None
+ self.parallel_mode = False
+ self.exclude_re = ''
+ self.nesting = 0
+ self.cstack = []
+ self.xstack = []
+ self.relative_dir = self.abs_file(os.curdir)+os.sep
+ self.exclude('# *pragma[: ]*[nN][oO] *[cC][oO][vV][eE][rR]')
+
+ # t(f, x, y). This method is passed to sys.settrace as a trace function.
+ # See [van Rossum 2001-07-20b, 9.2] for an explanation of sys.settrace and
+ # the arguments and return value of the trace function.
+ # See [van Rossum 2001-07-20a, 3.2] for a description of frame and code
+ # objects.
+
+ def t(self, f, w, unused): #pragma: no cover
+ if w == 'line':
+ self.c[(f.f_code.co_filename, f.f_lineno)] = 1
+ #-for c in self.cstack:
+ #- c[(f.f_code.co_filename, f.f_lineno)] = 1
+ return self.t
+
+ def help(self, error=None): #pragma: no cover
+ if error:
+ print error
+ print
+ print __doc__
+ sys.exit(1)
+
+ def command_line(self, argv, help_fn=None):
+ import getopt
+ help_fn = help_fn or self.help
+ settings = {}
+ optmap = {
+ '-a': 'annotate',
+ '-c': 'collect',
+ '-d:': 'directory=',
+ '-e': 'erase',
+ '-h': 'help',
+ '-i': 'ignore-errors',
+ '-m': 'show-missing',
+ '-p': 'parallel-mode',
+ '-r': 'report',
+ '-x': 'execute',
+ '-o:': 'omit=',
+ }
+ short_opts = string.join(map(lambda o: o[1:], optmap.keys()), '')
+ long_opts = optmap.values()
+ options, args = getopt.getopt(argv, short_opts, long_opts)
+ for o, a in options:
+ if optmap.has_key(o):
+ settings[optmap[o]] = 1
+ elif optmap.has_key(o + ':'):
+ settings[optmap[o + ':']] = a
+ elif o[2:] in long_opts:
+ settings[o[2:]] = 1
+ elif o[2:] + '=' in long_opts:
+ settings[o[2:]+'='] = a
+ else: #pragma: no cover
+ # Can't get here, because getopt won't return anything unknown.
+ pass
+
+ if settings.get('help'):
+ help_fn()
+
+ for i in ['erase', 'execute']:
+ for j in ['annotate', 'report', 'collect']:
+ if settings.get(i) and settings.get(j):
+ help_fn("You can't specify the '%s' and '%s' "
+ "options at the same time." % (i, j))
+
+ args_needed = (settings.get('execute')
+ or settings.get('annotate')
+ or settings.get('report'))
+ action = (settings.get('erase')
+ or settings.get('collect')
+ or args_needed)
+ if not action:
+ help_fn("You must specify at least one of -e, -x, -c, -r, or -a.")
+ if not args_needed and args:
+ help_fn("Unexpected arguments: %s" % " ".join(args))
+
+ self.parallel_mode = settings.get('parallel-mode')
+ self.get_ready()
+
+ if settings.get('erase'):
+ self.erase()
+ if settings.get('execute'):
+ if not args:
+ help_fn("Nothing to do.")
+ sys.argv = args
+ self.start()
+ import __main__
+ sys.path[0] = os.path.dirname(sys.argv[0])
+ execfile(sys.argv[0], __main__.__dict__)
+ if settings.get('collect'):
+ self.collect()
+ if not args:
+ args = self.cexecuted.keys()
+
+ ignore_errors = settings.get('ignore-errors')
+ show_missing = settings.get('show-missing')
+ directory = settings.get('directory=')
+
+ omit = settings.get('omit=')
+ if omit is not None:
+ omit = [self.abs_file(p) for p in omit.split(',')]
+ else:
+ omit = []
+
+ if settings.get('report'):
+ self.report(args, show_missing, ignore_errors, omit_prefixes=omit)
+ if settings.get('annotate'):
+ self.annotate(args, directory, ignore_errors, omit_prefixes=omit)
+
+ def use_cache(self, usecache, cache_file=None):
+ self.usecache = usecache
+ if cache_file and not self.cache:
+ self.cache_default = cache_file
+
+ def get_ready(self, parallel_mode=False):
+ if self.usecache and not self.cache:
+ self.cache = os.environ.get(self.cache_env, self.cache_default)
+ if self.parallel_mode:
+ self.cache += "." + gethostname() + "." + str(os.getpid())
+ self.restore()
+ self.analysis_cache = {}
+
+ def start(self, parallel_mode=False):
+ self.get_ready()
+ if self.nesting == 0: #pragma: no cover
+ sys.settrace(self.t)
+ if hasattr(threading, 'settrace'):
+ threading.settrace(self.t)
+ self.nesting += 1
+
+ def stop(self):
+ self.nesting -= 1
+ if self.nesting == 0: #pragma: no cover
+ sys.settrace(None)
+ if hasattr(threading, 'settrace'):
+ threading.settrace(None)
+
+ def erase(self):
+ self.get_ready()
+ self.c = {}
+ self.analysis_cache = {}
+ self.cexecuted = {}
+ if self.cache and os.path.exists(self.cache):
+ os.remove(self.cache)
+
+ def exclude(self, re):
+ if self.exclude_re:
+ self.exclude_re += "|"
+ self.exclude_re += "(" + re + ")"
+
+ def begin_recursive(self):
+ self.cstack.append(self.c)
+ self.xstack.append(self.exclude_re)
+
+ def end_recursive(self):
+ self.c = self.cstack.pop()
+ self.exclude_re = self.xstack.pop()
+
+ # save(). Save coverage data to the coverage cache.
+
+ def save(self):
+ if self.usecache and self.cache:
+ self.canonicalize_filenames()
+ cache = open(self.cache, 'wb')
+ import marshal
+ marshal.dump(self.cexecuted, cache)
+ cache.close()
+
+ # restore(). Restore coverage data from the coverage cache (if it exists).
+
+ def restore(self):
+ self.c = {}
+ self.cexecuted = {}
+ assert self.usecache
+ if os.path.exists(self.cache):
+ self.cexecuted = self.restore_file(self.cache)
+
+ def restore_file(self, file_name):
+ try:
+ cache = open(file_name, 'rb')
+ import marshal
+ cexecuted = marshal.load(cache)
+ cache.close()
+ if isinstance(cexecuted, types.DictType):
+ return cexecuted
+ else:
+ return {}
+ except:
+ return {}
+
+ # collect(). Collect data in multiple files produced by parallel mode
+
+ def collect(self):
+ cache_dir, local = os.path.split(self.cache)
+ for f in os.listdir(cache_dir or '.'):
+ if not f.startswith(local):
+ continue
+
+ full_path = os.path.join(cache_dir, f)
+ cexecuted = self.restore_file(full_path)
+ self.merge_data(cexecuted)
+
+ def merge_data(self, new_data):
+ for file_name, file_data in new_data.items():
+ if self.cexecuted.has_key(file_name):
+ self.merge_file_data(self.cexecuted[file_name], file_data)
+ else:
+ self.cexecuted[file_name] = file_data
+
+ def merge_file_data(self, cache_data, new_data):
+ for line_number in new_data.keys():
+ if not cache_data.has_key(line_number):
+ cache_data[line_number] = new_data[line_number]
+
+ def abs_file(self, filename):
+ """ Helper function to turn a filename into an absolute normalized
+ filename.
+ """
+ return os.path.normcase(os.path.abspath(os.path.realpath(filename)))
+
+ def get_zip_data(self, filename):
+ """ Get data from `filename` if it is a zip file path, or return None
+ if it is not.
+ """
+ markers = ['.zip'+os.sep, '.egg'+os.sep]
+ for marker in markers:
+ if marker in filename:
+ parts = filename.split(marker)
+ try:
+ zi = zipimport.zipimporter(parts[0]+marker[:-1])
+ except zipimport.ZipImportError:
+ continue
+ try:
+ data = zi.get_data(parts[1])
+ except IOError:
+ continue
+ return data
+ return None
+
+ # canonical_filename(filename). Return a canonical filename for the
+ # file (that is, an absolute path with no redundant components and
+ # normalized case). See [GDR 2001-12-04b, 3.3].
+
+ def canonical_filename(self, filename):
+ if not self.canonical_filename_cache.has_key(filename):
+ f = filename
+ if os.path.isabs(f) and not os.path.exists(f):
+ if not self.get_zip_data(f):
+ f = os.path.basename(f)
+ if not os.path.isabs(f):
+ for path in [os.curdir] + sys.path:
+ g = os.path.join(path, f)
+ if os.path.exists(g):
+ f = g
+ break
+ cf = self.abs_file(f)
+ self.canonical_filename_cache[filename] = cf
+ return self.canonical_filename_cache[filename]
+
+ # canonicalize_filenames(). Copy results from "c" to "cexecuted",
+ # canonicalizing filenames on the way. Clear the "c" map.
+
+ def canonicalize_filenames(self):
+ for filename, lineno in self.c.keys():
+ if filename == '<string>':
+ # Can't do anything useful with exec'd strings, so skip them.
+ continue
+ f = self.canonical_filename(filename)
+ if not self.cexecuted.has_key(f):
+ self.cexecuted[f] = {}
+ self.cexecuted[f][lineno] = 1
+ self.c = {}
+
+ # morf_filename(morf). Return the filename for a module or file.
+
+ def morf_filename(self, morf):
+ if hasattr(morf, '__file__'):
+ f = morf.__file__
+ else:
+ f = morf
+ return self.canonical_filename(f)
+
+ # analyze_morf(morf). Analyze the module or filename passed as
+ # the argument. If the source code can't be found, raise an error.
+ # Otherwise, return a tuple of (1) the canonical filename of the
+ # source code for the module, (2) a list of lines of statements
+ # in the source code, (3) a list of lines of excluded statements,
+ # and (4), a map of line numbers to multi-line line number ranges, for
+ # statements that cross lines.
+
+ def analyze_morf(self, morf):
+ if self.analysis_cache.has_key(morf):
+ return self.analysis_cache[morf]
+ filename = self.morf_filename(morf)
+ ext = os.path.splitext(filename)[1]
+ source, sourcef = None, None
+ if ext == '.pyc':
+ if not os.path.exists(filename[:-1]):
+ source = self.get_zip_data(filename[:-1])
+ if not source:
+ raise CoverageException(
+ "No source for compiled code '%s'." % filename
+ )
+ filename = filename[:-1]
+ if not source:
+ sourcef = open(filename, 'rU')
+ source = sourcef.read()
+ try:
+ lines, excluded_lines, line_map = self.find_executable_statements(
+ source, exclude=self.exclude_re
+ )
+ except SyntaxError, synerr:
+ raise CoverageException(
+ "Couldn't parse '%s' as Python source: '%s' at line %d" %
+ (filename, synerr.msg, synerr.lineno)
+ )
+ if sourcef:
+ sourcef.close()
+ result = filename, lines, excluded_lines, line_map
+ self.analysis_cache[morf] = result
+ return result
+
+ def first_line_of_tree(self, tree):
+ while True:
+ if len(tree) == 3 and type(tree[2]) == type(1):
+ return tree[2]
+ tree = tree[1]
+
+ def last_line_of_tree(self, tree):
+ while True:
+ if len(tree) == 3 and type(tree[2]) == type(1):
+ return tree[2]
+ tree = tree[-1]
+
+ def find_docstring_pass_pair(self, tree, spots):
+ for i in range(1, len(tree)):
+ if (self.is_string_constant(tree[i])
+ and self.is_pass_stmt(tree[i+1])):
+ first_line = self.first_line_of_tree(tree[i])
+ last_line = self.last_line_of_tree(tree[i+1])
+ self.record_multiline(spots, first_line, last_line)
+
+ def is_string_constant(self, tree):
+ try:
+ return (tree[0] == symbol.stmt
+ and tree[1][1][1][0] == symbol.expr_stmt)
+ except:
+ return False
+
+ def is_pass_stmt(self, tree):
+ try:
+ return (tree[0] == symbol.stmt
+ and tree[1][1][1][0] == symbol.pass_stmt)
+ except:
+ return False
+
+ def record_multiline(self, spots, i, j):
+ for l in range(i, j+1):
+ spots[l] = (i, j)
+
+ def get_suite_spots(self, tree, spots):
+ """ Analyze a parse tree to find suite introducers which span a number
+ of lines.
+ """
+ for i in range(1, len(tree)):
+ if type(tree[i]) == type(()):
+ if tree[i][0] == symbol.suite:
+ # Found a suite, look back for the colon and keyword.
+ lineno_colon = lineno_word = None
+ for j in range(i-1, 0, -1):
+ if tree[j][0] == token.COLON:
+ # Colons are never executed themselves: we want the
+ # line number of the last token before the colon.
+ lineno_colon = self.last_line_of_tree(tree[j-1])
+ elif tree[j][0] == token.NAME:
+ if tree[j][1] == 'elif':
+ # Find the line number of the first non-terminal
+ # after the keyword.
+ t = tree[j+1]
+ while t and token.ISNONTERMINAL(t[0]):
+ t = t[1]
+ if t:
+ lineno_word = t[2]
+ else:
+ lineno_word = tree[j][2]
+ break
+ elif tree[j][0] == symbol.except_clause:
+ # "except" clauses look like:
+ # ('except_clause', ('NAME', 'except', lineno), ...)
+ if tree[j][1][0] == token.NAME:
+ lineno_word = tree[j][1][2]
+ break
+ if lineno_colon and lineno_word:
+ # Found colon and keyword, mark all the lines
+ # between the two with the two line numbers.
+ self.record_multiline(spots, lineno_word, lineno_colon)
+
+ # "pass" statements are tricky: different versions of Python
+ # treat them differently, especially in the common case of a
+ # function with a doc string and a single pass statement.
+ self.find_docstring_pass_pair(tree[i], spots)
+
+ elif tree[i][0] == symbol.simple_stmt:
+ first_line = self.first_line_of_tree(tree[i])
+ last_line = self.last_line_of_tree(tree[i])
+ if first_line != last_line:
+ self.record_multiline(spots, first_line, last_line)
+ self.get_suite_spots(tree[i], spots)
+
+ def find_executable_statements(self, text, exclude=None):
+ # Find lines which match an exclusion pattern.
+ excluded = {}
+ suite_spots = {}
+ if exclude:
+ reExclude = re.compile(exclude)
+ lines = text.split('\n')
+ for i in range(len(lines)):
+ if reExclude.search(lines[i]):
+ excluded[i+1] = 1
+
+ # Parse the code and analyze the parse tree to find out which statements
+ # are multiline, and where suites begin and end.
+ import parser
+ tree = parser.suite(text+'\n\n').totuple(1)
+ self.get_suite_spots(tree, suite_spots)
+ #print "Suite spots:", suite_spots
+
+ # Use the compiler module to parse the text and find the executable
+ # statements. We add newlines to be impervious to final partial lines.
+ statements = {}
+ ast = compiler.parse(text+'\n\n')
+ visitor = StatementFindingAstVisitor(statements, excluded, suite_spots)
+ compiler.walk(ast, visitor, walker=visitor)
+
+ lines = statements.keys()
+ lines.sort()
+ excluded_lines = excluded.keys()
+ excluded_lines.sort()
+ return lines, excluded_lines, suite_spots
+
+ # format_lines(statements, lines). Format a list of line numbers
+ # for printing by coalescing groups of lines as long as the lines
+ # represent consecutive statements. This will coalesce even if
+ # there are gaps between statements, so if statements =
+ # [1,2,3,4,5,10,11,12,13,14] and lines = [1,2,5,10,11,13,14] then
+ # format_lines will return "1-2, 5-11, 13-14".
+
+ def format_lines(self, statements, lines):
+ pairs = []
+ i = 0
+ j = 0
+ start = None
+ pairs = []
+ while i < len(statements) and j < len(lines):
+ if statements[i] == lines[j]:
+ if start is None:
+ start = lines[j]
+ end = lines[j]
+ j = j + 1
+ elif start:
+ pairs.append((start, end))
+ start = None
+ i = i + 1
+ if start:
+ pairs.append((start, end))
+ def stringify(pair):
+ start, end = pair
+ if start == end:
+ return "%d" % start
+ else:
+ return "%d-%d" % (start, end)
+ ret = string.join(map(stringify, pairs), ", ")
+ return ret
+
+ # Backward compatibility with version 1.
+ def analysis(self, morf):
+ f, s, _, m, mf = self.analysis2(morf)
+ return f, s, m, mf
+
+ def analysis2(self, morf):
+ filename, statements, excluded, line_map = self.analyze_morf(morf)
+ self.canonicalize_filenames()
+ if not self.cexecuted.has_key(filename):
+ self.cexecuted[filename] = {}
+ missing = []
+ for line in statements:
+ lines = line_map.get(line, [line, line])
+ for l in range(lines[0], lines[1]+1):
+ if self.cexecuted[filename].has_key(l):
+ break
+ else:
+ missing.append(line)
+ return (filename, statements, excluded, missing,
+ self.format_lines(statements, missing))
+
+ def relative_filename(self, filename):
+ """ Convert filename to relative filename from self.relative_dir.
+ """
+ return filename.replace(self.relative_dir, "")
+
+ def morf_name(self, morf):
+ """ Return the name of morf as used in report.
+ """
+ if hasattr(morf, '__name__'):
+ return morf.__name__
+ else:
+ return self.relative_filename(os.path.splitext(morf)[0])
+
+ def filter_by_prefix(self, morfs, omit_prefixes):
+ """ Return list of morfs where the morf name does not begin
+ with any one of the omit_prefixes.
+ """
+ filtered_morfs = []
+ for morf in morfs:
+ for prefix in omit_prefixes:
+ if self.morf_name(morf).startswith(prefix):
+ break
+ else:
+ filtered_morfs.append(morf)
+
+ return filtered_morfs
+
+ def morf_name_compare(self, x, y):
+ return cmp(self.morf_name(x), self.morf_name(y))
+
+ def report(self, morfs, show_missing=1, ignore_errors=0, file=None,
+ omit_prefixes=[]):
+ if not isinstance(morfs, types.ListType):
+ morfs = [morfs]
+ # On windows, the shell doesn't expand wildcards. Do it here.
+ globbed = []
+ for morf in morfs:
+ if isinstance(morf, strclass):
+ globbed.extend(glob.glob(morf))
+ else:
+ globbed.append(morf)
+ morfs = globbed
+
+ morfs = self.filter_by_prefix(morfs, omit_prefixes)
+ morfs.sort(self.morf_name_compare)
+
+ max_name = max([5,] + map(len, map(self.morf_name, morfs)))
+ fmt_name = "%%- %ds " % max_name
+ fmt_err = fmt_name + "%s: %s"
+ header = fmt_name % "Name" + " Stmts Exec Cover"
+ fmt_coverage = fmt_name + "% 6d % 6d % 5d%%"
+ if show_missing:
+ header = header + " Missing"
+ fmt_coverage = fmt_coverage + " %s"
+ if not file:
+ file = sys.stdout
+ print >>file, header
+ print >>file, "-" * len(header)
+ total_statements = 0
+ total_executed = 0
+ for morf in morfs:
+ name = self.morf_name(morf)
+ try:
+ _, statements, _, missing, readable = self.analysis2(morf)
+ n = len(statements)
+ m = n - len(missing)
+ if n > 0:
+ pc = 100.0 * m / n
+ else:
+ pc = 100.0
+ args = (name, n, m, pc)
+ if show_missing:
+ args = args + (readable,)
+ print >>file, fmt_coverage % args
+ total_statements = total_statements + n
+ total_executed = total_executed + m
+ except KeyboardInterrupt: #pragma: no cover
+ raise
+ except:
+ if not ignore_errors:
+ typ, msg = sys.exc_info()[:2]
+ print >>file, fmt_err % (name, typ, msg)
+ if len(morfs) > 1:
+ print >>file, "-" * len(header)
+ if total_statements > 0:
+ pc = 100.0 * total_executed / total_statements
+ else:
+ pc = 100.0
+ args = ("TOTAL", total_statements, total_executed, pc)
+ if show_missing:
+ args = args + ("",)
+ print >>file, fmt_coverage % args
+
+ # annotate(morfs, ignore_errors).
+
+ blank_re = re.compile(r"\s*(#|$)")
+ else_re = re.compile(r"\s*else\s*:\s*(#|$)")
+
+ def annotate(self, morfs, directory=None, ignore_errors=0,
+ omit_prefixes=[]):
+ morfs = self.filter_by_prefix(morfs, omit_prefixes)
+ for morf in morfs:
+ try:
+ (filename, statements, excluded,
+ missing, _) = self.analysis2(morf)
+ self.annotate_file(filename, statements, excluded, missing,
+ directory)
+ except KeyboardInterrupt:
+ raise
+ except:
+ if not ignore_errors:
+ raise
+
+ def annotate_file(self, filename, statements, excluded, missing,
+ directory=None):
+ source = open(filename, 'r')
+ if directory:
+ dest_file = os.path.join(directory,
+ os.path.basename(filename)
+ + ',cover')
+ else:
+ dest_file = filename + ',cover'
+ dest = open(dest_file, 'w')
+ lineno = 0
+ i = 0
+ j = 0
+ covered = 1
+ while 1:
+ line = source.readline()
+ if line == '':
+ break
+ lineno = lineno + 1
+ while i < len(statements) and statements[i] < lineno:
+ i = i + 1
+ while j < len(missing) and missing[j] < lineno:
+ j = j + 1
+ if i < len(statements) and statements[i] == lineno:
+ covered = j >= len(missing) or missing[j] > lineno
+ if self.blank_re.match(line):
+ dest.write(' ')
+ elif self.else_re.match(line):
+ # Special logic for lines containing only 'else:'.
+ # See [GDR 2001-12-04b, 3.2].
+ if i >= len(statements) and j >= len(missing):
+ dest.write('! ')
+ elif i >= len(statements) or j >= len(missing):
+ dest.write('> ')
+ elif statements[i] == missing[j]:
+ dest.write('! ')
+ else:
+ dest.write('> ')
+ elif lineno in excluded:
+ dest.write('- ')
+ elif covered:
+ dest.write('> ')
+ else:
+ dest.write('! ')
+ dest.write(line)
+ source.close()
+ dest.close()
+
+# Singleton object.
+the_coverage = coverage()
+
+# Module functions call methods in the singleton object.
+def use_cache(*args, **kw):
+ return the_coverage.use_cache(*args, **kw)
+
+def start(*args, **kw):
+ return the_coverage.start(*args, **kw)
+
+def stop(*args, **kw):
+ return the_coverage.stop(*args, **kw)
+
+def erase(*args, **kw):
+ return the_coverage.erase(*args, **kw)
+
+def begin_recursive(*args, **kw):
+ return the_coverage.begin_recursive(*args, **kw)
+
+def end_recursive(*args, **kw):
+ return the_coverage.end_recursive(*args, **kw)
+
+def exclude(*args, **kw):
+ return the_coverage.exclude(*args, **kw)
+
+def analysis(*args, **kw):
+ return the_coverage.analysis(*args, **kw)
+
+def analysis2(*args, **kw):
+ return the_coverage.analysis2(*args, **kw)
+
+def report(*args, **kw):
+ return the_coverage.report(*args, **kw)
+
+def annotate(*args, **kw):
+ return the_coverage.annotate(*args, **kw)
+
+def annotate_file(*args, **kw):
+ return the_coverage.annotate_file(*args, **kw)
+
+# Save coverage data when Python exits. (The atexit module wasn't
+# introduced until Python 2.0, so use sys.exitfunc when it's not
+# available.)
+try:
+ import atexit
+ atexit.register(the_coverage.save)
+except ImportError:
+ sys.exitfunc = the_coverage.save
+
+def main():
+ the_coverage.command_line(sys.argv[1:])
+
+# Command-line interface.
+if __name__ == '__main__':
+ main()
+
+
+# A. REFERENCES
+#
+# [GDR 2001-12-04a] "Statement coverage for Python"; Gareth Rees;
+# Ravenbrook Limited; 2001-12-04;
+# <http://www.nedbatchelder.com/code/modules/rees-coverage.html>.
+#
+# [GDR 2001-12-04b] "Statement coverage for Python: design and
+# analysis"; Gareth Rees; Ravenbrook Limited; 2001-12-04;
+# <http://www.nedbatchelder.com/code/modules/rees-design.html>.
+#
+# [van Rossum 2001-07-20a] "Python Reference Manual (releae 2.1.1)";
+# Guide van Rossum; 2001-07-20;
+# <http://www.python.org/doc/2.1.1/ref/ref.html>.
+#
+# [van Rossum 2001-07-20b] "Python Library Reference"; Guido van Rossum;
+# 2001-07-20; <http://www.python.org/doc/2.1.1/lib/lib.html>.
+#
+#
+# B. DOCUMENT HISTORY
+#
+# 2001-12-04 GDR Created.
+#
+# 2001-12-06 GDR Added command-line interface and source code
+# annotation.
+#
+# 2001-12-09 GDR Moved design and interface to separate documents.
+#
+# 2001-12-10 GDR Open cache file as binary on Windows. Allow
+# simultaneous -e and -x, or -a and -r.
+#
+# 2001-12-12 GDR Added command-line help. Cache analysis so that it
+# only needs to be done once when you specify -a and -r.
+#
+# 2001-12-13 GDR Improved speed while recording. Portable between
+# Python 1.5.2 and 2.1.1.
+#
+# 2002-01-03 GDR Module-level functions work correctly.
+#
+# 2002-01-07 GDR Update sys.path when running a file with the -x option,
+# so that it matches the value the program would get if it were run on
+# its own.
+#
+# 2004-12-12 NMB Significant code changes.
+# - Finding executable statements has been rewritten so that docstrings and
+# other quirks of Python execution aren't mistakenly identified as missing
+# lines.
+# - Lines can be excluded from consideration, even entire suites of lines.
+# - The filesystem cache of covered lines can be disabled programmatically.
+# - Modernized the code.
+#
+# 2004-12-14 NMB Minor tweaks. Return 'analysis' to its original behavior
+# and add 'analysis2'. Add a global for 'annotate', and factor it, adding
+# 'annotate_file'.
+#
+# 2004-12-31 NMB Allow for keyword arguments in the module global functions.
+# Thanks, Allen.
+#
+# 2005-12-02 NMB Call threading.settrace so that all threads are measured.
+# Thanks Martin Fuzzey. Add a file argument to report so that reports can be
+# captured to a different destination.
+#
+# 2005-12-03 NMB coverage.py can now measure itself.
+#
+# 2005-12-04 NMB Adapted Greg Rogers' patch for using relative filenames,
+# and sorting and omitting files to report on.
+#
+# 2006-07-23 NMB Applied Joseph Tate's patch for function decorators.
+#
+# 2006-08-21 NMB Applied Sigve Tjora and Mark van der Wal's fixes for argument
+# handling.
+#
+# 2006-08-22 NMB Applied Geoff Bache's parallel mode patch.
+#
+# 2006-08-23 NMB Refactorings to improve testability. Fixes to command-line
+# logic for parallel mode and collect.
+#
+# 2006-08-25 NMB "#pragma: nocover" is excluded by default.
+#
+# 2006-09-10 NMB Properly ignore docstrings and other constant expressions that
+# appear in the middle of a function, a problem reported by Tim Leslie.
+# Minor changes to avoid lint warnings.
+#
+# 2006-09-17 NMB coverage.erase() shouldn't clobber the exclude regex.
+# Change how parallel mode is invoked, and fix erase() so that it erases the
+# cache when called programmatically.
+#
+# 2007-07-21 NMB In reports, ignore code executed from strings, since we can't
+# do anything useful with it anyway.
+# Better file handling on Linux, thanks Guillaume Chazarain.
+# Better shell support on Windows, thanks Noel O'Boyle.
+# Python 2.2 support maintained, thanks Catherine Proulx.
+#
+# 2007-07-22 NMB Python 2.5 now fully supported. The method of dealing with
+# multi-line statements is now less sensitive to the exact line that Python
+# reports during execution. Pass statements are handled specially so that their
+# disappearance during execution won't throw off the measurement.
+#
+# 2007-07-23 NMB Now Python 2.5 is *really* fully supported: the body of the
+# new with statement is counted as executable.
+#
+# 2007-07-29 NMB Better packaging.
+#
+# 2007-09-30 NMB Don't try to predict whether a file is Python source based on
+# the extension. Extensionless files are often Pythons scripts. Instead, simply
+# parse the file and catch the syntax errors. Hat tip to Ben Finney.
+#
+# 2008-05-25 NMB Open files in rU mode to avoid line ending craziness.
+# Thanks, Edward Loper.
+#
+# 2008-09-14 NMB Add support for finding source files in eggs.
+# Don't check for morf's being instances of ModuleType, instead use duck typing
+# so that pseudo-modules can participate. Thanks, Imri Goldberg.
+# Use os.realpath as part of the fixing of filenames so that symlinks won't
+# confuse things. Thanks, Patrick Mezard.
+#
+#
+# C. COPYRIGHT AND LICENCE
+#
+# Copyright 2001 Gareth Rees. All rights reserved.
+# Copyright 2004-2008 Ned Batchelder. 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
+# HOLDERS AND 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.
+#
+# $Id: coverage.py 100 2008-10-12 12:08:22Z nedbat $
diff --git a/tests/etree13/ElementPath.py b/tests/etree13/ElementPath.py
new file mode 100644
index 0000000..b097d81
--- /dev/null
+++ b/tests/etree13/ElementPath.py
@@ -0,0 +1,226 @@
+#
+# ElementTree
+# $Id$
+#
+# limited xpath support for element trees
+#
+# history:
+# 2003-05-23 fl created
+# 2003-05-28 fl added support for // etc
+# 2003-08-27 fl fixed parsing of periods in element names
+# 2007-09-10 fl new selection engine
+#
+# Copyright (c) 2003-2007 by Fredrik Lundh. All rights reserved.
+#
+# fredrik at pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2007 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Implementation module for XPath support. There's usually no reason
+# to import this module directly; the <b>ElementTree</b> does this for
+# you, if needed.
+##
+
+import re
+
+xpath_tokenizer = re.compile(
+ "("
+ "'[^']*'|\"[^\"]*\"|"
+ "::|"
+ "//?|"
+ "\.\.|"
+ "\(\)|"
+ "[/.*:\[\]\(\)@=])|"
+ "((?:\{[^}]+\})?[^/:\[\]\(\)@=\s]+)|"
+ "\s+"
+ ).findall
+
+def prepare_tag(next, token):
+ tag = token[1]
+ def select(context, result):
+ for elem in result:
+ for e in elem:
+ if e.tag == tag:
+ yield e
+ return select
+
+def prepare_star(next, token):
+ def select(context, result):
+ for elem in result:
+ for e in elem:
+ yield e
+ return select
+
+def prepare_dot(next, token):
+ def select(context, result):
+ for elem in result:
+ yield elem
+ return select
+
+def prepare_iter(next, token):
+ token = next()
+ if token[0] == "*":
+ tag = "*"
+ elif not token[0]:
+ tag = token[1]
+ else:
+ raise SyntaxError
+ def select(context, result):
+ for elem in result:
+ for e in elem.iter(tag):
+ if e is not elem:
+ yield e
+ return select
+
+def prepare_dot_dot(next, token):
+ def select(context, result):
+ parent_map = context.parent_map
+ if parent_map is None:
+ context.parent_map = parent_map = {}
+ for p in context.root.iter():
+ for e in p:
+ parent_map[e] = p
+ for elem in result:
+ if elem in parent_map:
+ yield parent_map[elem]
+ return select
+
+def prepare_predicate(next, token):
+ # this one should probably be refactored...
+ token = next()
+ if token[0] == "@":
+ # attribute
+ token = next()
+ if token[0]:
+ raise SyntaxError("invalid attribute predicate")
+ key = token[1]
+ token = next()
+ if token[0] == "]":
+ def select(context, result):
+ for elem in result:
+ if elem.get(key) is not None:
+ yield elem
+ elif token[0] == "=":
+ value = next()[0]
+ if value[:1] == "'" or value[:1] == '"':
+ value = value[1:-1]
+ else:
+ raise SyntaxError("invalid comparision target")
+ token = next()
+ def select(context, result):
+ for elem in result:
+ if elem.get(key) == value:
+ yield elem
+ if token[0] != "]":
+ raise SyntaxError("invalid attribute predicate")
+ elif not token[0]:
+ tag = token[1]
+ token = next()
+ if token[0] != "]":
+ raise SyntaxError("invalid node predicate")
+ def select(context, result):
+ for elem in result:
+ if elem.find(tag) is not None:
+ yield elem
+ else:
+ raise SyntaxError("invalid predicate")
+ return select
+
+ops = {
+ "": prepare_tag,
+ "*": prepare_star,
+ ".": prepare_dot,
+ "..": prepare_dot_dot,
+ "//": prepare_iter,
+ "[": prepare_predicate,
+ }
+
+_cache = {}
+
+class _SelectorContext:
+ parent_map = None
+ def __init__(self, root):
+ self.root = root
+
+# --------------------------------------------------------------------
+
+##
+# Find first matching object.
+
+def find(elem, path):
+ try:
+ return findall(elem, path).next()
+ except StopIteration:
+ return None
+
+##
+# Find all matching objects.
+
+def findall(elem, path):
+ # compile selector pattern
+ try:
+ selector = _cache[path]
+ except KeyError:
+ if len(_cache) > 100:
+ _cache.clear()
+ if path[:1] == "/":
+ raise SyntaxError("cannot use absolute path on element")
+ stream = iter(xpath_tokenizer(path))
+ next = stream.next; token = next()
+ selector = []
+ while 1:
+ try:
+ selector.append(ops[token[0]](next, token))
+ except StopIteration:
+ raise SyntaxError("invalid path")
+ try:
+ token = next()
+ if token[0] == "/":
+ token = next()
+ except StopIteration:
+ break
+ _cache[path] = selector
+ # execute selector pattern
+ result = [elem]
+ context = _SelectorContext(elem)
+ for select in selector:
+ result = select(context, result)
+ return result
+
+##
+# Find text for first matching object.
+
+def findtext(elem, path, default=None):
+ try:
+ elem = findall(elem, path).next()
+ return elem.text
+ except StopIteration:
+ return default
diff --git a/tests/etree13/ElementTree.py b/tests/etree13/ElementTree.py
new file mode 100644
index 0000000..f459c7f
--- /dev/null
+++ b/tests/etree13/ElementTree.py
@@ -0,0 +1,1546 @@
+#
+# ElementTree
+# $Id$
+#
+# light-weight XML support for Python 2.2 and later.
+#
+# history:
+# 2001-10-20 fl created (from various sources)
+# 2001-11-01 fl return root from parse method
+# 2002-02-16 fl sort attributes in lexical order
+# 2002-04-06 fl TreeBuilder refactoring, added PythonDoc markup
+# 2002-05-01 fl finished TreeBuilder refactoring
+# 2002-07-14 fl added basic namespace support to ElementTree.write
+# 2002-07-25 fl added QName attribute support
+# 2002-10-20 fl fixed encoding in write
+# 2002-11-24 fl changed default encoding to ascii; fixed attribute encoding
+# 2002-11-27 fl accept file objects or file names for parse/write
+# 2002-12-04 fl moved XMLTreeBuilder back to this module
+# 2003-01-11 fl fixed entity encoding glitch for us-ascii
+# 2003-02-13 fl added XML literal factory
+# 2003-02-21 fl added ProcessingInstruction/PI factory
+# 2003-05-11 fl added tostring/fromstring helpers
+# 2003-05-26 fl added ElementPath support
+# 2003-07-05 fl added makeelement factory method
+# 2003-07-28 fl added more well-known namespace prefixes
+# 2003-08-15 fl fixed typo in ElementTree.findtext (Thomas Dartsch)
+# 2003-09-04 fl fall back on emulator if ElementPath is not installed
+# 2003-10-31 fl markup updates
+# 2003-11-15 fl fixed nested namespace bug
+# 2004-03-28 fl added XMLID helper
+# 2004-06-02 fl added default support to findtext
+# 2004-06-08 fl fixed encoding of non-ascii element/attribute names
+# 2004-08-23 fl take advantage of post-2.1 expat features
+# 2004-09-03 fl made Element class visible; removed factory
+# 2005-02-01 fl added iterparse implementation
+# 2005-03-02 fl fixed iterparse support for pre-2.2 versions
+# 2005-11-12 fl added tostringlist/fromstringlist helpers
+# 2006-07-05 fl merged in selected changes from the 1.3 sandbox
+# 2006-07-05 fl removed support for 2.1 and earlier
+# 2007-06-21 fl added deprecation/future warnings
+# 2007-08-25 fl added doctype hook, added parser version attribute etc
+# 2007-08-26 fl added new serializer code (better namespace handling, etc)
+# 2007-08-27 fl warn for broken /tag searches on tree level
+# 2007-09-02 fl added html/text methods to serializer (experimental)
+# 2007-09-05 fl added method argument to tostring/tostringlist
+# 2007-09-06 fl improved error handling
+#
+# Copyright (c) 1999-2007 by Fredrik Lundh. All rights reserved.
+#
+# fredrik at pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2007 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+from __future__ import generators
+
+__all__ = [
+ # public symbols
+ "Comment",
+ "dump",
+ "Element", "ElementTree",
+ "fromstring", "fromstringlist",
+ "iselement", "iterparse",
+ "parse", "ParseError",
+ "PI", "ProcessingInstruction",
+ "QName",
+ "SubElement",
+ "tostring", "tostringlist",
+ "TreeBuilder",
+ "VERSION",
+ "XML",
+ "XMLParser", "XMLTreeBuilder",
+ ]
+
+##
+# The <b>Element</b> type is a flexible container object, designed to
+# store hierarchical data structures in memory. The type can be
+# described as a cross between a list and a dictionary.
+# <p>
+# Each element has a number of properties associated with it:
+# <ul>
+# <li>a <i>tag</i>. This is a string identifying what kind of data
+# this element represents (the element type, in other words).</li>
+# <li>a number of <i>attributes</i>, stored in a Python dictionary.</li>
+# <li>a <i>text</i> string.</li>
+# <li>an optional <i>tail</i> string.</li>
+# <li>a number of <i>child elements</i>, stored in a Python sequence</li>
+# </ul>
+#
+# To create an element instance, use the {@link #Element} constructor
+# or the {@link #SubElement} factory function.
+# <p>
+# The {@link #ElementTree} class can be used to wrap an element
+# structure, and convert it from and to XML.
+##
+
+import sys, re
+
+class _SimpleElementPath(object):
+ # emulate pre-1.2 find/findtext/findall behaviour
+ def find(self, element, tag):
+ for elem in element:
+ if elem.tag == tag:
+ return elem
+ return None
+ def findtext(self, element, tag, default=None):
+ for elem in element:
+ if elem.tag == tag:
+ return elem.text or ""
+ return default
+ def findall(self, element, tag):
+ if tag[:3] == ".//":
+ return element.getiterator(tag[3:])
+ result = []
+ for elem in element:
+ if elem.tag == tag:
+ result.append(elem)
+ return result
+
+try:
+ import ElementPath
+except ImportError:
+ # FIXME: issue warning in this case?
+ ElementPath = _SimpleElementPath()
+
+VERSION = "1.3a2"
+
+class ParseError(SyntaxError):
+ pass
+
+# --------------------------------------------------------------------
+
+##
+# Checks if an object appears to be a valid element object.
+#
+# @param An element instance.
+# @return A true value if this is an element object.
+# @defreturn flag
+
+def iselement(element):
+ # FIXME: not sure about this; might be a better idea to look
+ # for tag/attrib/text attributes
+ return isinstance(element, Element) or hasattr(element, "tag")
+
+##
+# Element class. This class defines the Element interface, and
+# provides a reference implementation of this interface.
+# <p>
+# The element name, attribute names, and attribute values can be
+# either 8-bit ASCII strings or Unicode strings.
+#
+# @param tag The element name.
+# @param attrib An optional dictionary, containing element attributes.
+# @param **extra Additional attributes, given as keyword arguments.
+# @see Element
+# @see SubElement
+# @see Comment
+# @see ProcessingInstruction
+
+class Element(object):
+ # <tag attrib>text<child/>...</tag>tail
+
+ ##
+ # (Attribute) Element tag.
+
+ tag = None
+
+ ##
+ # (Attribute) Element attribute dictionary. Where possible, use
+ # {@link #Element.get},
+ # {@link #Element.set},
+ # {@link #Element.keys}, and
+ # {@link #Element.items} to access
+ # element attributes.
+
+ attrib = None
+
+ ##
+ # (Attribute) Text before first subelement. This is either a
+ # string or the value None, if there was no text.
+
+ text = None
+
+ ##
+ # (Attribute) Text after this element's end tag, but before the
+ # next sibling element's start tag. This is either a string or
+ # the value None, if there was no text.
+
+ tail = None # text after end tag, if any
+
+ def __init__(self, tag, attrib={}, **extra):
+ attrib = attrib.copy()
+ attrib.update(extra)
+ self.tag = tag
+ self.attrib = attrib
+ self._children = []
+
+ def __repr__(self):
+ return "<Element %s at %x>" % (repr(self.tag), id(self))
+
+ ##
+ # Creates a new element object of the same type as this element.
+ #
+ # @param tag Element tag.
+ # @param attrib Element attributes, given as a dictionary.
+ # @return A new element instance.
+
+ def makeelement(self, tag, attrib):
+ return Element(tag, attrib)
+
+ ##
+ # Returns the number of subelements.
+ #
+ # @return The number of subelements.
+
+ def __len__(self):
+ return len(self._children)
+
+ def __nonzero__(self):
+ import warnings
+ warnings.warn(
+ "The behavior of this method will change in future versions. "
+ "Use specific 'len(elem)' or 'elem is not None' test instead.",
+ FutureWarning
+ )
+ return len(self._children) != 0 # emulate old behaviour
+
+ ##
+ # Returns the given subelement.
+ #
+ # @param index What subelement to return.
+ # @return The given subelement.
+ # @exception IndexError If the given element does not exist.
+
+ def __getitem__(self, index):
+ return self._children[index]
+
+ ##
+ # Replaces the given subelement.
+ #
+ # @param index What subelement to replace.
+ # @param element The new element value.
+ # @exception IndexError If the given element does not exist.
+ # @exception AssertionError If element is not a valid object.
+
+ def __setitem__(self, index, element):
+ assert iselement(element)
+ self._children[index] = element
+
+ ##
+ # Deletes the given subelement.
+ #
+ # @param index What subelement to delete.
+ # @exception IndexError If the given element does not exist.
+
+ def __delitem__(self, index):
+ del self._children[index]
+
+ ##
+ # Returns a list containing subelements in the given range.
+ #
+ # @param start The first subelement to return.
+ # @param stop The first subelement that shouldn't be returned.
+ # @return A sequence object containing subelements.
+
+ def __getslice__(self, start, stop):
+ return self._children[start:stop]
+
+ ##
+ # Replaces a number of subelements with elements from a sequence.
+ #
+ # @param start The first subelement to replace.
+ # @param stop The first subelement that shouldn't be replaced.
+ # @param elements A sequence object with zero or more elements.
+ # @exception AssertionError If a sequence member is not a valid object.
+
+ def __setslice__(self, start, stop, elements):
+ for element in elements:
+ assert iselement(element)
+ self._children[start:stop] = list(elements)
+
+ ##
+ # Deletes a number of subelements.
+ #
+ # @param start The first subelement to delete.
+ # @param stop The first subelement to leave in there.
+
+ def __delslice__(self, start, stop):
+ del self._children[start:stop]
+
+ ##
+ # Adds a subelement to the end of this element.
+ #
+ # @param element The element to add.
+ # @exception AssertionError If a sequence member is not a valid object.
+
+ def append(self, element):
+ assert iselement(element)
+ self._children.append(element)
+
+ ##
+ # Appends subelements from a sequence.
+ #
+ # @param elements A sequence object with zero or more elements.
+ # @exception AssertionError If a subelement is not a valid object.
+ # @since 1.3
+
+ def extend(self, elements):
+ for element in elements:
+ assert iselement(element)
+ self._children.extend(elements)
+
+ ##
+ # Inserts a subelement at the given position in this element.
+ #
+ # @param index Where to insert the new subelement.
+ # @exception AssertionError If the element is not a valid object.
+
+ def insert(self, index, element):
+ assert iselement(element)
+ self._children.insert(index, element)
+
+ ##
+ # Removes a matching subelement. Unlike the <b>find</b> methods,
+ # this method compares elements based on identity, not on tag
+ # value or contents.
+ #
+ # @param element What element to remove.
+ # @exception ValueError If a matching element could not be found.
+ # @exception AssertionError If the element is not a valid object.
+
+ def remove(self, element):
+ assert iselement(element)
+ self._children.remove(element)
+
+ ##
+ # (Deprecated) Returns all subelements. The elements are returned
+ # in document order.
+ #
+ # @return A list of subelements.
+ # @defreturn list of Element instances
+
+ def getchildren(self):
+ import warnings
+ warnings.warn(
+ "This method will be removed in future versions. "
+ "Use 'list(elem)' or iteration over elem instead.",
+ DeprecationWarning
+ )
+ return self._children
+
+ ##
+ # Finds the first matching subelement, by tag name or path.
+ #
+ # @param path What element to look for.
+ # @return The first matching element, or None if no element was found.
+ # @defreturn Element or None
+
+ def find(self, path):
+ return ElementPath.find(self, path)
+
+ ##
+ # Finds text for the first matching subelement, by tag name or path.
+ #
+ # @param path What element to look for.
+ # @param default What to return if the element was not found.
+ # @return The text content of the first matching element, or the
+ # default value no element was found. Note that if the element
+ # has is found, but has no text content, this method returns an
+ # empty string.
+ # @defreturn string
+
+ def findtext(self, path, default=None):
+ return ElementPath.findtext(self, path, default)
+
+ ##
+ # Finds all matching subelements, by tag name or path.
+ #
+ # @param path What element to look for.
+ # @return A list or iterator containing all matching elements,
+ # in document order.
+ # @defreturn list of Element instances
+
+ def findall(self, path):
+ return ElementPath.findall(self, path)
+
+ ##
+ # Resets an element. This function removes all subelements, clears
+ # all attributes, and sets the text and tail attributes to None.
+
+ def clear(self):
+ self.attrib.clear()
+ self._children = []
+ self.text = self.tail = None
+
+ ##
+ # Gets an element attribute.
+ #
+ # @param key What attribute to look for.
+ # @param default What to return if the attribute was not found.
+ # @return The attribute value, or the default value, if the
+ # attribute was not found.
+ # @defreturn string or None
+
+ def get(self, key, default=None):
+ return self.attrib.get(key, default)
+
+ ##
+ # Sets an element attribute.
+ #
+ # @param key What attribute to set.
+ # @param value The attribute value.
+
+ def set(self, key, value):
+ self.attrib[key] = value
+
+ ##
+ # Gets a list of attribute names. The names are returned in an
+ # arbitrary order (just like for an ordinary Python dictionary).
+ #
+ # @return A list of element attribute names.
+ # @defreturn list of strings
+
+ def keys(self):
+ return self.attrib.keys()
+
+ ##
+ # Gets element attributes, as a sequence. The attributes are
+ # returned in an arbitrary order.
+ #
+ # @return A list of (name, value) tuples for all attributes.
+ # @defreturn list of (string, string) tuples
+
+ def items(self):
+ return self.attrib.items()
+
+ ##
+ # Creates a tree iterator. The iterator loops over this element
+ # and all subelements, in document order, and returns all elements
+ # with a matching tag.
+ # <p>
+ # If the tree structure is modified during iteration, new or removed
+ # elements may or may not be included. To get a stable set, use the
+ # list() function on the iterator, and loop over the resulting list.
+ #
+ # @param tag What tags to look for (default is to return all elements).
+ # @return An iterator containing all the matching elements.
+ # @defreturn iterator
+
+ def iter(self, tag=None):
+ if tag == "*":
+ tag = None
+ if tag is None or self.tag == tag:
+ yield self
+ for e in self._children:
+ for e in e.iter(tag):
+ yield e
+
+ # compatibility (FIXME: preserve list behaviour too? see below)
+ getiterator = iter
+
+ # def getiterator(self, tag=None):
+ # return list(tag)
+
+ ##
+ # Creates a text iterator. The iterator loops over this element
+ # and all subelements, in document order, and returns all inner
+ # text.
+ #
+ # @return An iterator containing all inner text.
+ # @defreturn iterator
+
+ def itertext(self):
+ if self.text:
+ yield self.text
+ for e in self:
+ for s in e.itertext():
+ yield s
+ if e.tail:
+ yield e.tail
+
+# compatibility
+_Element = _ElementInterface = Element
+
+##
+# Subelement factory. This function creates an element instance, and
+# appends it to an existing element.
+# <p>
+# The element name, attribute names, and attribute values can be
+# either 8-bit ASCII strings or Unicode strings.
+#
+# @param parent The parent element.
+# @param tag The subelement name.
+# @param attrib An optional dictionary, containing element attributes.
+# @param **extra Additional attributes, given as keyword arguments.
+# @return An element instance.
+# @defreturn Element
+
+def SubElement(parent, tag, attrib={}, **extra):
+ attrib = attrib.copy()
+ attrib.update(extra)
+ element = parent.makeelement(tag, attrib)
+ parent.append(element)
+ return element
+
+##
+# Comment element factory. This factory function creates a special
+# element that will be serialized as an XML comment by the standard
+# serializer.
+# <p>
+# The comment string can be either an 8-bit ASCII string or a Unicode
+# string.
+#
+# @param text A string containing the comment string.
+# @return An element instance, representing a comment.
+# @defreturn Element
+
+def Comment(text=None):
+ element = Element(Comment)
+ element.text = text
+ return element
+
+##
+# PI element factory. This factory function creates a special element
+# that will be serialized as an XML processing instruction by the standard
+# serializer.
+#
+# @param target A string containing the PI target.
+# @param text A string containing the PI contents, if any.
+# @return An element instance, representing a PI.
+# @defreturn Element
+
+def ProcessingInstruction(target, text=None):
+ element = Element(ProcessingInstruction)
+ element.text = target
+ if text:
+ element.text = element.text + " " + text
+ return element
+
+PI = ProcessingInstruction
+
+##
+# QName wrapper. This can be used to wrap a QName attribute value, in
+# order to get proper namespace handling on output.
+#
+# @param text A string containing the QName value, in the form {uri}local,
+# or, if the tag argument is given, the URI part of a QName.
+# @param tag Optional tag. If given, the first argument is interpreted as
+# an URI, and this argument is interpreted as a local name.
+# @return An opaque object, representing the QName.
+
+class QName(object):
+ def __init__(self, text_or_uri, tag=None):
+ if tag:
+ text_or_uri = "{%s}%s" % (text_or_uri, tag)
+ self.text = text_or_uri
+ def __str__(self):
+ return self.text
+ def __hash__(self):
+ return hash(self.text)
+ def __cmp__(self, other):
+ if isinstance(other, QName):
+ return cmp(self.text, other.text)
+ return cmp(self.text, other)
+
+# --------------------------------------------------------------------
+
+##
+# ElementTree wrapper class. This class represents an entire element
+# hierarchy, and adds some extra support for serialization to and from
+# standard XML.
+#
+# @param element Optional root element.
+# @keyparam file Optional file handle or file name. If given, the
+# tree is initialized with the contents of this XML file.
+
+class ElementTree(object):
+
+ def __init__(self, element=None, file=None):
+ assert element is None or iselement(element)
+ self._root = element # first node
+ if file:
+ self.parse(file)
+
+ ##
+ # Gets the root element for this tree.
+ #
+ # @return An element instance.
+ # @defreturn Element
+
+ def getroot(self):
+ return self._root
+
+ ##
+ # Replaces the root element for this tree. This discards the
+ # current contents of the tree, and replaces it with the given
+ # element. Use with care.
+ #
+ # @param element An element instance.
+
+ def _setroot(self, element):
+ assert iselement(element)
+ self._root = element
+
+ ##
+ # Loads an external XML document into this element tree.
+ #
+ # @param source A file name or file object.
+ # @keyparam parser An optional parser instance. If not given, the
+ # standard {@link XMLParser} parser is used.
+ # @return The document root element.
+ # @defreturn Element
+
+ def parse(self, source, parser=None):
+ if not hasattr(source, "read"):
+ source = open(source, "rb")
+ if not parser:
+ parser = XMLParser(target=TreeBuilder())
+ while 1:
+ data = source.read(32768)
+ if not data:
+ break
+ parser.feed(data)
+ self._root = parser.close()
+ return self._root
+
+ ##
+ # Creates a tree iterator for the root element. The iterator loops
+ # over all elements in this tree, in document order.
+ #
+ # @param tag What tags to look for (default is to return all elements)
+ # @return An iterator.
+ # @defreturn iterator
+
+ def iter(self, tag=None):
+ assert self._root is not None
+ return self._root.iter(tag)
+
+ getiterator = iter
+
+ ##
+ # Finds the first toplevel element with given tag.
+ # Same as getroot().find(path).
+ #
+ # @param path What element to look for.
+ # @return The first matching element, or None if no element was found.
+ # @defreturn Element or None
+
+ def find(self, path):
+ assert self._root is not None
+ if path[:1] == "/":
+ path = "." + path
+ import warnings
+ warnings.warn(
+ "This search is broken in 1.3 and earlier; if you rely "
+ "on the current behaviour, change it to %r" % path,
+ FutureWarning
+ )
+ return self._root.find(path)
+
+ ##
+ # Finds the element text for the first toplevel element with given
+ # tag. Same as getroot().findtext(path).
+ #
+ # @param path What toplevel element to look for.
+ # @param default What to return if the element was not found.
+ # @return The text content of the first matching element, or the
+ # default value no element was found. Note that if the element
+ # has is found, but has no text content, this method returns an
+ # empty string.
+ # @defreturn string
+
+ def findtext(self, path, default=None):
+ assert self._root is not None
+ if path[:1] == "/":
+ path = "." + path
+ import warnings
+ warnings.warn(
+ "This search is broken in 1.3 and earlier; if you rely "
+ "on the current behaviour, change it to %r" % path,
+ FutureWarning
+ )
+ return self._root.findtext(path, default)
+
+ ##
+ # Finds all toplevel elements with the given tag.
+ # Same as getroot().findall(path).
+ #
+ # @param path What element to look for.
+ # @return A list or iterator containing all matching elements,
+ # in document order.
+ # @defreturn list of Element instances
+
+ def findall(self, path):
+ assert self._root is not None
+ if path[:1] == "/":
+ path = "." + path
+ import warnings
+ warnings.warn(
+ "This search is broken in 1.3 and earlier; if you rely "
+ "on the current behaviour, change it to %r" % path,
+ FutureWarning
+ )
+ return self._root.findall(path)
+
+ ##
+ # Writes the element tree to a file, as XML.
+ #
+ # @param file A file name, or a file object opened for writing.
+ # @keyparam encoding Optional output encoding (default is US-ASCII).
+ # @keyparam method Optional output method ("xml" or "html"; default
+ # is "xml".
+ # @keyparam xml_declaration Controls if an XML declaration should
+ # be added to the file. Use False for never, True for always,
+ # None for only if not US-ASCII or UTF-8. None is default.
+
+ def write(self, file,
+ # keyword arguments
+ encoding="us-ascii",
+ xml_declaration=None,
+ default_namespace=None,
+ method=None):
+ assert self._root is not None
+ if not hasattr(file, "write"):
+ file = open(file, "wb")
+ write = file.write
+ if not method:
+ method = "xml"
+ if not encoding:
+ encoding = "us-ascii"
+ elif xml_declaration or (xml_declaration is None and
+ encoding not in ("utf-8", "us-ascii")):
+ write("<?xml version='1.0' encoding='%s'?>\n" % encoding)
+ if method == "text":
+ _serialize_text(write, self._root, encoding)
+ else:
+ qnames, namespaces = _namespaces(
+ self._root, encoding, default_namespace
+ )
+ if method == "xml":
+ _serialize_xml(
+ write, self._root, encoding, qnames, namespaces
+ )
+ elif method == "html":
+ _serialize_html(
+ write, self._root, encoding, qnames, namespaces
+ )
+ else:
+ raise ValueError("unknown method %r" % method)
+
+# --------------------------------------------------------------------
+# serialization support
+
+def _namespaces(elem, encoding, default_namespace=None):
+ # identify namespaces used in this tree
+
+ # maps qnames to *encoded* prefix:local names
+ qnames = {None: None}
+
+ # maps uri:s to prefixes
+ namespaces = {}
+ if default_namespace:
+ namespaces[default_namespace] = ""
+
+ def encode(text):
+ return text.encode(encoding)
+
+ def add_qname(qname):
+ # calculate serialized qname representation
+ try:
+ if qname[:1] == "{":
+ uri, tag = qname[1:].split("}", 1)
+ prefix = namespaces.get(uri)
+ if prefix is None:
+ prefix = _namespace_map.get(uri)
+ if prefix is None:
+ prefix = "ns%d" % len(namespaces)
+ if prefix != "xml":
+ namespaces[uri] = prefix
+ if prefix:
+ qnames[qname] = encode("%s:%s" % (prefix, tag))
+ else:
+ qnames[qname] = encode(tag) # default element
+ else:
+ if default_namespace:
+ # FIXME: can this be handled in XML 1.0?
+ raise ValueError(
+ "cannot use non-qualified names with "
+ "default_namespace option"
+ )
+ qnames[qname] = encode(qname)
+ except TypeError:
+ _raise_serialization_error(qname)
+
+ # populate qname and namespaces table
+ try:
+ iterate = elem.iter
+ except AttributeError:
+ iterate = elem.getiterator # cET compatibility
+ for elem in iterate():
+ tag = elem.tag
+ if isinstance(tag, QName) and tag.text not in qnames:
+ add_qname(tag.text)
+ elif isinstance(tag, basestring):
+ if tag not in qnames:
+ add_qname(tag)
+ elif tag is not None and tag is not Comment and tag is not PI:
+ _raise_serialization_error(tag)
+ for key, value in elem.items():
+ if isinstance(key, QName):
+ key = key.text
+ if key not in qnames:
+ add_qname(key)
+ if isinstance(value, QName) and value.text not in qnames:
+ add_qname(value.text)
+ text = elem.text
+ if isinstance(text, QName) and text.text not in qnames:
+ add_qname(text.text)
+ return qnames, namespaces
+
+def _serialize_xml(write, elem, encoding, qnames, namespaces):
+ tag = elem.tag
+ text = elem.text
+ if tag is Comment:
+ write("<!--%s-->" % _escape_cdata(text, encoding))
+ elif tag is ProcessingInstruction:
+ write("<?%s?>" % _escape_cdata(text, encoding))
+ else:
+ tag = qnames[tag]
+ if tag is None:
+ if text:
+ write(_escape_cdata(text, encoding))
+ for e in elem:
+ _serialize_xml(write, e, encoding, qnames, None)
+ else:
+ write("<" + tag)
+ items = elem.items()
+ if items or namespaces:
+ items.sort() # lexical order
+ for k, v in items:
+ if isinstance(k, QName):
+ k = k.text
+ if isinstance(v, QName):
+ v = qnames[v.text]
+ else:
+ v = _escape_attrib(v, encoding)
+ write(" %s=\"%s\"" % (qnames[k], v))
+ if namespaces:
+ items = namespaces.items()
+ items.sort(key=lambda x: x[1]) # sort on prefix
+ for v, k in items:
+ if k:
+ k = ":" + k
+ write(" xmlns%s=\"%s\"" % (
+ k.encode(encoding),
+ _escape_attrib(v, encoding)
+ ))
+ if text or len(elem):
+ write(">")
+ if text:
+ write(_escape_cdata(text, encoding))
+ for e in elem:
+ _serialize_xml(write, e, encoding, qnames, None)
+ write("</" + tag + ">")
+ else:
+ write(" />")
+ if elem.tail:
+ write(_escape_cdata(elem.tail, encoding))
+
+HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",
+ "img", "input", "isindex", "link", "meta" "param")
+
+try:
+ HTML_EMPTY = set(HTML_EMPTY)
+except NameError:
+ pass
+
+def _serialize_html(write, elem, encoding, qnames, namespaces):
+ tag = elem.tag
+ text = elem.text
+ if tag is Comment:
+ write("<!--%s-->" % _escape_cdata(text, encoding))
+ elif tag is ProcessingInstruction:
+ write("<?%s?>" % _escape_cdata(text, encoding))
+ else:
+ tag = qnames[tag]
+ if tag is None:
+ if text:
+ write(_escape_cdata(text, encoding))
+ for e in elem:
+ _serialize_html(write, e, encoding, qnames, None)
+ else:
+ write("<" + tag)
+ items = elem.items()
+ if items or namespaces:
+ items.sort() # lexical order
+ for k, v in items:
+ if isinstance(k, QName):
+ k = k.text
+ if isinstance(v, QName):
+ v = qnames[v.text]
+ else:
+ v = _escape_attrib_html(v, encoding)
+ # FIXME: handle boolean attributes
+ write(" %s=\"%s\"" % (qnames[k], v))
+ if namespaces:
+ items = namespaces.items()
+ items.sort(key=lambda x: x[1]) # sort on prefix
+ for v, k in items:
+ if k:
+ k = ":" + k
+ write(" xmlns%s=\"%s\"" % (
+ k.encode(encoding),
+ _escape_attrib(v, encoding)
+ ))
+ write(">")
+ tag = tag.lower()
+ if text:
+ if tag == "script" or tag == "style":
+ write(_encode(text, encoding))
+ else:
+ write(_escape_cdata(text, encoding))
+ for e in elem:
+ _serialize_html(write, e, encoding, qnames, None)
+ if tag not in HTML_EMPTY:
+ write("</" + tag + ">")
+ if elem.tail:
+ write(_escape_cdata(elem.tail, encoding))
+
+def _serialize_text(write, elem, encoding):
+ for part in elem.itertext():
+ write(part.encode(encoding))
+ if elem.tail:
+ write(elem.tail.encode(encoding))
+
+##
+# Registers a namespace prefix. The registry is global, and any
+# existing mapping for either the given prefix or the namespace URI
+# will be removed.
+#
+# @param prefix Namespace prefix.
+# @param uri Namespace uri. Tags and attributes in this namespace
+# will be serialized with the given prefix, if at all possible.
+# @raise ValueError If the prefix is reserved, or is otherwise
+# invalid.
+
+def register_namespace(prefix, uri):
+ if re.match("ns\d+$", prefix):
+ raise ValueError("Prefix format reserved for internal use")
+ for k, v in _namespace_map.items():
+ if k == uri or v == prefix:
+ del _namespace_map[k]
+ _namespace_map[uri] = prefix
+
+_namespace_map = {
+ # "well-known" namespace prefixes
+ "http://www.w3.org/XML/1998/namespace": "xml",
+ "http://www.w3.org/1999/xhtml": "html",
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
+ "http://schemas.xmlsoap.org/wsdl/": "wsdl",
+ # xml schema
+ "http://www.w3.org/2001/XMLSchema": "xs",
+ "http://www.w3.org/2001/XMLSchema-instance": "xsi",
+ # dublic core
+ "http://purl.org/dc/elements/1.1/": "dc",
+}
+
+def _raise_serialization_error(text):
+ raise TypeError(
+ "cannot serialize %r (type %s)" % (text, type(text).__name__)
+ )
+
+def _encode(text, encoding):
+ try:
+ return text.encode(encoding, "xmlcharrefreplace")
+ except (TypeError, AttributeError):
+ _raise_serialization_error(text)
+
+def _escape_cdata(text, encoding):
+ # escape character data
+ try:
+ # it's worth avoiding do-nothing calls for strings that are
+ # shorter than 500 character, or so. assume that's, by far,
+ # the most common case in most applications.
+ if "&" in text:
+ text = text.replace("&", "&")
+ if "<" in text:
+ text = text.replace("<", "<")
+ if ">" in text:
+ text = text.replace(">", ">")
+ return text.encode(encoding, "xmlcharrefreplace")
+ except (TypeError, AttributeError):
+ _raise_serialization_error(text)
+
+def _escape_attrib(text, encoding):
+ # escape attribute value
+ try:
+ if "&" in text:
+ text = text.replace("&", "&")
+ if "<" in text:
+ text = text.replace("<", "<")
+ if ">" in text:
+ text = text.replace(">", ">")
+ if "\"" in text:
+ text = text.replace("\"", """)
+ if "\n" in text:
+ text = text.replace("\n", "
")
+ return text.encode(encoding, "xmlcharrefreplace")
+ except (TypeError, AttributeError):
+ _raise_serialization_error(text)
+
+def _escape_attrib_html(text, encoding):
+ # escape attribute value
+ try:
+ if "&" in text:
+ text = text.replace("&", "&")
+ if ">" in text:
+ text = text.replace(">", ">")
+ if "\"" in text:
+ text = text.replace("\"", """)
+ return text.encode(encoding, "xmlcharrefreplace")
+ except (TypeError, AttributeError):
+ _raise_serialization_error(text)
+
+# --------------------------------------------------------------------
+
+##
+# Generates a string representation of an XML element, including all
+# subelements.
+#
+# @param element An Element instance.
+# @return An encoded string containing the XML data.
+# @defreturn string
+
+def tostring(element, encoding=None, method=None):
+ class dummy:
+ pass
+ data = []
+ file = dummy()
+ file.write = data.append
+ ElementTree(element).write(file, encoding, method=method)
+ return "".join(data)
+
+##
+# Generates a string representation of an XML element, including all
+# subelements. The string is returned as a sequence of string fragments.
+#
+# @param element An Element instance.
+# @return A sequence object containing the XML data.
+# @defreturn sequence
+# @since 1.3
+
+def tostringlist(element, encoding=None):
+ class dummy:
+ pass
+ data = []
+ file = dummy()
+ file.write = data.append
+ ElementTree(element).write(file, encoding)
+ # FIXME: merge small fragments into larger parts
+ return data
+
+##
+# Writes an element tree or element structure to sys.stdout. This
+# function should be used for debugging only.
+# <p>
+# The exact output format is implementation dependent. In this
+# version, it's written as an ordinary XML file.
+#
+# @param elem An element tree or an individual element.
+
+def dump(elem):
+ # debugging
+ if not isinstance(elem, ElementTree):
+ elem = ElementTree(elem)
+ elem.write(sys.stdout)
+ tail = elem.getroot().tail
+ if not tail or tail[-1] != "\n":
+ sys.stdout.write("\n")
+
+# --------------------------------------------------------------------
+# parsing
+
+##
+# Parses an XML document into an element tree.
+#
+# @param source A filename or file object containing XML data.
+# @param parser An optional parser instance. If not given, the
+# standard {@link XMLParser} parser is used.
+# @return An ElementTree instance
+
+def parse(source, parser=None):
+ tree = ElementTree()
+ tree.parse(source, parser)
+ return tree
+
+##
+# Parses an XML document into an element tree incrementally, and reports
+# what's going on to the user.
+#
+# @param source A filename or file object containing XML data.
+# @param events A list of events to report back. If omitted, only "end"
+# events are reported.
+# @param parser An optional parser instance. If not given, the
+# standard {@link XMLParser} parser is used.
+# @return A (event, elem) iterator.
+
+def iterparse(source, events=None, parser=None):
+ if not hasattr(source, "read"):
+ source = open(source, "rb")
+ if not parser:
+ parser = XMLParser(target=TreeBuilder())
+ return _IterParseIterator(source, events, parser)
+
+class _IterParseIterator(object):
+
+ def __init__(self, source, events, parser):
+ self._file = source
+ self._events = []
+ self._index = 0
+ self.root = self._root = None
+ self._parser = parser
+ # wire up the parser for event reporting
+ parser = self._parser._parser
+ append = self._events.append
+ if events is None:
+ events = ["end"]
+ for event in events:
+ if event == "start":
+ try:
+ parser.ordered_attributes = 1
+ parser.specified_attributes = 1
+ def handler(tag, attrib_in, event=event, append=append,
+ start=self._parser._start_list):
+ append((event, start(tag, attrib_in)))
+ parser.StartElementHandler = handler
+ except AttributeError:
+ def handler(tag, attrib_in, event=event, append=append,
+ start=self._parser._start):
+ append((event, start(tag, attrib_in)))
+ parser.StartElementHandler = handler
+ elif event == "end":
+ def handler(tag, event=event, append=append,
+ end=self._parser._end):
+ append((event, end(tag)))
+ parser.EndElementHandler = handler
+ elif event == "start-ns":
+ def handler(prefix, uri, event=event, append=append):
+ try:
+ uri = uri.encode("ascii")
+ except UnicodeError:
+ pass
+ append((event, (prefix or "", uri)))
+ parser.StartNamespaceDeclHandler = handler
+ elif event == "end-ns":
+ def handler(prefix, event=event, append=append):
+ append((event, None))
+ parser.EndNamespaceDeclHandler = handler
+
+ def next(self):
+ while 1:
+ try:
+ item = self._events[self._index]
+ except IndexError:
+ if self._parser is None:
+ self.root = self._root
+ raise StopIteration
+ # load event buffer
+ del self._events[:]
+ self._index = 0
+ data = self._file.read(16384)
+ if data:
+ self._parser.feed(data)
+ else:
+ self._root = self._parser.close()
+ self._parser = None
+ else:
+ self._index = self._index + 1
+ return item
+
+ def __iter__(self):
+ return self
+
+##
+# Parses an XML document from a string constant. This function can
+# be used to embed "XML literals" in Python code.
+#
+# @param source A string containing XML data.
+# @param parser An optional parser instance. If not given, the
+# standard {@link XMLParser} parser is used.
+# @return An Element instance.
+# @defreturn Element
+
+def XML(text, parser=None):
+ if not parser:
+ parser = XMLParser(target=TreeBuilder())
+ parser.feed(text)
+ return parser.close()
+
+##
+# Parses an XML document from a string constant, and also returns
+# a dictionary which maps from element id:s to elements.
+#
+# @param source A string containing XML data.
+# @param parser An optional parser instance. If not given, the
+# standard {@link XMLParser} parser is used.
+# @return A tuple containing an Element instance and a dictionary.
+# @defreturn (Element, dictionary)
+
+def XMLID(text, parser=None):
+ if not parser:
+ parser = XMLParser(target=TreeBuilder())
+ parser.feed(text)
+ tree = parser.close()
+ ids = {}
+ for elem in tree.getiterator():
+ id = elem.get("id")
+ if id:
+ ids[id] = elem
+ return tree, ids
+
+##
+# Parses an XML document from a string constant. Same as {@link #XML}.
+#
+# @def fromstring(text)
+# @param source A string containing XML data.
+# @return An Element instance.
+# @defreturn Element
+
+fromstring = XML
+
+##
+# Parses an XML document from a sequence of string fragments.
+#
+# @param sequence A list or other sequence containing XML data fragments.
+# @param parser An optional parser instance. If not given, the
+# standard {@link XMLParser} parser is used.
+# @return An Element instance.
+# @defreturn Element
+# @since 1.3
+
+def fromstringlist(sequence, parser=None):
+ if not parser:
+ parser = XMLParser(target=TreeBuilder())
+ for text in sequence:
+ parser.feed(text)
+ return parser.close()
+
+# --------------------------------------------------------------------
+
+##
+# Generic element structure builder. This builder converts a sequence
+# of {@link #TreeBuilder.start}, {@link #TreeBuilder.data}, and {@link
+# #TreeBuilder.end} method calls to a well-formed element structure.
+# <p>
+# You can use this class to build an element structure using a custom XML
+# parser, or a parser for some other XML-like format.
+#
+# @param element_factory Optional element factory. This factory
+# is called to create new Element instances, as necessary.
+
+class TreeBuilder(object):
+
+ def __init__(self, element_factory=None):
+ self._data = [] # data collector
+ self._elem = [] # element stack
+ self._last = None # last element
+ self._tail = None # true if we're after an end tag
+ if element_factory is None:
+ element_factory = Element
+ self._factory = element_factory
+
+ ##
+ # Flushes the builder buffers, and returns the toplevel document
+ # element.
+ #
+ # @return An Element instance.
+ # @defreturn Element
+
+ def close(self):
+ assert len(self._elem) == 0, "missing end tags"
+ assert self._last != None, "missing toplevel element"
+ return self._last
+
+ def _flush(self):
+ if self._data:
+ if self._last is not None:
+ text = "".join(self._data)
+ if self._tail:
+ assert self._last.tail is None, "internal error (tail)"
+ self._last.tail = text
+ else:
+ assert self._last.text is None, "internal error (text)"
+ self._last.text = text
+ self._data = []
+
+ ##
+ # Adds text to the current element.
+ #
+ # @param data A string. This should be either an 8-bit string
+ # containing ASCII text, or a Unicode string.
+
+ def data(self, data):
+ self._data.append(data)
+
+ ##
+ # Opens a new element.
+ #
+ # @param tag The element name.
+ # @param attrib A dictionary containing element attributes.
+ # @return The opened element.
+ # @defreturn Element
+
+ def start(self, tag, attrs):
+ self._flush()
+ self._last = elem = self._factory(tag, attrs)
+ if self._elem:
+ self._elem[-1].append(elem)
+ self._elem.append(elem)
+ self._tail = 0
+ return elem
+
+ ##
+ # Closes the current element.
+ #
+ # @param tag The element name.
+ # @return The closed element.
+ # @defreturn Element
+
+ def end(self, tag):
+ self._flush()
+ self._last = self._elem.pop()
+ assert self._last.tag == tag,\
+ "end tag mismatch (expected %s, got %s)" % (
+ self._last.tag, tag)
+ self._tail = 1
+ return self._last
+
+##
+# Element structure builder for XML source data, based on the
+# <b>expat</b> parser.
+#
+# @keyparam target Target object. If omitted, the builder uses an
+# instance of the standard {@link #TreeBuilder} class.
+# @keyparam html Predefine HTML entities. This flag is not supported
+# by the current implementation.
+# @keyparam encoding Optional encoding. If given, the value overrides
+# the encoding specified in the XML file.
+# @see #ElementTree
+# @see #TreeBuilder
+
+class XMLParser(object):
+
+ def __init__(self, html=0, target=None, encoding=None):
+ try:
+ from xml.parsers import expat
+ except ImportError:
+ try:
+ import pyexpat; expat = pyexpat
+ except ImportError:
+ raise ImportError(
+ "No module named expat; use SimpleXMLTreeBuilder instead"
+ )
+ parser = expat.ParserCreate(encoding, "}")
+ if target is None:
+ target = TreeBuilder()
+ # underscored names are provided for compatibility only
+ self.parser = self._parser = parser
+ self.target = self._target = target
+ self._error = expat.error
+ self._names = {} # name memo cache
+ # callbacks
+ parser.DefaultHandlerExpand = self._default
+ parser.StartElementHandler = self._start
+ parser.EndElementHandler = self._end
+ parser.CharacterDataHandler = self._data
+ # let expat do the buffering, if supported
+ try:
+ self._parser.buffer_text = 1
+ except AttributeError:
+ pass
+ # use new-style attribute handling, if supported
+ try:
+ self._parser.ordered_attributes = 1
+ self._parser.specified_attributes = 1
+ parser.StartElementHandler = self._start_list
+ except AttributeError:
+ pass
+ self._doctype = None
+ self.entity = {}
+ try:
+ self.version = "Expat %d.%d.%d" % expat.version_info
+ except AttributeError:
+ pass # unknown
+
+ def _raiseerror(self, value):
+ err = ParseError(value)
+ err.code = value.code
+ err.position = value.lineno, value.offset
+ raise err
+
+ if sys.version_info >= (3, 0):
+ def _fixtext(self, text):
+ return text
+ else:
+ def _fixtext(self, text):
+ # convert text string to ascii, if possible
+ try:
+ return text.encode("ascii")
+ except UnicodeError:
+ return text
+
+ def _fixname(self, key):
+ # expand qname, and convert name string to ascii, if possible
+ try:
+ name = self._names[key]
+ except KeyError:
+ name = key
+ if "}" in name:
+ name = "{" + name
+ self._names[key] = name = self._fixtext(name)
+ return name
+
+ def _start(self, tag, attrib_in):
+ fixname = self._fixname
+ fixtext = self._fixtext
+ tag = fixname(tag)
+ attrib = {}
+ for key, value in attrib_in.items():
+ attrib[fixname(key)] = fixtext(value)
+ return self.target.start(tag, attrib)
+
+ def _start_list(self, tag, attrib_in):
+ fixname = self._fixname
+ fixtext = self._fixtext
+ tag = fixname(tag)
+ attrib = {}
+ if attrib_in:
+ for i in range(0, len(attrib_in), 2):
+ attrib[fixname(attrib_in[i])] = fixtext(attrib_in[i+1])
+ return self.target.start(tag, attrib)
+
+ def _data(self, text):
+ return self.target.data(self._fixtext(text))
+
+ def _end(self, tag):
+ return self.target.end(self._fixname(tag))
+
+ def _default(self, text):
+ prefix = text[:1]
+ if prefix == "&":
+ # deal with undefined entities
+ try:
+ self.target.data(self.entity[text[1:-1]])
+ except KeyError:
+ from xml.parsers import expat
+ err = expat.error(
+ "undefined entity %s: line %d, column %d" %
+ (text, self._parser.ErrorLineNumber,
+ self._parser.ErrorColumnNumber)
+ )
+ err.code = 11 # XML_ERROR_UNDEFINED_ENTITY
+ err.lineno = self._parser.ErrorLineNumber
+ err.offset = self._parser.ErrorColumnNumber
+ raise err
+ elif prefix == "<" and text[:9] == "<!DOCTYPE":
+ self._doctype = [] # inside a doctype declaration
+ elif self._doctype is not None:
+ # parse doctype contents
+ if prefix == ">":
+ self._doctype = None
+ return
+ text = text.strip()
+ if not text:
+ return
+ self._doctype.append(text)
+ n = len(self._doctype)
+ if n > 2:
+ type = self._doctype[1]
+ if type == "PUBLIC" and n == 4:
+ name, type, pubid, system = self._doctype
+ elif type == "SYSTEM" and n == 3:
+ name, type, system = self._doctype
+ pubid = None
+ else:
+ return
+ if pubid:
+ pubid = pubid[1:-1]
+ if hasattr(self.target, "doctype"):
+ self.target.doctype(name, pubid, system[1:-1])
+ self._doctype = None
+
+ ##
+ # Feeds data to the parser.
+ #
+ # @param data Encoded data.
+
+ def feed(self, data):
+ try:
+ self._parser.Parse(data, 0)
+ except self._error, v:
+ self._raiseerror(v)
+
+ ##
+ # Finishes feeding data to the parser.
+ #
+ # @return An element structure.
+ # @defreturn Element
+
+ def close(self):
+ try:
+ self._parser.Parse("", 1) # end of data
+ except self._error, v:
+ self._raiseerror(v)
+ tree = self.target.close()
+ del self.target, self._parser # get rid of circular references
+ return tree
+
+# compatibility
+XMLTreeBuilder = XMLParser
diff --git a/tests/etree13/HTMLTreeBuilder.py b/tests/etree13/HTMLTreeBuilder.py
new file mode 100644
index 0000000..4c5a24f
--- /dev/null
+++ b/tests/etree13/HTMLTreeBuilder.py
@@ -0,0 +1,230 @@
+#
+# ElementTree
+# $Id$
+#
+# a simple tree builder, for HTML input
+#
+# history:
+# 2002-04-06 fl created
+# 2002-04-07 fl ignore IMG and HR end tags
+# 2002-04-07 fl added support for 1.5.2 and later
+# 2003-04-13 fl added HTMLTreeBuilder alias
+# 2004-12-02 fl don't feed non-ASCII charrefs/entities as 8-bit strings
+# 2004-12-05 fl don't feed non-ASCII CDATA as 8-bit strings
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh. All rights reserved.
+#
+# fredrik at pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2007 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Tools to build element trees from HTML files.
+##
+
+import htmlentitydefs
+import re, string, sys
+import mimetools, StringIO
+
+import ElementTree
+
+AUTOCLOSE = "p", "li", "tr", "th", "td", "head", "body"
+IGNOREEND = "img", "hr", "meta", "link", "br"
+
+if sys.version[:3] == "1.5":
+ is_not_ascii = re.compile(r"[\x80-\xff]").search # 1.5.2
+else:
+ is_not_ascii = re.compile(eval(r'u"[\u0080-\uffff]"')).search
+
+try:
+ from HTMLParser import HTMLParser
+except ImportError:
+ from sgmllib import SGMLParser
+ # hack to use sgmllib's SGMLParser to emulate 2.2's HTMLParser
+ class HTMLParser(SGMLParser):
+ # the following only works as long as this class doesn't
+ # provide any do, start, or end handlers
+ def unknown_starttag(self, tag, attrs):
+ self.handle_starttag(tag, attrs)
+ def unknown_endtag(self, tag):
+ self.handle_endtag(tag)
+
+##
+# ElementTree builder for HTML source code. This builder converts an
+# HTML document or fragment to an ElementTree.
+# <p>
+# The parser is relatively picky, and requires balanced tags for most
+# elements. However, elements belonging to the following group are
+# automatically closed: P, LI, TR, TH, and TD. In addition, the
+# parser automatically inserts end tags immediately after the start
+# tag, and ignores any end tags for the following group: IMG, HR,
+# META, and LINK.
+#
+# @keyparam builder Optional builder object. If omitted, the parser
+# uses the standard <b>elementtree</b> builder.
+# @keyparam encoding Optional character encoding, if known. If omitted,
+# the parser looks for META tags inside the document. If no tags
+# are found, the parser defaults to ISO-8859-1. Note that if your
+# document uses a non-ASCII compatible encoding, you must decode
+# the document before parsing.
+#
+# @see elementtree.ElementTree
+
+class HTMLTreeBuilder(HTMLParser):
+
+ # FIXME: shouldn't this class be named Parser, not Builder?
+
+ def __init__(self, builder=None, encoding=None):
+ self.__stack = []
+ if builder is None:
+ builder = ElementTree.TreeBuilder()
+ self.__builder = builder
+ self.encoding = encoding or "iso-8859-1"
+ HTMLParser.__init__(self)
+
+ ##
+ # Flushes parser buffers, and return the root element.
+ #
+ # @return An Element instance.
+
+ def close(self):
+ HTMLParser.close(self)
+ return self.__builder.close()
+
+ ##
+ # (Internal) Handles start tags.
+
+ def handle_starttag(self, tag, attrs):
+ if tag == "meta":
+ # look for encoding directives
+ http_equiv = content = None
+ for k, v in attrs:
+ if k == "http-equiv":
+ http_equiv = string.lower(v)
+ elif k == "content":
+ content = v
+ if http_equiv == "content-type" and content:
+ # use mimetools to parse the http header
+ header = mimetools.Message(
+ StringIO.StringIO("%s: %s\n\n" % (http_equiv, content))
+ )
+ encoding = header.getparam("charset")
+ if encoding:
+ self.encoding = encoding
+ if tag in AUTOCLOSE:
+ if self.__stack and self.__stack[-1] == tag:
+ self.handle_endtag(tag)
+ self.__stack.append(tag)
+ attrib = {}
+ if attrs:
+ for k, v in attrs:
+ attrib[string.lower(k)] = v
+ self.__builder.start(tag, attrib)
+ if tag in IGNOREEND:
+ self.__stack.pop()
+ self.__builder.end(tag)
+
+ ##
+ # (Internal) Handles end tags.
+
+ def handle_endtag(self, tag):
+ if tag in IGNOREEND:
+ return
+ lasttag = self.__stack.pop()
+ if tag != lasttag and lasttag in AUTOCLOSE:
+ self.handle_endtag(lasttag)
+ self.__builder.end(tag)
+
+ ##
+ # (Internal) Handles character references.
+
+ def handle_charref(self, char):
+ if char[:1] == "x":
+ char = int(char[1:], 16)
+ else:
+ char = int(char)
+ if 0 <= char < 128:
+ self.__builder.data(chr(char))
+ else:
+ self.__builder.data(unichr(char))
+
+ ##
+ # (Internal) Handles entity references.
+
+ def handle_entityref(self, name):
+ entity = htmlentitydefs.entitydefs.get(name)
+ if entity:
+ if len(entity) == 1:
+ entity = ord(entity)
+ else:
+ entity = int(entity[2:-1])
+ if 0 <= entity < 128:
+ self.__builder.data(chr(entity))
+ else:
+ self.__builder.data(unichr(entity))
+ else:
+ self.unknown_entityref(name)
+
+ ##
+ # (Internal) Handles character data.
+
+ def handle_data(self, data):
+ if isinstance(data, type('')) and is_not_ascii(data):
+ # convert to unicode, but only if necessary
+ data = unicode(data, self.encoding, "ignore")
+ self.__builder.data(data)
+
+ ##
+ # (Hook) Handles unknown entity references. The default action
+ # is to ignore unknown entities.
+
+ def unknown_entityref(self, name):
+ pass # ignore by default; override if necessary
+
+##
+# An alias for the <b>HTMLTreeBuilder</b> class.
+
+TreeBuilder = HTMLTreeBuilder
+
+##
+# Parse an HTML document or document fragment.
+#
+# @param source A filename or file object containing HTML data.
+# @param encoding Optional character encoding, if known. If omitted,
+# the parser looks for META tags inside the document. If no tags
+# are found, the parser defaults to ISO-8859-1.
+# @return An ElementTree instance
+
+def parse(source, encoding=None):
+ return ElementTree.parse(source, HTMLTreeBuilder(encoding=encoding))
+
+if __name__ == "__main__":
+ import sys
+ ElementTree.dump(parse(open(sys.argv[1])))
diff --git a/tests/etree13/__init__.py b/tests/etree13/__init__.py
new file mode 100644
index 0000000..1bcba1c
--- /dev/null
+++ b/tests/etree13/__init__.py
@@ -0,0 +1,30 @@
+# $Id$
+# elementtree package
+
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2007 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
diff --git a/tests/path.py b/tests/path.py
new file mode 100755
index 0000000..fa90a6f
--- /dev/null
+++ b/tests/path.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ path
+ ~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import os
+import sys
+import shutil
+from codecs import open
+
+
+FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding()
+
+
+class path(unicode):
+ """
+ Represents a path which behaves like a string.
+ """
+ if sys.version_info < (3, 0):
+ def __new__(cls, s, encoding=FILESYSTEMENCODING, errors='strict'):
+ if isinstance(s, str):
+ s = s.decode(encoding, errors)
+ return unicode.__new__(cls, s)
+ return unicode.__new__(cls, s)
+
+ @property
+ def parent(self):
+ """
+ The name of the directory the file or directory is in.
+ """
+ return self.__class__(os.path.dirname(self))
+
+ def abspath(self):
+ """
+ Returns the absolute path.
+ """
+ return self.__class__(os.path.abspath(self))
+
+ def isabs(self):
+ """
+ Returns ``True`` if the path is absolute.
+ """
+ return os.path.isabs(self)
+
+ def isdir(self):
+ """
+ Returns ``True`` if the path is a directory.
+ """
+ return os.path.isdir(self)
+
+ def isfile(self):
+ """
+ Returns ``True`` if the path is a file.
+ """
+ return os.path.isfile(self)
+
+ def islink(self):
+ """
+ Returns ``True`` if the path is a symbolic link.
+ """
+ return os.path.islink(self)
+
+ def ismount(self):
+ """
+ Returns ``True`` if the path is a mount point.
+ """
+ return os.path.ismount(self)
+
+ def rmtree(self, ignore_errors=False, onerror=None):
+ """
+ Removes the file or directory and any files or directories it may
+ contain.
+
+ :param ignore_errors:
+ If ``True`` errors are silently ignored, otherwise an exception
+ is raised in case an error occurs.
+
+ :param onerror:
+ A callback which gets called with the arguments `func`, `path` and
+ `exc_info`. `func` is one of :func:`os.listdir`, :func:`os.remove`
+ or :func:`os.rmdir`. `path` is the argument to the function which
+ caused it to fail and `exc_info` is a tuple as returned by
+ :func:`sys.exc_info`.
+ """
+ shutil.rmtree(self, ignore_errors=ignore_errors, onerror=onerror)
+
+ def copytree(self, destination, symlinks=False):
+ """
+ Recursively copy a directory to the given `destination`. If the given
+ `destination` does not exist it will be created.
+
+ :param symlinks:
+ If ``True`` symbolic links in the source tree result in symbolic
+ links in the destination tree otherwise the contents of the files
+ pointed to by the symbolic links are copied.
+ """
+ shutil.copytree(self, destination, symlinks=symlinks)
+
+ def movetree(self, destination):
+ """
+ Recursively move the file or directory to the given `destination`
+ similar to the Unix "mv" command.
+
+ If the `destination` is a file it may be overwritten depending on the
+ :func:`os.rename` semantics.
+ """
+ shutil.move(self, destination)
+
+ move = movetree
+
+ def unlink(self):
+ """
+ Removes a file.
+ """
+ os.unlink(self)
+
+ def write_text(self, text, **kwargs):
+ """
+ Writes the given `text` to the file.
+ """
+ f = open(self, 'w', **kwargs)
+ try:
+ f.write(text)
+ finally:
+ f.close()
+
+ def text(self, **kwargs):
+ """
+ Returns the text in the file.
+ """
+ f = open(self, mode='U', **kwargs)
+ try:
+ return f.read()
+ finally:
+ f.close()
+
+ def bytes(self):
+ """
+ Returns the bytes in the file.
+ """
+ f = open(self, mode='rb')
+ try:
+ return f.read()
+ finally:
+ f.close()
+
+ def write_bytes(self, bytes, append=False):
+ """
+ Writes the given `bytes` to the file.
+
+ :param append:
+ If ``True`` given `bytes` are added at the end of the file.
+ """
+ if append:
+ mode = 'ab'
+ else:
+ mode = 'wb'
+ f = open(self, mode=mode)
+ try:
+ f.write(bytes)
+ finally:
+ f.close()
+
+ def exists(self):
+ """
+ Returns ``True`` if the path exist.
+ """
+ return os.path.exists(self)
+
+ def lexists(self):
+ """
+ Returns ``True`` if the path exists unless it is a broken symbolic
+ link.
+ """
+ return os.path.lexists(self)
+
+ def makedirs(self, mode=0777):
+ """
+ Recursively create directories.
+ """
+ os.makedirs(self, mode)
+
+ def joinpath(self, *args):
+ """
+ Joins the path with the argument given and returns the result.
+ """
+ return self.__class__(os.path.join(self, *map(self.__class__, args)))
+
+ __div__ = __truediv__ = joinpath
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, unicode.__repr__(self))
diff --git a/tests/root/Makefile b/tests/root/Makefile
new file mode 100644
index 0000000..7954bc7
--- /dev/null
+++ b/tests/root/Makefile
@@ -0,0 +1,70 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " pickle to make pickle files (usable by e.g. sphinx-web)"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " changes to make an overview over all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+
+clean:
+ rm -rf _build/*
+
+html:
+ mkdir -p _build/html _build/doctrees
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
+ @echo
+ @echo "Build finished. The HTML pages are in _build/html."
+
+pickle:
+ mkdir -p _build/pickle _build/doctrees
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files or run"
+ @echo " sphinx-web _build/pickle"
+ @echo "to start the sphinx-web server."
+
+web: pickle
+
+htmlhelp:
+ mkdir -p _build/htmlhelp _build/doctrees
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in _build/htmlhelp."
+
+latex:
+ mkdir -p _build/latex _build/doctrees
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in _build/latex."
+ @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+ "run these through (pdf)latex."
+
+changes:
+ mkdir -p _build/changes _build/doctrees
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
+ @echo
+ @echo "The overview file is in _build/changes."
+
+linkcheck:
+ mkdir -p _build/linkcheck _build/doctrees
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in _build/linkcheck/output.txt."
diff --git a/tests/root/_static/README b/tests/root/_static/README
new file mode 100644
index 0000000..9e1ec35
--- /dev/null
+++ b/tests/root/_static/README
@@ -0,0 +1 @@
+This whole directory is there to test html_static_path.
diff --git a/tests/root/_static/excluded.css b/tests/root/_static/excluded.css
new file mode 100644
index 0000000..03c941a
--- /dev/null
+++ b/tests/root/_static/excluded.css
@@ -0,0 +1 @@
+/* This file should be excluded from being copied over */
diff --git a/tests/root/_static/subdir/foo.css b/tests/root/_static/subdir/foo.css
new file mode 100644
index 0000000..9427981
--- /dev/null
+++ b/tests/root/_static/subdir/foo.css
@@ -0,0 +1 @@
+/* Stub file */
diff --git a/tests/root/_templates/contentssb.html b/tests/root/_templates/contentssb.html
new file mode 100644
index 0000000..9951d3c
--- /dev/null
+++ b/tests/root/_templates/contentssb.html
@@ -0,0 +1,2 @@
+{# sidebar only for contents document #}
+<h4>Contents sidebar</h4>
\ No newline at end of file
diff --git a/tests/root/_templates/customsb.html b/tests/root/_templates/customsb.html
new file mode 100644
index 0000000..0cd6735
--- /dev/null
+++ b/tests/root/_templates/customsb.html
@@ -0,0 +1,4 @@
+{# custom sidebar template #}
+<h4>Custom sidebar</h4>
+
+{{ toctree(titles_only=True, maxdepth=1) }}
diff --git a/tests/root/_templates/layout.html b/tests/root/_templates/layout.html
new file mode 100644
index 0000000..82125df
--- /dev/null
+++ b/tests/root/_templates/layout.html
@@ -0,0 +1,15 @@
+{% extends "!layout.html" %}
+
+{% block extrahead %}
+{# html_context variable from conf.py #}
+<meta name="hc" content="{{ hckey }}" />
+{# html_context variable from confoverrides (as if given on cmdline) #}
+<meta name="hc_co" content="{{ hckey_co }}" />
+{{ super() }}
+{% endblock %}
+
+{% block sidebartoc %}
+{# display global TOC in addition to local TOC #}
+{{ super() }}
+{{ toctree(collapse=False, maxdepth=-1) }}
+{% endblock %}
\ No newline at end of file
diff --git a/tests/root/autodoc.txt b/tests/root/autodoc.txt
new file mode 100644
index 0000000..d4b3404
--- /dev/null
+++ b/tests/root/autodoc.txt
@@ -0,0 +1,47 @@
+Autodoc tests
+=============
+
+Just testing a few autodoc possibilities...
+
+.. automodule:: util
+
+.. automodule:: test_autodoc
+ :members:
+
+.. autofunction:: function
+
+.. autoclass:: Class
+ :inherited-members:
+
+ Additional content.
+
+.. autoclass:: Outer
+ :members: Inner
+
+.. autoattribute:: Class.docattr
+
+.. autoexception:: CustomEx
+ :members: f
+
+.. autoclass:: CustomDict
+ :show-inheritance:
+ :members:
+
+
+.. automodule:: autodoc_fodder
+ :noindex:
+
+ .. autoclass:: MarkupError
+
+
+.. currentmodule:: test_autodoc
+
+.. autoclass:: InstAttCls
+ :members:
+
+ All members (5 total)
+
+.. autoclass:: InstAttCls
+ :members: ca1, ia1
+
+ Specific members (2 total)
diff --git a/tests/root/autodoc_fodder.py b/tests/root/autodoc_fodder.py
new file mode 100644
index 0000000..e5fd741
--- /dev/null
+++ b/tests/root/autodoc_fodder.py
@@ -0,0 +1,7 @@
+
+class MarkupError(object):
+ """
+ .. note:: This is a docstring with a
+ small markup error which should have
+ correct location information.
+ """
diff --git a/tests/root/autosummary.txt b/tests/root/autosummary.txt
new file mode 100644
index 0000000..fc1a35a
--- /dev/null
+++ b/tests/root/autosummary.txt
@@ -0,0 +1,31 @@
+Autosummary test
+================
+
+.. autosummary::
+ :toctree: generated
+
+ sphinx.application.Sphinx
+
+.. currentmodule:: sphinx.application
+
+.. autoclass:: TemplateBridge
+
+ Basic test
+
+ .. autosummary::
+
+ render -- some ignored stuff goes here
+ render_string More ignored stuff
+
+ Test with tildes
+
+ .. autosummary::
+
+ ~TemplateBridge.render
+ ~TemplateBridge.render_string
+
+ Methods:
+
+ .. automethod:: render
+
+ .. automethod:: render_string
diff --git a/tests/root/bom.po b/tests/root/bom.po
new file mode 100644
index 0000000..c6025eb
--- /dev/null
+++ b/tests/root/bom.po
@@ -0,0 +1,12 @@
+#, fuzzy
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "File with UTF-8 BOM"
+msgstr "Datei mit UTF-8"
+
+msgid "This file has a UTF-8 \"BOM\"."
+msgstr "This file has umlauts: äöü."
diff --git a/tests/root/bom.txt b/tests/root/bom.txt
new file mode 100644
index 0000000..3fea824
--- /dev/null
+++ b/tests/root/bom.txt
@@ -0,0 +1,5 @@
+File with UTF-8 BOM
+===================
+
+This file has a UTF-8 "BOM".
+
diff --git a/tests/root/conf.py b/tests/root/conf.py
new file mode 100644
index 0000000..8025ba3
--- /dev/null
+++ b/tests/root/conf.py
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+
+import sys, os
+
+sys.path.append(os.path.abspath('.'))
+sys.path.append(os.path.abspath('..'))
+
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath', 'sphinx.ext.todo',
+ 'sphinx.ext.coverage', 'sphinx.ext.autosummary',
+ 'sphinx.ext.doctest', 'sphinx.ext.extlinks',
+ 'sphinx.ext.viewcode', 'sphinx.ext.oldcmarkup', 'ext']
+
+jsmath_path = 'dummy.js'
+
+templates_path = ['_templates']
+
+master_doc = 'contents'
+source_suffix = '.txt'
+
+project = 'Sphinx <Tests>'
+copyright = '2010, Georg Brandl & Team'
+# If this is changed, remember to update the versionchanges!
+version = '0.6'
+release = '0.6alpha1'
+today_fmt = '%B %d, %Y'
+# unused_docs = []
+exclude_patterns = ['_build', '**/excluded.*']
+keep_warnings = True
+pygments_style = 'sphinx'
+show_authors = True
+
+rst_epilog = '.. |subst| replace:: global substitution'
+
+html_theme = 'testtheme'
+html_theme_path = ['.']
+html_theme_options = {'testopt': 'testoverride'}
+html_sidebars = {'**': 'customsb.html',
+ 'contents': ['contentssb.html', 'localtoc.html'] }
+html_style = 'default.css'
+html_static_path = ['_static', 'templated.css_t']
+html_extra_path = ['robots.txt']
+html_last_updated_fmt = '%b %d, %Y'
+html_context = {'hckey': 'hcval', 'hckey_co': 'wrong_hcval_co'}
+
+htmlhelp_basename = 'SphinxTestsdoc'
+
+latex_documents = [
+ ('contents', 'SphinxTests.tex', 'Sphinx Tests Documentation',
+ 'Georg Brandl \\and someone else', 'manual'),
+]
+
+latex_additional_files = ['svgimg.svg']
+
+texinfo_documents = [
+ ('contents', 'SphinxTests', 'Sphinx Tests',
+ 'Georg Brandl \\and someone else', 'Sphinx Testing', 'Miscellaneous'),
+]
+
+man_pages = [
+ ('contents', 'SphinxTests', 'Sphinx Tests Documentation',
+ 'Georg Brandl and someone else', 1),
+]
+
+value_from_conf_py = 84
+
+coverage_c_path = ['special/*.h']
+coverage_c_regexes = {'function': r'^PyAPI_FUNC\(.*\)\s+([^_][\w_]+)'}
+
+autosummary_generate = ['autosummary']
+
+extlinks = {'issue': ('http://bugs.python.org/issue%s', 'issue '),
+ 'pyurl': ('http://python.org/%s', None)}
+
+# modify tags from conf.py
+tags.add('confpytag')
+
+# -- linkcode
+
+if 'test_linkcode' in tags:
+ import glob
+
+ extensions.remove('sphinx.ext.viewcode')
+ extensions.append('sphinx.ext.linkcode')
+
+ exclude_patterns.extend(glob.glob('*.txt') + glob.glob('*/*.txt'))
+ exclude_patterns.remove('contents.txt')
+ exclude_patterns.remove('objects.txt')
+
+ def linkcode_resolve(domain, info):
+ if domain == 'py':
+ fn = info['module'].replace('.', '/')
+ return "http://foobar/source/%s.py" % fn
+ elif domain == "js":
+ return "http://foobar/js/" + info['fullname']
+ elif domain in ("c", "cpp"):
+ return "http://foobar/%s/%s" % (domain, "".join(info['names']))
+ else:
+ raise AssertionError()
+
+# -- extension API
+
+from docutils import nodes
+from sphinx import addnodes
+from sphinx.util.compat import Directive
+
+def userdesc_parse(env, sig, signode):
+ x, y = sig.split(':')
+ signode += addnodes.desc_name(x, x)
+ signode += addnodes.desc_parameterlist()
+ signode[-1] += addnodes.desc_parameter(y, y)
+ return x
+
+def functional_directive(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ return [nodes.strong(text='from function: %s' % options['opt'])]
+
+class ClassDirective(Directive):
+ option_spec = {'opt': lambda x: x}
+ def run(self):
+ return [nodes.strong(text='from class: %s' % self.options['opt'])]
+
+def setup(app):
+ app.add_config_value('value_from_conf_py', 42, False)
+ app.add_directive('funcdir', functional_directive, opt=lambda x: x)
+ app.add_directive('clsdir', ClassDirective)
+ app.add_object_type('userdesc', 'userdescrole', '%s (userdesc)',
+ userdesc_parse, objname='user desc')
+ app.add_javascript('file://moo.js')
diff --git a/tests/root/contents.txt b/tests/root/contents.txt
new file mode 100644
index 0000000..7486750
--- /dev/null
+++ b/tests/root/contents.txt
@@ -0,0 +1,45 @@
+.. Sphinx Tests documentation master file, created by sphinx-quickstart on Wed Jun 4 23:49:58 2008.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to Sphinx Tests's documentation!
+========================================
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+ :numbered:
+
+ extapi
+ images
+ subdir/images
+ subdir/includes
+ includes
+ markup
+ objects
+ bom
+ math
+ autodoc
+ autosummary
+ metadata
+ extensions
+ doctest
+ extensions
+ versioning/index
+ footnote
+ lists
+
+ Python <http://python.org/>
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+References
+==========
+
+.. [Ref1] Reference target.
diff --git a/tests/root/doctest.txt b/tests/root/doctest.txt
new file mode 100644
index 0000000..d029cd8
--- /dev/null
+++ b/tests/root/doctest.txt
@@ -0,0 +1,129 @@
+Testing the doctest extension
+=============================
+
+Simple doctest blocks
+---------------------
+
+>>> 1+1
+2
+>>> 1/0
+Traceback (most recent call last):
+ ...
+ZeroDivisionError: integer division or modulo by zero
+
+
+Special directives
+------------------
+
+* doctest
+
+ .. doctest::
+
+ >>> 1+1
+ 2
+ >>> 1/0
+ Traceback (most recent call last):
+ ...
+ ZeroDivisionError: integer division or modulo by zero
+
+* testcode/testoutput
+
+ .. testcode::
+
+ print(1+1)
+
+ .. testoutput::
+
+ 2
+
+ .. testcode::
+
+ 1/0
+
+ .. testoutput::
+
+ Traceback (most recent call last):
+ ...
+ ZeroDivisionError: integer division or modulo by zero
+
+* testsetup
+
+ .. testsetup:: *
+
+ def squared(x):
+ return x * x
+
+ .. doctest::
+
+ >>> squared(2)
+ 4
+
+ .. testcode::
+
+ print(squared(2))
+
+ .. testoutput::
+
+ 4
+
+ >>> squared(2)
+ 4
+
+* options for testcode/testoutput blocks
+
+ .. testcode::
+ :hide:
+
+ print('Output text.')
+
+ .. testoutput::
+ :hide:
+ :options: +NORMALIZE_WHITESPACE
+
+ Output text.
+
+* grouping
+
+ .. testsetup:: group1
+
+ def add(x, y):
+ return x + y
+
+
+ ``add`` is now known in "group1", but not in others.
+
+ .. doctest:: group1
+
+ >>> add(1, 1)
+ 2
+
+ .. doctest:: group2
+
+ >>> add(1, 1)
+ Traceback (most recent call last):
+ ...
+ NameError: name 'add' is not defined
+
+ Interleaving testcode/testoutput:
+
+ .. testcode:: group1
+
+ print(squared(3))
+
+ .. testcode:: group2
+
+ print(squared(4))
+
+ .. testoutput:: group1
+
+ 9
+
+ .. testoutput:: group2
+
+ 16
+
+
+.. testcleanup:: *
+
+ import test_doctest
+ test_doctest.cleanup_call()
diff --git a/tests/root/ext.py b/tests/root/ext.py
new file mode 100644
index 0000000..34a73cb
--- /dev/null
+++ b/tests/root/ext.py
@@ -0,0 +1,4 @@
+# Test extension module
+
+def setup(app):
+ app.add_config_value('value_from_ext', [], False)
diff --git a/tests/root/extapi.txt b/tests/root/extapi.txt
new file mode 100644
index 0000000..4728e3d
--- /dev/null
+++ b/tests/root/extapi.txt
@@ -0,0 +1,10 @@
+Extension API tests
+===================
+
+Testing directives:
+
+.. funcdir::
+ :opt: Foo
+
+.. clsdir::
+ :opt: Bar
diff --git a/tests/root/extensions.txt b/tests/root/extensions.txt
new file mode 100644
index 0000000..96b1f8e
--- /dev/null
+++ b/tests/root/extensions.txt
@@ -0,0 +1,28 @@
+Test for diverse extensions
+===========================
+
+extlinks
+--------
+
+Test diverse links: :issue:`1000` and :pyurl:`dev/`, also with
+:issue:`explicit caption <1042>`.
+
+
+todo
+----
+
+.. todo::
+
+ Test the todo extension.
+
+.. todo::
+
+ Test with |sub| (see #286).
+
+.. |sub| replace:: substitution references
+
+
+list of all todos
+^^^^^^^^^^^^^^^^^
+
+.. todolist::
diff --git a/tests/root/footnote.txt b/tests/root/footnote.txt
new file mode 100644
index 0000000..b600697
--- /dev/null
+++ b/tests/root/footnote.txt
@@ -0,0 +1,46 @@
+:tocdepth: 2
+
+Testing footnote and citation
+================================
+.. #1058 footnote-backlinks-do-not-work
+
+numbered footnote
+--------------------
+
+[1]_
+
+auto-numbered footnote
+------------------------------
+
+[#]_
+
+named footnote
+--------------------
+
+[#foo]_
+
+citation
+--------------------
+
+[bar]_
+
+footenotes
+--------------------
+
+.. rubric:: Footnotes
+
+.. [1] numbered
+
+.. [#] auto numbered
+
+.. [#foo] named
+
+.. rubric:: Citations
+
+.. [bar] cite
+
+
+missing target
+--------------------
+[missing]_ citation
+
diff --git a/tests/root/images.txt b/tests/root/images.txt
new file mode 100644
index 0000000..bd64d57
--- /dev/null
+++ b/tests/root/images.txt
@@ -0,0 +1,28 @@
+Sphinx image handling
+=====================
+
+.. first, a simple test with direct filename
+.. image:: img.png
+
+.. a non-existing image with direct filename
+.. image:: foo.png
+
+.. an image with path name (relative to this directory!)
+.. image:: subdir/img.png
+ :height: 100
+ :width: 200
+
+.. an image with unspecified extension
+.. image:: img.*
+
+.. a non-existing image with .*
+.. image:: foo.*
+
+.. a non-local image URI
+.. image:: http://www.python.org/logo.png
+
+.. an image with subdir and unspecified extension
+.. image:: subdir/simg.*
+
+.. an SVG image (for HTML at least)
+.. image:: svgimg.*
diff --git a/tests/root/img.gif b/tests/root/img.gif
new file mode 100644
index 0000000..8f02686
Binary files /dev/null and b/tests/root/img.gif differ
diff --git a/tests/root/img.pdf b/tests/root/img.pdf
new file mode 100644
index 0000000..cacbd85
Binary files /dev/null and b/tests/root/img.pdf differ
diff --git a/tests/root/img.png b/tests/root/img.png
new file mode 100644
index 0000000..72c12d1
Binary files /dev/null and b/tests/root/img.png differ
diff --git a/tests/root/includes.txt b/tests/root/includes.txt
new file mode 100644
index 0000000..904f067
--- /dev/null
+++ b/tests/root/includes.txt
@@ -0,0 +1,84 @@
+Testing downloadable files
+==========================
+
+Download :download:`img.png` here.
+Download :download:`this <subdir/img.png>` there.
+Don't download :download:`this <nonexisting.png>`.
+
+Test file and literal inclusion
+===============================
+
+.. include:: subdir/include.inc
+
+.. include:: /subdir/include.inc
+
+.. literalinclude:: literal.inc
+ :language: python
+
+.. should give a warning
+.. literalinclude:: wrongenc.inc
+
+.. should succeed
+.. literalinclude:: wrongenc.inc
+ :encoding: latin-1
+.. include:: wrongenc.inc
+ :encoding: latin-1
+
+Literalinclude options
+======================
+
+.. highlight:: text
+
+.. cssclass:: inc-pyobj1
+.. literalinclude:: literal.inc
+ :pyobject: Foo
+
+.. cssclass:: inc-pyobj2
+.. literalinclude:: literal.inc
+ :pyobject: Bar.baz
+
+.. cssclass:: inc-lines
+.. literalinclude:: literal.inc
+ :lines: 6-7,9
+
+.. cssclass:: inc-startend
+.. literalinclude:: literal.inc
+ :start-after: coding: utf-8
+ :end-before: class Foo
+
+.. cssclass:: inc-preappend
+.. literalinclude:: literal.inc
+ :prepend: START CODE
+ :append: END CODE
+
+.. literalinclude:: literal.inc
+ :start-after: utf-8
+
+.. literalinclude:: literal.inc
+ :end-before: class Foo
+
+.. cssclass:: inc-tab3
+.. literalinclude:: tabs.inc
+ :tab-width: 3
+ :language: text
+
+.. cssclass:: inc-tab8
+.. literalinclude:: tabs.inc
+ :tab-width: 8
+ :language: python
+
+Test if dedenting before parsing works.
+
+.. highlight:: python
+
+.. cssclass:: inc-pyobj-dedent
+.. literalinclude:: literal.inc
+ :pyobject: Bar.baz
+
+Docutils include with "literal"
+===============================
+
+While not recommended, it should work (and leave quotes alone).
+
+.. include:: quotes.inc
+ :literal:
diff --git a/tests/root/lists.txt b/tests/root/lists.txt
new file mode 100644
index 0000000..99a55dc
--- /dev/null
+++ b/tests/root/lists.txt
@@ -0,0 +1,54 @@
+Various kinds of lists
+======================
+
+
+nested enumerated lists
+-----------------------
+
+#. one
+
+#. two
+
+ #. two.1
+ #. two.2
+
+#. three
+
+
+enumerated lists with non-default start values
+----------------------------------------------
+
+0. zero
+#. one
+
+----------------------------------------
+
+1. one
+#. two
+
+----------------------------------------
+
+2. two
+#. three
+
+
+enumerated lists using letters
+------------------------------
+
+a. a
+
+b. b
+
+#. c
+
+#. d
+
+----------------------------------------
+
+x. x
+
+y. y
+
+#. z
+
+#. {
diff --git a/tests/root/literal.inc b/tests/root/literal.inc
new file mode 100644
index 0000000..694f15e
--- /dev/null
+++ b/tests/root/literal.inc
@@ -0,0 +1,13 @@
+# Literally included file using Python highlighting
+# -*- coding: utf-8 -*-
+
+foo = "Including Unicode characters: üöä"
+
+class Foo:
+ pass
+
+class Bar:
+ def baz():
+ pass
+
+def bar(): pass
diff --git a/tests/root/markup.txt b/tests/root/markup.txt
new file mode 100644
index 0000000..34e8fdb
--- /dev/null
+++ b/tests/root/markup.txt
@@ -0,0 +1,359 @@
+:tocdepth: 2
+
+.. title:: set by title directive
+
+Testing various markup
+======================
+
+Meta markup
+-----------
+
+.. sectionauthor:: Georg Brandl
+.. moduleauthor:: Georg Brandl
+
+.. contents:: TOC
+
+.. meta::
+ :author: Me
+ :keywords: docs, sphinx
+
+
+Generic reST
+------------
+
+A |subst| (the definition is in rst_epilog).
+
+.. _label:
+
+::
+
+ some code
+
+Option list:
+
+-h help
+--help also help
+
+Line block:
+
+| line1
+| line2
+| line3
+| line4
+| line5
+| line6
+| line7
+
+
+Body directives
+^^^^^^^^^^^^^^^
+
+.. topic:: Title
+
+ Topic body.
+
+.. sidebar:: Sidebar
+ :subtitle: Sidebar subtitle
+
+ Sidebar body.
+
+.. rubric:: Test rubric
+
+.. epigraph:: Epigraph title
+
+ Epigraph body.
+
+ -- Author
+
+.. highlights:: Highlights
+
+ Highlights body.
+
+.. pull-quote:: Pull-quote
+
+ Pull quote body.
+
+.. compound::
+
+ a
+
+ b
+
+.. parsed-literal::
+
+ with some *markup* inside
+
+
+.. _admonition-section:
+
+Admonitions
+^^^^^^^^^^^
+
+.. admonition:: My Admonition
+
+ Admonition text.
+
+.. note::
+ Note text.
+
+.. warning::
+
+ Warning text.
+
+.. _some-label:
+
+.. tip::
+ Tip text.
+
+
+Inline markup
+-------------
+
+*Generic inline markup*
+
+Adding \n to test unescaping.
+
+* :command:`command\\n`
+* :dfn:`dfn\\n`
+* :guilabel:`guilabel with &accelerator and \\n`
+* :kbd:`kbd\\n`
+* :mailheader:`mailheader\\n`
+* :makevar:`makevar\\n`
+* :manpage:`manpage\\n`
+* :mimetype:`mimetype\\n`
+* :newsgroup:`newsgroup\\n`
+* :program:`program\\n`
+* :regexp:`regexp\\n`
+* :menuselection:`File --> Close\\n`
+* :menuselection:`&File --> &Print`
+* :file:`a/{varpart}/b\\n`
+* :samp:`print {i}\\n`
+
+*Linking inline markup*
+
+* :pep:`8`
+* :rfc:`1`
+* :envvar:`HOME`
+* :keyword:`with`
+* :token:`try statement <try_stmt>`
+* :ref:`admonition-section`
+* :ref:`here <some-label>`
+* :ref:`my-figure`
+* :ref:`my-table`
+* :doc:`subdir/includes`
+* ``:download:`` is tested in includes.txt
+* :option:`Python -c option <python -c>`
+* This used to crash: :option:`Python c option`
+
+Test :abbr:`abbr (abbreviation)` and another :abbr:`abbr (abbreviation)`.
+
+Testing the :index:`index` role, also available with
+:index:`explicit <pair: title; explicit>` title.
+
+.. _with:
+
+With
+----
+
+(Empty section.)
+
+
+Tables
+------
+
+.. tabularcolumns:: |L|p{5cm}|R|
+
+.. _my-table:
+
+.. table:: my table
+
+ +----+----------------+----+
+ | 1 | * Block elems | x |
+ | | * In table | |
+ +----+----------------+----+
+ | 2 | Empty cells: | |
+ +----+----------------+----+
+
+Table with multicol:
+
+.. only:: latex
+
+ +----+---------------------+
+ | 1 | test! |
+ +----+---------+------+----+
+ | 2 | col | col | c |
+ | y +---------+------+----+
+ | x | test |
+ +----+---------------------+
+
+
+Figures
+-------
+
+.. _my-figure:
+
+.. figure:: img.png
+
+ My caption of the figure
+
+ My description paragraph of the figure.
+
+ Description paragraph is wraped with legend node.
+
+
+Version markup
+--------------
+
+.. versionadded:: 0.6
+ Some funny **stuff**.
+
+.. versionchanged:: 0.6
+ Even more funny stuff.
+
+.. deprecated:: 0.6
+ Boring stuff.
+
+.. versionadded:: 1.2
+
+ First paragraph of versionadded.
+
+.. versionchanged:: 1.2
+ First paragraph of versionchanged.
+
+ Second paragraph of versionchanged.
+
+
+Code blocks
+-----------
+
+.. code-block:: ruby
+ :linenos:
+
+ def ruby?
+ false
+ end
+
+
+Misc stuff
+----------
+
+Stuff [#]_
+
+Reference lookup: [Ref1]_ (defined in another file).
+
+.. seealso:: something, something else, something more
+
+ `Google <http://www.google.com>`_
+ For everything.
+
+.. hlist::
+ :columns: 4
+
+ * This
+ * is
+ * a horizontal
+ * list
+ * with several
+ * items
+
+.. rubric:: Side note
+
+This is a side note.
+
+This tests :CLASS:`role names in uppercase`.
+
+.. centered:: LICENSE AGREEMENT
+
+.. acks::
+
+ * Terry Pratchett
+ * J. R. R. Tolkien
+ * Monty Python
+
+.. glossary::
+ :sorted:
+
+ boson
+ Particle with integer spin.
+
+ *fermion*
+ Particle with half-integer spin.
+
+ tauon
+ myon
+ electron
+ Examples for fermions.
+
+ über
+ Gewisse
+
+ änhlich
+ Dinge
+
+.. productionlist::
+ try_stmt: `try1_stmt` | `try2_stmt`
+ try1_stmt: "try" ":" `suite`
+ : ("except" [`expression` ["," `target`]] ":" `suite`)+
+ : ["else" ":" `suite`]
+ : ["finally" ":" `suite`]
+ try2_stmt: "try" ":" `suite`
+ : "finally" ":" `suite`
+
+
+Index markup
+------------
+
+.. index::
+ single: entry
+ pair: entry; pair
+ double: entry; double
+ triple: index; entry; triple
+ keyword: with
+ see: from; to
+ seealso: fromalso; toalso
+
+Invalid index markup...
+
+.. index::
+ single:
+ pair:
+ keyword:
+
+.. index::
+ !Main, !Other
+ !single: entry; pair
+
+:index:`!Main`
+
+.. _ölabel:
+
+Ö... Some strange characters
+----------------------------
+
+Testing öäü...
+
+
+Only directive
+--------------
+
+.. only:: html
+
+ In HTML.
+
+.. only:: latex
+
+ In LaTeX.
+
+.. only:: html or latex
+
+ In both.
+
+.. only:: confpytag and (testtag or nonexisting_tag)
+
+ Always present, because set through conf.py/command line.
+
+
+.. rubric:: Footnotes
+
+.. [#] Like footnotes.
+
diff --git a/tests/root/math.txt b/tests/root/math.txt
new file mode 100644
index 0000000..36b2449
--- /dev/null
+++ b/tests/root/math.txt
@@ -0,0 +1,22 @@
+Test math extensions
+====================
+
+This is inline math: :math:`a^2 + b^2 = c^2`.
+
+.. math:: a^2 + b^2 = c^2
+
+.. math::
+
+ a^2 + b^2 = c^2
+
+.. math::
+ :label: foo
+
+ e^{i\pi} = 1
+
+.. math::
+ :label:
+
+ e^{ix} = \cos x + i\sin x
+
+Referencing equation :eq:`foo`.
diff --git a/tests/root/metadata.txt b/tests/root/metadata.txt
new file mode 100644
index 0000000..9b3044b
--- /dev/null
+++ b/tests/root/metadata.txt
@@ -0,0 +1,53 @@
+:Author: David Goodger
+:Address: 123 Example Street
+ Example, EX Canada
+ A1B 2C3
+:Contact: goodger at python.org
+:Authors: Me; Myself; I
+:organization: humankind
+:date: $Date: 2006-05-21 22:44:42 +0200 (Son, 21 Mai 2006) $
+:status: This is a "work in progress"
+:revision: $Revision: 4564 $
+:version: 1
+:copyright: This document has been placed in the public domain. You
+ may do with it as you wish. You may copy, modify,
+ redistribute, reattribute, sell, buy, rent, lease,
+ destroy, or improve it, quote it at length, excerpt,
+ incorporate, collate, fold, staple, or mutilate it, or do
+ anything else to it that your or anyone else's heart
+ desires.
+:field name: This is a generic bibliographic field.
+:field name 2:
+ Generic bibliographic fields may contain multiple body elements.
+
+ Like this.
+
+:Dedication:
+
+ For Docutils users & co-developers.
+
+:abstract:
+
+ This document is a demonstration of the reStructuredText markup
+ language, containing examples of all basic reStructuredText
+ constructs and many advanced constructs.
+
+.. meta::
+ :keywords: reStructuredText, demonstration, demo, parser
+ :description lang=en: A demonstration of the reStructuredText
+ markup language, containing examples of all basic
+ constructs and many advanced constructs.
+
+================================
+ reStructuredText Demonstration
+================================
+
+.. Above is the document title, and below is the subtitle.
+ They are transformed from section titles after parsing.
+
+--------------------------------
+ Examples of Syntax Constructs
+--------------------------------
+
+.. bibliographic fields (which also require a transform):
+
diff --git a/tests/root/objects.txt b/tests/root/objects.txt
new file mode 100644
index 0000000..57e8221
--- /dev/null
+++ b/tests/root/objects.txt
@@ -0,0 +1,198 @@
+Testing object descriptions
+===========================
+
+.. function:: func_without_module(a, b, *c[, d])
+
+ Does something.
+
+.. function:: func_without_body()
+
+.. function:: func_with_unknown_field()
+
+ : :
+
+ : empty field name:
+
+ :field_name:
+
+ :field_name all lower:
+
+ :FIELD_NAME:
+
+ :FIELD_NAME ALL CAPS:
+
+ :Field_Name:
+
+ :Field_Name All Word Caps:
+
+ :Field_name:
+
+ :Field_name First word cap:
+
+ :FIELd_name:
+
+ :FIELd_name PARTial caps:
+
+.. function:: func_noindex
+ :noindex:
+
+.. function:: func_with_module
+ :module: foolib
+
+Referring to :func:`func with no index <func_noindex>`.
+Referring to :func:`nothing <>`.
+
+.. module:: mod
+ :synopsis: Module synopsis.
+ :platform: UNIX
+
+.. function:: func_in_module
+
+.. class:: Cls
+
+ .. method:: meth1
+
+ .. staticmethod:: meths
+
+ .. attribute:: attr
+
+.. explicit class given
+.. method:: Cls.meth2
+
+.. explicit module given
+.. exception:: Error(arg1, arg2)
+ :module: errmod
+
+.. data:: var
+
+
+.. currentmodule:: None
+
+.. function:: func_without_module2() -> annotation
+
+.. object:: long(parameter, \
+ list)
+ another one
+
+.. class:: TimeInt
+
+ Has only one parameter (triggers special behavior...)
+
+ :param moo: |test|
+ :type moo: |test|
+
+.. |test| replace:: Moo
+
+.. class:: Time(hour, minute, isdst)
+
+ :param year: The year.
+ :type year: TimeInt
+ :param TimeInt minute: The minute.
+ :param isdst: whether it's DST
+ :type isdst: * some complex
+ * expression
+ :returns: a new :class:`Time` instance
+ :rtype: :class:`Time`
+ :raises ValueError: if the values are out of range
+ :ivar int hour: like *hour*
+ :ivar minute: like *minute*
+ :vartype minute: int
+ :param hour: Some parameter
+ :type hour: DuplicateType
+ :param hour: Duplicate param. Should not lead to crashes.
+ :type hour: DuplicateType
+
+
+C items
+=======
+
+.. c:function:: Sphinx_DoSomething()
+
+.. c:member:: SphinxStruct.member
+
+.. c:macro:: SPHINX_USE_PYTHON
+
+.. c:type:: SphinxType
+
+.. c:var:: sphinx_global
+
+
+Old C items (from oldcmarkup ext)
+---------------------------------
+
+.. cfunction:: Sphinx_Func()
+
+Refer to :cfunc:`Sphinx_Func`.
+
+
+Javascript items
+================
+
+.. js:function:: foo()
+
+.. js:data:: bar
+
+.. documenting the method of any object
+.. js:function:: bar.baz(href, callback[, errback])
+
+ :param string href: The location of the resource.
+ :param callback: Get's called with the data returned by the resource.
+ :throws InvalidHref: If the `href` is invalid.
+ :returns: `undefined`
+
+.. js:attribute:: bar.spam
+
+References
+==========
+
+Referencing :class:`mod.Cls` or :Class:`mod.Cls` should be the same.
+
+With target: :c:func:`Sphinx_DoSomething()` (parentheses are handled),
+:c:member:`SphinxStruct.member`, :c:macro:`SPHINX_USE_PYTHON`,
+:c:type:`SphinxType *` (pointer is handled), :c:data:`sphinx_global`.
+
+Without target: :c:func:`CFunction`. :c:func:`!malloc`.
+
+:js:func:`foo()`
+:js:func:`foo`
+
+:js:data:`bar`
+:js:func:`bar.baz()`
+:js:func:`bar.baz`
+:js:func:`~bar.baz()`
+
+:js:attr:`bar.baz`
+
+
+Others
+======
+
+.. envvar:: HOME
+
+.. program:: python
+
+.. cmdoption:: -c command
+
+.. program:: perl
+
+.. cmdoption:: -c
+
+
+User markup
+===========
+
+.. userdesc:: myobj:parameter
+
+ Description of userdesc.
+
+
+Referencing :userdescrole:`myobj`.
+
+
+CPP domain
+==========
+
+.. cpp:class:: n::Array<T,d>
+
+ .. cpp:function:: T& operator[]( unsigned j )
+ const T& operator[]( unsigned j ) const
diff --git a/tests/root/quotes.inc b/tests/root/quotes.inc
new file mode 100644
index 0000000..276cc56
--- /dev/null
+++ b/tests/root/quotes.inc
@@ -0,0 +1 @@
+Testing "quotes" in literal 'included' text.
diff --git a/tests/root/rimg.png b/tests/root/rimg.png
new file mode 100644
index 0000000..1081dc1
Binary files /dev/null and b/tests/root/rimg.png differ
diff --git a/tests/root/robots.txt b/tests/root/robots.txt
new file mode 100644
index 0000000..1b425ee
--- /dev/null
+++ b/tests/root/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow: /cgi-bin/
diff --git a/tests/root/special/api.h b/tests/root/special/api.h
new file mode 100644
index 0000000..7c137e0
--- /dev/null
+++ b/tests/root/special/api.h
@@ -0,0 +1 @@
+PyAPI_FUNC(PyObject *) Py_SphinxTest();
diff --git a/tests/root/special/code.py b/tests/root/special/code.py
new file mode 100644
index 0000000..70c48d2
--- /dev/null
+++ b/tests/root/special/code.py
@@ -0,0 +1,2 @@
+print "line 1"
+print "line 2"
diff --git a/tests/root/subdir.po b/tests/root/subdir.po
new file mode 100644
index 0000000..f515f22
--- /dev/null
+++ b/tests/root/subdir.po
@@ -0,0 +1,9 @@
+#, fuzzy
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Including in subdir"
+msgstr "translation"
diff --git a/tests/root/subdir/excluded.txt b/tests/root/subdir/excluded.txt
new file mode 100644
index 0000000..5df3139
--- /dev/null
+++ b/tests/root/subdir/excluded.txt
@@ -0,0 +1,2 @@
+Excluded file -- should *not* be read as source
+-----------------------------------------------
diff --git a/tests/root/subdir/images.txt b/tests/root/subdir/images.txt
new file mode 100644
index 0000000..f2adf88
--- /dev/null
+++ b/tests/root/subdir/images.txt
@@ -0,0 +1,6 @@
+Image including source in subdir
+================================
+
+.. image:: img.*
+
+.. image:: /rimg.png
diff --git a/tests/root/subdir/img.png b/tests/root/subdir/img.png
new file mode 100644
index 0000000..72c12d1
Binary files /dev/null and b/tests/root/subdir/img.png differ
diff --git a/tests/root/subdir/include.inc b/tests/root/subdir/include.inc
new file mode 100644
index 0000000..1211300
--- /dev/null
+++ b/tests/root/subdir/include.inc
@@ -0,0 +1,5 @@
+.. This file is included by contents.txt.
+
+.. Paths in included files are relative to the file that
+ includes them
+.. image:: ../root/img.png
diff --git a/tests/root/subdir/includes.txt b/tests/root/subdir/includes.txt
new file mode 100644
index 0000000..627dcfb
--- /dev/null
+++ b/tests/root/subdir/includes.txt
@@ -0,0 +1,18 @@
+Including in subdir
+===================
+
+.. absolute filename
+.. literalinclude:: /special/code.py
+ :lines: 1
+
+.. relative filename
+.. literalinclude:: ../special/code.py
+ :lines: 2
+
+Absolute :download:`/img.png` download.
+
+.. absolute image filename
+.. image:: /img.png
+
+.. absolute include filename
+.. include:: /test.inc
diff --git a/tests/root/subdir/simg.png b/tests/root/subdir/simg.png
new file mode 100644
index 0000000..72c12d1
Binary files /dev/null and b/tests/root/subdir/simg.png differ
diff --git a/tests/root/svgimg.pdf b/tests/root/svgimg.pdf
new file mode 100644
index 0000000..cacbd85
Binary files /dev/null and b/tests/root/svgimg.pdf differ
diff --git a/tests/root/svgimg.svg b/tests/root/svgimg.svg
new file mode 100644
index 0000000..10e035b
--- /dev/null
+++ b/tests/root/svgimg.svg
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ height="60"
+ width="60"
+ _SVGFile__filename="oldscale/apps/warning.svg"
+ version="1.0"
+ y="0"
+ x="0"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.41"
+ sodipodi:docname="exclamation.svg"
+ sodipodi:docbase="/home/danny/work/icons/primary/scalable/actions">
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0000000"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7.5136000"
+ inkscape:cx="42.825186"
+ inkscape:cy="24.316071"
+ inkscape:window-width="1020"
+ inkscape:window-height="691"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1160">
+ <stop
+ style="stop-color: #000000;stop-opacity: 1.0;"
+ id="stop1161"
+ offset="0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ id="stop1162"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient1160"
+ id="linearGradient1163" />
+ </defs>
+ <metadata
+ id="metadata12">
+ <RDF
+ id="RDF13">
+ <Work
+ about=""
+ id="Work14">
+ <title
+ id="title15">Part of the Flat Icon Collection (Thu Aug 26 14:31:40 2004)</title>
+ <description
+ id="description17" />
+ <subject
+ id="subject18">
+ <Bag
+ id="Bag19">
+ <li
+ id="li20" />
+ </Bag>
+ </subject>
+ <publisher
+ id="publisher21">
+ <Agent
+ about=""
+ id="Agent22">
+ <title
+ id="title23" />
+ </Agent>
+ </publisher>
+ <creator
+ id="creator24">
+ <Agent
+ about=""
+ id="Agent25">
+ <title
+ id="title26">Danny Allen</title>
+ </Agent>
+ </creator>
+ <rights
+ id="rights28">
+ <Agent
+ about=""
+ id="Agent29">
+ <title
+ id="title30">Danny Allen</title>
+ </Agent>
+ </rights>
+ <date
+ id="date32" />
+ <format
+ id="format33">image/svg+xml</format>
+ <type
+ id="type35"
+ resource="http://purl.org/dc/dcmitype/StillImage" />
+ <license
+ id="license36"
+ resource="http://creativecommons.org/licenses/LGPL/2.1/">
+ <date
+ id="date37" />
+ </license>
+ <language
+ id="language38">en</language>
+ </Work>
+ </RDF>
+ <rdf:RDF
+ id="RDF40">
+ <cc:Work
+ rdf:about=""
+ id="Work41">
+ <dc:format
+ id="format42">image/svg+xml</dc:format>
+ <dc:type
+ id="type44"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="g2099">
+ <path
+ style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:8.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+ d="M 55.311891,51.920745 L 4.6880989,51.920744 L 29.999995,8.0792542 L 55.311891,51.920745 z "
+ id="path1724" />
+ <path
+ style="color:#000000;fill:#ffe940;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250010;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+ d="M 55.311891,51.920745 L 4.6880989,51.920744 L 29.999995,8.0792542 L 55.311891,51.920745 z "
+ id="path1722" />
+ <path
+ style="font-size:12.000000;font-weight:900;fill:none;fill-opacity:1.0000000;stroke:#ffffff;stroke-width:8.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 34.944960,10.779626 L 34.944960,33.186510 C 34.944960,34.752415 34.501979,36.081368 33.616007,37.173380 C 32.750636,38.265402 31.545298,38.811408 29.999995,38.811408 C 28.475302,38.811408 27.269965,38.265402 26.383993,37.173380 C 25.498020,36.060767 25.055030,34.731804 25.055030,33.186510 L 25.055030,10.779626 C 25.055030,9.1931155 25.498020,7.8641562 26.383993,6.7927462 C 27.269965,5.7007332 28.475302,5.1547262 29.999995,5.1547262 C 31.009593,5.1547262 31.885265,5.4019740 32 [...]
+ id="path1099" />
+ <path
+ style="font-size:12.000000;font-weight:900;fill:#e71c02;fill-opacity:1.0000000;stroke:none;stroke-width:3.1249981;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1.0000000"
+ d="M 29.999995,3.5986440 C 28.102272,3.5986440 26.318514,4.3848272 25.156245,5.8173940 C 24.028906,7.1806889 23.499995,8.9087770 23.499995,10.786144 L 23.499995,33.192394 C 23.499995,35.036302 24.050685,36.772771 25.156245,38.161144 C 26.318514,39.593721 28.102273,40.379893 29.999995,40.379894 C 31.913354,40.379894 33.697195,39.576736 34.843745,38.129894 C 35.959941,36.754118 36.499995,35.052976 36.499995,33.192394 L 36.499995,10.786144 C 36.499995,9.5413010 36.276626,8.3551469 35 [...]
+ id="path835"
+ sodipodi:nodetypes="cccccccccccc" />
+ <path
+ style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:5.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+ d="M 36.506243,49.901522 C 36.506243,53.492972 33.591442,56.407773 29.999991,56.407773 C 26.408541,56.407773 23.493739,53.492972 23.493739,49.901522 C 23.493739,46.310071 26.408541,43.395270 29.999991,43.395270 C 33.591442,43.395270 36.506243,46.310071 36.506243,49.901522 z "
+ id="path1727" />
+ <path
+ style="color:#000000;fill:#e71c02;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+ d="M 36.506243,49.901522 C 36.506243,53.492972 33.591442,56.407773 29.999991,56.407773 C 26.408541,56.407773 23.493739,53.492972 23.493739,49.901522 C 23.493739,46.310071 26.408541,43.395270 29.999991,43.395270 C 33.591442,43.395270 36.506243,46.310071 36.506243,49.901522 z "
+ id="path1725" />
+ </g>
+</svg>
diff --git a/tests/root/tabs.inc b/tests/root/tabs.inc
new file mode 100644
index 0000000..20b5182
--- /dev/null
+++ b/tests/root/tabs.inc
@@ -0,0 +1,5 @@
+Tabs include file test
+----------------------
+
+The next line has a tab:
+-| |-
diff --git a/tests/root/templated.css_t b/tests/root/templated.css_t
new file mode 100644
index 0000000..72ddb80
--- /dev/null
+++ b/tests/root/templated.css_t
@@ -0,0 +1,2 @@
+/* Stub file, templated */
+{{ sphinx_version }}
diff --git a/tests/root/test.inc b/tests/root/test.inc
new file mode 100644
index 0000000..b8fdb93
--- /dev/null
+++ b/tests/root/test.inc
@@ -0,0 +1,3 @@
+.. This file is included from subdir/includes.txt.
+
+This is an include file.
\ No newline at end of file
diff --git a/tests/root/testtheme/layout.html b/tests/root/testtheme/layout.html
new file mode 100644
index 0000000..81372be
--- /dev/null
+++ b/tests/root/testtheme/layout.html
@@ -0,0 +1,5 @@
+{% extends "basic/layout.html" %}
+{% block extrahead %}
+<meta name="testopt" content="{{ theme_testopt }}" />
+{{ super() }}
+{% endblock %}
diff --git a/tests/root/testtheme/static/staticimg.png b/tests/root/testtheme/static/staticimg.png
new file mode 100644
index 0000000..1081dc1
Binary files /dev/null and b/tests/root/testtheme/static/staticimg.png differ
diff --git a/tests/root/testtheme/static/statictmpl.html_t b/tests/root/testtheme/static/statictmpl.html_t
new file mode 100644
index 0000000..4ab292b
--- /dev/null
+++ b/tests/root/testtheme/static/statictmpl.html_t
@@ -0,0 +1,2 @@
+<!-- testing static templates -->
+<html><project>{{ project|e }}</project></html>
diff --git a/tests/root/testtheme/theme.conf b/tests/root/testtheme/theme.conf
new file mode 100644
index 0000000..a877673
--- /dev/null
+++ b/tests/root/testtheme/theme.conf
@@ -0,0 +1,7 @@
+[theme]
+inherit = basic
+stylesheet = default.css
+pygments_style = emacs
+
+[options]
+testopt = optdefault
diff --git a/tests/root/versioning/added.txt b/tests/root/versioning/added.txt
new file mode 100644
index 0000000..22a7073
--- /dev/null
+++ b/tests/root/versioning/added.txt
@@ -0,0 +1,20 @@
+Versioning test text
+====================
+
+So the thing is I need some kind of text - not the lorem ipsum stuff, that
+doesn't work out that well - to test :mod:`sphinx.versioning`. I couldn't find
+a good text for that under public domain so I thought the easiest solution is
+to write one by myself. It's not really interesting, in fact it is *really*
+boring.
+
+Anyway I need more than one paragraph, at least three for the original
+document, I think, and another one for two different ones.
+
+So the previous paragraph was a bit short because I don't want to test this
+only on long paragraphs, I hope it was short enough to cover most stuff.
+Anyway I see this lacks ``some markup`` so I have to add a **little** bit.
+
+Woho another paragraph, if this test fails we really have a problem because
+this means the algorithm itself fails and not the diffing algorithm which is
+pretty much doomed anyway as it probably fails for some kind of language
+respecting certain nodes anyway but we can't work around that anyway.
diff --git a/tests/root/versioning/deleted.txt b/tests/root/versioning/deleted.txt
new file mode 100644
index 0000000..a1a9c4c
--- /dev/null
+++ b/tests/root/versioning/deleted.txt
@@ -0,0 +1,12 @@
+Versioning test text
+====================
+
+So the thing is I need some kind of text - not the lorem ipsum stuff, that
+doesn't work out that well - to test :mod:`sphinx.versioning`. I couldn't find
+a good text for that under public domain so I thought the easiest solution is
+to write one by myself. It's not really interesting, in fact it is *really*
+boring.
+
+So the previous paragraph was a bit short because I don't want to test this
+only on long paragraphs, I hope it was short enough to cover most stuff.
+Anyway I see this lacks ``some markup`` so I have to add a **little** bit.
diff --git a/tests/root/versioning/deleted_end.txt b/tests/root/versioning/deleted_end.txt
new file mode 100644
index 0000000..f30e630
--- /dev/null
+++ b/tests/root/versioning/deleted_end.txt
@@ -0,0 +1,11 @@
+Versioning test text
+====================
+
+So the thing is I need some kind of text - not the lorem ipsum stuff, that
+doesn't work out that well - to test :mod:`sphinx.versioning`. I couldn't find
+a good text for that under public domain so I thought the easiest solution is
+to write one by myself. It's not really interesting, in fact it is *really*
+boring.
+
+Anyway I need more than one paragraph, at least three for the original
+document, I think, and another one for two different ones.
diff --git a/tests/root/versioning/index.txt b/tests/root/versioning/index.txt
new file mode 100644
index 0000000..9d098f7
--- /dev/null
+++ b/tests/root/versioning/index.txt
@@ -0,0 +1,13 @@
+Versioning Stuff
+================
+
+.. toctree::
+
+ original
+ added
+ insert
+ deleted
+ deleted_end
+ modified
+ insert_beginning
+ insert_similar
diff --git a/tests/root/versioning/insert.txt b/tests/root/versioning/insert.txt
new file mode 100644
index 0000000..1c157cc
--- /dev/null
+++ b/tests/root/versioning/insert.txt
@@ -0,0 +1,18 @@
+Versioning test text
+====================
+
+So the thing is I need some kind of text - not the lorem ipsum stuff, that
+doesn't work out that well - to test :mod:`sphinx.versioning`. I couldn't find
+a good text for that under public domain so I thought the easiest solution is
+to write one by myself. It's not really interesting, in fact it is *really*
+boring.
+
+So this paragraph is just something I inserted in this document to test if our
+algorithm notices that this paragraph is not just a changed version.
+
+Anyway I need more than one paragraph, at least three for the original
+document, I think, and another one for two different ones.
+
+So the previous paragraph was a bit short because I don't want to test this
+only on long paragraphs, I hope it was short enough to cover most stuff.
+Anyway I see this lacks ``some markup`` so I have to add a **little** bit.
diff --git a/tests/root/versioning/insert_beginning.txt b/tests/root/versioning/insert_beginning.txt
new file mode 100644
index 0000000..57102a7
--- /dev/null
+++ b/tests/root/versioning/insert_beginning.txt
@@ -0,0 +1,18 @@
+Versioning test text
+====================
+
+Apperantly inserting a paragraph at the beginning of a document caused
+problems earlier so this document should be used to test that.
+
+So the thing is I need some kind of text - not the lorem ipsum stuff, that
+doesn't work out that well - to test :mod:`sphinx.versioning`. I couldn't find
+a good text for that under public domain so I thought the easiest solution is
+to write one by myself. It's not really interesting, in fact it is *really*
+boring.
+
+Anyway I need more than one paragraph, at least three for the original
+document, I think, and another one for two different ones.
+
+So the previous paragraph was a bit short because I don't want to test this
+only on long paragraphs, I hope it was short enough to cover most stuff.
+Anyway I see this lacks ``some markup`` so I have to add a **little** bit.
diff --git a/tests/root/versioning/insert_similar.txt b/tests/root/versioning/insert_similar.txt
new file mode 100644
index 0000000..ee9b530
--- /dev/null
+++ b/tests/root/versioning/insert_similar.txt
@@ -0,0 +1,17 @@
+Versioning test text
+====================
+
+So the thing is I need some kind of text - not the lorem ipsum stuff, that
+doesn't work out that well - to test :mod:`sphinx.versioning`. I couldn't find
+a good text for that under public domain so I thought the easiest solution is
+to write one by myself. It's not really interesting, in fact it is *really*
+boring.
+
+Anyway I need more
+
+Anyway I need more than one paragraph, at least three for the original
+document, I think, and another one for two different ones.
+
+So the previous paragraph was a bit short because I don't want to test this
+only on long paragraphs, I hope it was short enough to cover most stuff.
+Anyway I see this lacks ``some markup`` so I have to add a **little** bit.
diff --git a/tests/root/versioning/modified.txt b/tests/root/versioning/modified.txt
new file mode 100644
index 0000000..49cdad9
--- /dev/null
+++ b/tests/root/versioning/modified.txt
@@ -0,0 +1,17 @@
+Versioning test text
+====================
+
+So the thing is I need some kind of text - not the lorem ipsum stuff, that
+doesn't work out that well - to test :mod:`sphinx.versioning`. I couldn't find
+a good text for that under public domain so I thought the easiest solution is
+to write one by myself. Inserting something silly as a modification, btw. have
+you seen the typo below?. It's not really interesting, in fact it is *really*
+boring.
+
+Anyway I need more than one paragraph, at least three for the original
+document, I think, and another one for two different ones. So this is a small
+modification by adding something to this paragraph.
+
+So the previous paragraph was a bit short because I don't want to test this
+only on long paragraphs, I hoep it was short enough to cover most stuff.
+Anyway I see this lacks ``some markup`` so I have to add a **little** bit.
diff --git a/tests/root/versioning/original.txt b/tests/root/versioning/original.txt
new file mode 100644
index 0000000..b3fe060
--- /dev/null
+++ b/tests/root/versioning/original.txt
@@ -0,0 +1,15 @@
+Versioning test text
+====================
+
+So the thing is I need some kind of text - not the lorem ipsum stuff, that
+doesn't work out that well - to test :mod:`sphinx.versioning`. I couldn't find
+a good text for that under public domain so I thought the easiest solution is
+to write one by myself. It's not really interesting, in fact it is *really*
+boring.
+
+Anyway I need more than one paragraph, at least three for the original
+document, I think, and another one for two different ones.
+
+So the previous paragraph was a bit short because I don't want to test this
+only on long paragraphs, I hope it was short enough to cover most stuff.
+Anyway I see this lacks ``some markup`` so I have to add a **little** bit.
diff --git a/tests/root/wrongenc.inc b/tests/root/wrongenc.inc
new file mode 100644
index 0000000..700f613
--- /dev/null
+++ b/tests/root/wrongenc.inc
@@ -0,0 +1,3 @@
+This file is encoded in latin-1 but at first read as utf-8.
+
+Max Strau� a� in M�nchen eine Leberk�ssemmel.
diff --git a/tests/root/ziptheme.zip b/tests/root/ziptheme.zip
new file mode 100644
index 0000000..8a246ed
Binary files /dev/null and b/tests/root/ziptheme.zip differ
diff --git a/tests/roots/test-autosummary/conf.py b/tests/roots/test-autosummary/conf.py
new file mode 100644
index 0000000..542696e
--- /dev/null
+++ b/tests/roots/test-autosummary/conf.py
@@ -0,0 +1,5 @@
+extensions = ['sphinx.ext.autosummary']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+autosummary_generate = True
diff --git a/tests/roots/test-autosummary/contents.rst b/tests/roots/test-autosummary/contents.rst
new file mode 100644
index 0000000..3f16af9
--- /dev/null
+++ b/tests/roots/test-autosummary/contents.rst
@@ -0,0 +1,6 @@
+
+.. autosummary::
+ :nosignatures:
+ :toctree:
+
+ dummy_module
diff --git a/tests/roots/test-autosummary/dummy_module.py b/tests/roots/test-autosummary/dummy_module.py
new file mode 100644
index 0000000..a64035d
--- /dev/null
+++ b/tests/roots/test-autosummary/dummy_module.py
@@ -0,0 +1,71 @@
+"""
+.. autosummary::
+
+ module_attr
+ C.class_attr
+ C.prop_attr1
+ C.prop_attr2
+ C.C2
+"""
+
+def withSentence():
+ '''I have a sentence which
+ spans multiple lines. Then I have
+ more stuff
+ '''
+ pass
+
+def noSentence():
+ '''this doesn't start with a
+ capital. so it's not considered
+ a sentence
+ '''
+ pass
+
+def emptyLine():
+ '''This is the real summary
+
+ However, it did't end with a period.
+ '''
+ pass
+
+
+#: This is a module attribute
+#:
+#: value is integer.
+module_attr = 1
+
+
+class C:
+ '''
+ My C class
+
+ with class_attr attribute
+ '''
+
+ #: This is a class attribute
+ #:
+ #: value is integer.
+ class_attr = 42
+
+ def _prop_attr_get(self):
+ """
+ This is a function docstring
+
+ return value is string.
+ """
+ return 'spam egg'
+
+ prop_attr1 = property(_prop_attr_get)
+
+ prop_attr2 = property(_prop_attr_get)
+ """
+ This is a attribute docstring
+
+ value is string.
+ """
+
+ class C2:
+ '''
+ This is a nested inner class docstring
+ '''
diff --git a/tests/roots/test-docutilsconf/conf.py b/tests/roots/test-docutilsconf/conf.py
new file mode 100644
index 0000000..67074ec
--- /dev/null
+++ b/tests/roots/test-docutilsconf/conf.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+
+project = 'Sphinx docutils conf <Tests>'
+source_suffix = '.txt'
+keep_warnings = True
diff --git a/tests/roots/test-docutilsconf/contents.txt b/tests/roots/test-docutilsconf/contents.txt
new file mode 100644
index 0000000..3d0003b
--- /dev/null
+++ b/tests/roots/test-docutilsconf/contents.txt
@@ -0,0 +1,15 @@
+docutils conf
+=============
+
+field-name-limit
+----------------
+
+:short: desc
+:long long long long: long title
+
+option-limit
+------------
+
+--short short desc
+--long-long-long-long long desc
+
diff --git a/tests/roots/test-docutilsconf/docutils.conf b/tests/roots/test-docutilsconf/docutils.conf
new file mode 100644
index 0000000..e69de29
diff --git a/tests/roots/test-intl/_templates/index.html b/tests/roots/test-intl/_templates/index.html
new file mode 100644
index 0000000..d730545
--- /dev/null
+++ b/tests/roots/test-intl/_templates/index.html
@@ -0,0 +1,10 @@
+{% extends "layout.html" %}
+{% block body %}
+ <h1>{{ _('Welcome') }}</h1>
+ <p>{%trans%}Sphinx {{ version }}{%endtrans%}</p>
+{% endblock %}
+
+{% block comment %}
+utf-8 encoded string: ニシキヘビ
+{% endblock %}
+
diff --git a/tests/roots/test-intl/admonitions.po b/tests/roots/test-intl/admonitions.po
new file mode 100644
index 0000000..0dd1637
--- /dev/null
+++ b/tests/roots/test-intl/admonitions.po
@@ -0,0 +1,81 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2013, test_intl
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-07-03 12:00\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Admonitions"
+msgstr "ADMONITIONS"
+
+msgid "attention title"
+msgstr "ATTENTION TITLE"
+
+msgid "attention body"
+msgstr "ATTENTION BODY"
+
+msgid "caution title"
+msgstr "CAUTION TITLE"
+
+msgid "caution body"
+msgstr "CAUTION BODY"
+
+msgid "danger title"
+msgstr "DANGER TITLE"
+
+msgid "danger body"
+msgstr "DANGER BODY"
+
+msgid "error title"
+msgstr "ERROR TITLE"
+
+msgid "error body"
+msgstr "ERROR BODY"
+
+msgid "hint title"
+msgstr "HINT TITLE"
+
+msgid "hint body"
+msgstr "HINT BODY"
+
+msgid "important title"
+msgstr "IMPORTANT TITLE"
+
+msgid "important body"
+msgstr "IMPORTANT BODY"
+
+msgid "note title"
+msgstr "NOTE TITLE"
+
+msgid "note body"
+msgstr "NOTE BODY"
+
+msgid "tip title"
+msgstr "TIP TITLE"
+
+msgid "tip body"
+msgstr "TIP BODY"
+
+msgid "warning title"
+msgstr "WARNING TITLE"
+
+msgid "warning body"
+msgstr "WARNING BODY"
+
+msgid "admonition title"
+msgstr "ADMONITION TITLE"
+
+msgid "admonition body"
+msgstr "ADMONITION BODY"
+
diff --git a/tests/roots/test-intl/admonitions.txt b/tests/roots/test-intl/admonitions.txt
new file mode 100644
index 0000000..170b8ed
--- /dev/null
+++ b/tests/roots/test-intl/admonitions.txt
@@ -0,0 +1,46 @@
+:tocdepth: 2
+
+Admonitions
+==================
+.. #1206 gettext did not translate admonition directive's title
+
+.. attention:: attention title
+
+ attention body
+
+.. caution:: caution title
+
+ caution body
+
+.. danger:: danger title
+
+ danger body
+
+.. error:: error title
+
+ error body
+
+.. hint:: hint title
+
+ hint body
+
+.. important:: important title
+
+ important body
+
+.. note:: note title
+
+ note body
+
+.. tip:: tip title
+
+ tip body
+
+.. warning:: warning title
+
+ warning body
+
+.. admonition:: admonition title
+
+ admonition body
+
diff --git a/tests/roots/test-intl/bom.po b/tests/roots/test-intl/bom.po
new file mode 100644
index 0000000..c6025eb
--- /dev/null
+++ b/tests/roots/test-intl/bom.po
@@ -0,0 +1,12 @@
+#, fuzzy
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "File with UTF-8 BOM"
+msgstr "Datei mit UTF-8"
+
+msgid "This file has a UTF-8 \"BOM\"."
+msgstr "This file has umlauts: äöü."
diff --git a/tests/roots/test-intl/bom.txt b/tests/roots/test-intl/bom.txt
new file mode 100644
index 0000000..3fea824
--- /dev/null
+++ b/tests/roots/test-intl/bom.txt
@@ -0,0 +1,5 @@
+File with UTF-8 BOM
+===================
+
+This file has a UTF-8 "BOM".
+
diff --git a/tests/roots/test-intl/conf.py b/tests/roots/test-intl/conf.py
new file mode 100644
index 0000000..4c37f77
--- /dev/null
+++ b/tests/roots/test-intl/conf.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+
+project = 'Sphinx intl <Tests>'
+source_suffix = '.txt'
+keep_warnings = True
+templates_path = ['_templates']
+html_additional_pages = {'index': 'index.html'}
+release = version = '2013.120'
diff --git a/tests/roots/test-intl/contents.txt b/tests/roots/test-intl/contents.txt
new file mode 100644
index 0000000..b08fc36
--- /dev/null
+++ b/tests/roots/test-intl/contents.txt
@@ -0,0 +1,23 @@
+CONTENTS
+========
+
+.. toctree::
+ :maxdepth: 2
+ :numbered:
+
+ subdir/contents
+ bom
+ warnings
+ footnote
+ external_links
+ refs_inconsistency
+ literalblock
+ seealso
+ definition_terms
+ figure_caption
+ index_entries
+ role_xref
+ glossary_terms
+ glossary_terms_inconsistency
+ versionchange
+ docfields
diff --git a/tests/roots/test-intl/definition_terms.po b/tests/roots/test-intl/definition_terms.po
new file mode 100644
index 0000000..2c3a3bc
--- /dev/null
+++ b/tests/roots/test-intl/definition_terms.po
@@ -0,0 +1,32 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-01-01 05:00\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with definition terms"
+msgstr "I18N WITH DEFINITION TERMS"
+
+msgid "Some term"
+msgstr "SOME TERM"
+
+msgid "The corresponding definition"
+msgstr "THE CORRESPONDING DEFINITION"
+
+msgid "Some other term"
+msgstr "SOME OTHER TERM"
+
+msgid "The corresponding definition #2"
+msgstr "THE CORRESPONDING DEFINITION #2"
diff --git a/tests/roots/test-intl/definition_terms.txt b/tests/roots/test-intl/definition_terms.txt
new file mode 100644
index 0000000..9891401
--- /dev/null
+++ b/tests/roots/test-intl/definition_terms.txt
@@ -0,0 +1,11 @@
+:tocdepth: 2
+
+i18n with definition terms
+==========================
+
+Some term
+ The corresponding definition
+
+Some other term
+ The corresponding definition #2
+
diff --git a/tests/roots/test-intl/docfields.po b/tests/roots/test-intl/docfields.po
new file mode 100644
index 0000000..f906ca1
--- /dev/null
+++ b/tests/roots/test-intl/docfields.po
@@ -0,0 +1,39 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010, Georg Brandl & Team
+# This file is distributed under the same license as the Sphinx <Tests> package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx <Tests> 0.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-12-16 14:11\n"
+"PO-Revision-Date: 2012-12-18 06:14+0900\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with docfields"
+msgstr "I18N WITH DOCFIELDS"
+
+msgid "description of parameter param"
+msgstr "DESCRIPTION OF PARAMETER param"
+
+msgid "description of parameter foo"
+msgstr "DESCRIPTION OF PARAMETER foo"
+
+msgid "description of parameter bar"
+msgstr "DESCRIPTION OF PARAMETER bar"
+
+msgid "if the values are not valid"
+msgstr "IF THE VALUES ARE NOT VALID"
+
+msgid "if the values are out of range"
+msgstr "IF THE VALUES ARE OUT OF RANGE"
+
+msgid "a new :class:`Cls3` instance"
+msgstr "A NEW :class:`Cls3` INSTANCE"
+
diff --git a/tests/roots/test-intl/docfields.txt b/tests/roots/test-intl/docfields.txt
new file mode 100644
index 0000000..e4dab8e
--- /dev/null
+++ b/tests/roots/test-intl/docfields.txt
@@ -0,0 +1,46 @@
+:tocdepth: 2
+
+i18n with docfields
+===================
+
+.. single TypedField
+
+.. class:: Cls1
+ :noindex:
+
+ :param param: description of parameter param
+
+.. grouped TypedFields
+
+.. class:: Cls2
+ :noindex:
+
+ :param foo: description of parameter foo
+ :param bar: description of parameter bar
+
+
+.. single GroupedField
+
+.. class:: Cls3(values)
+ :noindex:
+
+ :raises ValueError: if the values are out of range
+
+.. grouped GroupedFields
+
+.. class:: Cls4(values)
+ :noindex:
+
+ :raises TypeError: if the values are not valid
+ :raises ValueError: if the values are out of range
+
+
+.. single Field
+
+.. class:: Cls5
+ :noindex:
+
+ :returns: a new :class:`Cls3` instance
+
+.. Field is never grouped
+
diff --git a/tests/roots/test-intl/external_links.po b/tests/roots/test-intl/external_links.po
new file mode 100644
index 0000000..e4e6764
--- /dev/null
+++ b/tests/roots/test-intl/external_links.po
@@ -0,0 +1,47 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-11-22 08:28\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with external links"
+msgstr "EXTERNAL LINKS"
+
+msgid "External link to Python_."
+msgstr "EXTERNAL LINK TO Python_."
+
+msgid "Internal link to `i18n with external links`_."
+msgstr "`EXTERNAL LINKS`_ IS INTERNAL LINK."
+
+msgid "Inline link by `Sphinx Site <http://sphinx-doc.org>`_."
+msgstr "INLINE LINK BY `THE SPHINX SITE <http://sphinx-doc.org>`_."
+
+msgid "Unnamed link__."
+msgstr "UNNAMED LINK__."
+
+msgid "link target swapped translation"
+msgstr "LINK TARGET SWAPPED TRANSLATION"
+
+msgid "link to external1_ and external2_."
+msgstr "LINK TO external2_ AND external1_."
+
+msgid "link to `Sphinx Site <http://sphinx-doc.org>`_ and `Python Site <http://python.org>`_."
+msgstr "LINK TO `THE PYTHON SITE <http://python.org>`_ AND `THE SPHINX SITE <http://sphinx-doc.org>`_."
+
+msgid "Multiple references in the same line"
+msgstr "MULTIPLE REFERENCES IN THE SAME LINE"
+
+msgid "Link to `Sphinx Site <http://sphinx-doc.org>`_, `Python Site <http://python.org>`_, Python_, Unnamed__ and `i18n with external links`_."
+msgstr "LINK TO `EXTERNAL LINKS`_, Python_, `THE SPHINX SITE <http://sphinx-doc.org>`_, UNNAMED__ AND `THE PYTHON SITE <http://python.org>`_."
diff --git a/tests/roots/test-intl/external_links.txt b/tests/roots/test-intl/external_links.txt
new file mode 100644
index 0000000..96e3973
--- /dev/null
+++ b/tests/roots/test-intl/external_links.txt
@@ -0,0 +1,35 @@
+:tocdepth: 2
+
+i18n with external links
+========================
+.. #1044 external-links-dont-work-in-localized-html
+
+External link to Python_.
+
+Internal link to `i18n with external links`_.
+
+Inline link by `Sphinx Site <http://sphinx-doc.org>`_.
+
+Unnamed link__.
+
+.. _Python: http://python.org/index.html
+.. __: http://google.com
+
+
+link target swapped translation
+================================
+
+link to external1_ and external2_.
+
+link to `Sphinx Site <http://sphinx-doc.org>`_ and `Python Site <http://python.org>`_.
+
+.. _external1: http://example.com/external1
+.. _external2: http://example.com/external2
+
+
+Multiple references in the same line
+=====================================
+
+Link to `Sphinx Site <http://sphinx-doc.org>`_, `Python Site <http://python.org>`_, Python_, Unnamed__ and `i18n with external links`_.
+
+.. __: http://google.com
diff --git a/tests/roots/test-intl/figure_caption.po b/tests/roots/test-intl/figure_caption.po
new file mode 100644
index 0000000..2b85aea
--- /dev/null
+++ b/tests/roots/test-intl/figure_caption.po
@@ -0,0 +1,35 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-01-04 7:00\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with figure caption"
+msgstr "I18N WITH FIGURE CAPTION"
+
+msgid "My caption of the figure"
+msgstr "MY CAPTION OF THE FIGURE"
+
+msgid "My description paragraph1 of the figure."
+msgstr "MY DESCRIPTION PARAGRAPH1 OF THE FIGURE."
+
+msgid "My description paragraph2 of the figure."
+msgstr "MY DESCRIPTION PARAGRAPH2 OF THE FIGURE."
+
+msgid "figure in the block"
+msgstr "FIGURE IN THE BLOCK"
+
+msgid "block"
+msgstr "BLOCK"
diff --git a/tests/roots/test-intl/figure_caption.txt b/tests/roots/test-intl/figure_caption.txt
new file mode 100644
index 0000000..0f978b5
--- /dev/null
+++ b/tests/roots/test-intl/figure_caption.txt
@@ -0,0 +1,26 @@
+:tocdepth: 2
+
+i18n with figure caption
+========================
+
+.. figure:: i18n.png
+
+ My caption of the figure
+
+ My description paragraph1 of the figure.
+
+ My description paragraph2 of the figure.
+
+figure in the block
+---------------------
+
+block
+
+ .. figure:: i18n.png
+
+ My caption of the figure
+
+ My description paragraph1 of the figure.
+
+ My description paragraph2 of the figure.
+
diff --git a/tests/roots/test-intl/footnote.po b/tests/roots/test-intl/footnote.po
new file mode 100644
index 0000000..b3876f5
--- /dev/null
+++ b/tests/roots/test-intl/footnote.po
@@ -0,0 +1,36 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-11-22 08:28\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with Footnote"
+msgstr "I18N WITH FOOTNOTE"
+
+msgid "[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_ [#named]_."
+msgstr "`I18N WITH FOOTNOTE`_ INCLUDE THIS CONTENTS [#named]_ [ref]_ [#]_ [100]_."
+
+msgid "This is a auto numbered footnote."
+msgstr "THIS IS A AUTO NUMBERED FOOTNOTE."
+
+msgid "This is a named footnote."
+msgstr "THIS IS A NAMED FOOTNOTE."
+
+msgid "This is a numbered footnote."
+msgstr "THIS IS A NUMBERED FOOTNOTE."
+
+msgid "This is a auto numbered named footnote."
+msgstr "THIS IS A AUTO NUMBERED NAMED FOOTNOTE."
+
diff --git a/tests/roots/test-intl/footnote.txt b/tests/roots/test-intl/footnote.txt
new file mode 100644
index 0000000..55da9c6
--- /dev/null
+++ b/tests/roots/test-intl/footnote.txt
@@ -0,0 +1,12 @@
+:tocdepth: 2
+
+i18n with Footnote
+==================
+.. #955 cant-build-html-with-footnotes-when-using
+
+[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_ [#named]_.
+
+.. [#] This is a auto numbered footnote.
+.. [ref] This is a named footnote.
+.. [100] This is a numbered footnote.
+.. [#named] This is a auto numbered named footnote.
diff --git a/tests/roots/test-intl/glossary_terms.po b/tests/roots/test-intl/glossary_terms.po
new file mode 100644
index 0000000..1ffcaeb
--- /dev/null
+++ b/tests/roots/test-intl/glossary_terms.po
@@ -0,0 +1,35 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-01-29 14:10\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with glossary terms"
+msgstr "I18N WITH GLOSSARY TERMS"
+
+msgid "Some term"
+msgstr "SOME NEW TERM"
+
+msgid "The corresponding glossary"
+msgstr "THE CORRESPONDING GLOSSARY"
+
+msgid "Some other term"
+msgstr "SOME OTHER NEW TERM"
+
+msgid "The corresponding glossary #2"
+msgstr "THE CORRESPONDING GLOSSARY #2"
+
+msgid "link to :term:`Some term`."
+msgstr "LINK TO :term:`SOME NEW TERM`."
diff --git a/tests/roots/test-intl/glossary_terms.txt b/tests/roots/test-intl/glossary_terms.txt
new file mode 100644
index 0000000..a6e16c9
--- /dev/null
+++ b/tests/roots/test-intl/glossary_terms.txt
@@ -0,0 +1,14 @@
+:tocdepth: 2
+
+i18n with glossary terms
+========================
+
+.. glossary::
+
+ Some term
+ The corresponding glossary
+
+ Some other term
+ The corresponding glossary #2
+
+link to :term:`Some term`.
diff --git a/tests/roots/test-intl/glossary_terms_inconsistency.po b/tests/roots/test-intl/glossary_terms_inconsistency.po
new file mode 100644
index 0000000..5e30165
--- /dev/null
+++ b/tests/roots/test-intl/glossary_terms_inconsistency.po
@@ -0,0 +1,23 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-01-29 14:10\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with glossary terms inconsistency"
+msgstr "I18N WITH GLOSSARY TERMS INCONSISTENCY"
+
+msgid "link to :term:`Some term` and :term:`Some other term`."
+msgstr "LINK TO :term:`SOME NEW TERM`."
diff --git a/tests/roots/test-intl/glossary_terms_inconsistency.txt b/tests/roots/test-intl/glossary_terms_inconsistency.txt
new file mode 100644
index 0000000..837411b
--- /dev/null
+++ b/tests/roots/test-intl/glossary_terms_inconsistency.txt
@@ -0,0 +1,6 @@
+:tocdepth: 2
+
+i18n with glossary terms inconsistency
+======================================
+
+1. link to :term:`Some term` and :term:`Some other term`.
diff --git a/tests/roots/test-intl/i18n.png b/tests/roots/test-intl/i18n.png
new file mode 100644
index 0000000..72c12d1
Binary files /dev/null and b/tests/roots/test-intl/i18n.png differ
diff --git a/tests/roots/test-intl/index_entries.po b/tests/roots/test-intl/index_entries.po
new file mode 100644
index 0000000..6da9a81
--- /dev/null
+++ b/tests/roots/test-intl/index_entries.po
@@ -0,0 +1,77 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2013, foo
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: foo foo\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-01-05 18:10\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with index entries"
+msgstr ""
+
+msgid "index target section"
+msgstr ""
+
+msgid "this is :index:`Newsletter` target paragraph."
+msgstr "THIS IS :index:`NEWSLETTER` TARGET PARAGRAPH."
+
+msgid "various index entries"
+msgstr ""
+
+msgid "That's all."
+msgstr ""
+
+msgid "Mailing List"
+msgstr "MAILING LIST"
+
+msgid "Newsletter"
+msgstr "NEWSLETTER"
+
+msgid "Recipients List"
+msgstr "RECIPIENTS LIST"
+
+msgid "First"
+msgstr "FIRST"
+
+msgid "Second"
+msgstr "SECOND"
+
+msgid "Third"
+msgstr "THIRD"
+
+msgid "Entry"
+msgstr "ENTRY"
+
+msgid "See"
+msgstr "SEE"
+
+msgid "Module"
+msgstr "MODULE"
+
+msgid "Keyword"
+msgstr "KEYWORD"
+
+msgid "Operator"
+msgstr "OPERATOR"
+
+msgid "Object"
+msgstr "OBJECT"
+
+msgid "Exception"
+msgstr "EXCEPTION"
+
+msgid "Statement"
+msgstr "STATEMENT"
+
+msgid "Builtin"
+msgstr "BUILTIN"
diff --git a/tests/roots/test-intl/index_entries.txt b/tests/roots/test-intl/index_entries.txt
new file mode 100644
index 0000000..c914a4b
--- /dev/null
+++ b/tests/roots/test-intl/index_entries.txt
@@ -0,0 +1,31 @@
+:tocdepth: 2
+
+i18n with index entries
+=======================
+
+.. index::
+ single: Mailing List
+ pair: Newsletter; Recipients List
+
+index target section
+--------------------
+
+this is :index:`Newsletter` target paragraph.
+
+
+various index entries
+---------------------
+
+.. index::
+ triple: First; Second; Third
+ see: Entry; Mailing List
+ seealso: See; Newsletter
+ module: Module
+ keyword: Keyword
+ operator: Operator
+ object: Object
+ exception: Exception
+ statement: Statement
+ builtin: Builtin
+
+That's all.
diff --git a/tests/roots/test-intl/label_target.po b/tests/roots/test-intl/label_target.po
new file mode 100644
index 0000000..60d7c3e
--- /dev/null
+++ b/tests/roots/test-intl/label_target.po
@@ -0,0 +1,66 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2013, sphinx
+# This file is distributed under the same license as the sphinx package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: 1.2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-06-19 00:33+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "section and label"
+msgstr "X SECTION AND LABEL"
+
+msgid ""
+":ref:`implicit-target` point to ``implicit-target`` and "
+"`section and label`_ point to ``section-and-label``."
+msgstr ""
+":ref:`implicit-target` POINT TO ``implicit-target`` AND "
+"`X SECTION AND LABEL`_ POINT TO ``section-and-label``."
+
+msgid "explicit-target"
+msgstr "X EXPLICIT-TARGET"
+
+msgid ""
+":ref:`explicit-target` point to ``explicit-target`` and `explicit-target`_"
+" point to duplicated id like ``id1``."
+msgstr ""
+":ref:`explicit-target` POINT TO ``explicit-target`` AND `X EXPLICIT-TARGET`_"
+" POINT TO DUPLICATED ID LIKE ``id1``."
+
+msgid "implicit section name"
+msgstr "X IMPLICIT SECTION NAME"
+
+msgid "`implicit section name`_ point to ``implicit-section-name``."
+msgstr "`X IMPLICIT SECTION NAME`_ POINT TO ``implicit-section-name``."
+
+msgid "duplicated sub section"
+msgstr "X DUPLICATED SUB SECTION"
+
+msgid ""
+"`duplicated sub section`_ is broken link."
+msgstr ""
+"`X DUPLICATED SUB SECTION`_ IS BROKEN LINK."
+
+msgid "label bridged target section"
+msgstr "X LABEL BRIDGED TARGET SECTION"
+
+msgid "`bridge label`_ is not translatable but linked to translated section title."
+msgstr "X `bridge label`_ IS NOT TRANSLATABLE BUT LINKED TO TRANSLATED SECTION TITLE."
+
+msgid ""
+"`bridge label2`_ point to ``section and label`` and `bridge label`_ point to "
+"``label bridged target section``. The second appeared `bridge label2`_ point "
+"to correct target."
+msgstr ""
+"X `bridge label`_ POINT TO ``LABEL BRIDGED TARGET SECTION`` AND "
+"`bridge label2`_ POINT TO ``SECTION AND LABEL``. THE SECOND APPEARED "
+"`bridge label2`_ POINT TO CORRECT TARGET."
diff --git a/tests/roots/test-intl/label_target.txt b/tests/roots/test-intl/label_target.txt
new file mode 100644
index 0000000..ac00084
--- /dev/null
+++ b/tests/roots/test-intl/label_target.txt
@@ -0,0 +1,67 @@
+:tocdepth: 2
+
+.. _implicit-target:
+
+section and label
+==================
+
+.. This section's label and section title are different.
+.. This case, the section have 2 target id.
+
+:ref:`implicit-target` point to ``implicit-target`` and
+`section and label`_ point to ``section-and-label``.
+
+
+.. _explicit-target:
+
+explicit-target
+================
+
+.. This section's label equals to section title.
+.. This case, a duplicated target id is generated by docutils.
+
+:ref:`explicit-target` point to ``explicit-target`` and
+`explicit-target`_ point to duplicated id like ``id1``.
+
+
+implicit section name
+======================
+
+.. This section have no label.
+.. This case, the section have one id.
+
+`implicit section name`_ point to ``implicit-section-name``.
+
+duplicated sub section
+------------------------
+
+.. This section have no label, but name will be duplicated by next section.
+.. This case, the section have one id.
+
+`duplicated sub section`_ is broken link.
+
+.. There is no way to link to this section's ``duplicated-sub-section``` by
+.. using formal reStructuredText markup.
+
+duplicated sub section
+------------------------
+
+.. This section have no label, but the section was a duplicate name.
+.. This case, a duplicated target id is generated by docutils.
+
+.. There is no way to link to this section's duplicated id like ``id2`` by
+.. using formal reStructuredText markup.
+
+
+.. _bridge label: `label bridged target section`_
+.. _bridge label2: `section and label`_
+
+label bridged target section
+=============================
+
+.. This section is targeted through label definition.
+
+`bridge label`_ is not translatable but linked to translated section title.
+
+`bridge label2`_ point to ``section and label`` and `bridge label`_ point to ``label bridged target section``. The second appeared `bridge label2`_ point to correct target.
+
diff --git a/tests/roots/test-intl/literalblock.po b/tests/roots/test-intl/literalblock.po
new file mode 100644
index 0000000..8ea83b3
--- /dev/null
+++ b/tests/roots/test-intl/literalblock.po
@@ -0,0 +1,30 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-11-22 08:28\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with literal block"
+msgstr "I18N WITH LITERAL BLOCK"
+
+msgid "Correct literal block::"
+msgstr "CORRECT LITERAL BLOCK::"
+
+msgid "Missing literal block::"
+msgstr "MISSING LITERAL BLOCK::"
+
+msgid "That's all."
+msgstr "THAT'S ALL."
+
diff --git a/tests/roots/test-intl/literalblock.txt b/tests/roots/test-intl/literalblock.txt
new file mode 100644
index 0000000..c9c7109
--- /dev/null
+++ b/tests/roots/test-intl/literalblock.txt
@@ -0,0 +1,13 @@
+:tocdepth: 2
+
+i18n with literal block
+=========================
+
+Correct literal block::
+
+ this is
+ literal block
+
+Missing literal block::
+
+That's all.
diff --git a/tests/roots/test-intl/refs_inconsistency.po b/tests/roots/test-intl/refs_inconsistency.po
new file mode 100644
index 0000000..9cab687
--- /dev/null
+++ b/tests/roots/test-intl/refs_inconsistency.po
@@ -0,0 +1,39 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-12-05 08:28\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with refs inconsistency"
+msgstr "I18N WITH REFS INCONSISTENCY"
+
+msgid "[100]_ for [#]_ footnote [ref2]_."
+msgstr "FOR FOOTNOTE [ref2]_."
+
+msgid "for reference_."
+msgstr "reference_ FOR reference_."
+
+msgid "normal text."
+msgstr "ORPHAN REFERENCE: `I18N WITH REFS INCONSISTENCY`_."
+
+msgid "This is a auto numbered footnote."
+msgstr "THIS IS A AUTO NUMBERED FOOTNOTE."
+
+msgid "This is a named footnote."
+msgstr "THIS IS A NAMED FOOTNOTE."
+
+msgid "This is a numbered footnote."
+msgstr "THIS IS A NUMBERED FOOTNOTE."
+
diff --git a/tests/roots/test-intl/refs_inconsistency.txt b/tests/roots/test-intl/refs_inconsistency.txt
new file mode 100644
index 0000000..c65c5b4
--- /dev/null
+++ b/tests/roots/test-intl/refs_inconsistency.txt
@@ -0,0 +1,13 @@
+:tocdepth: 2
+
+i18n with refs inconsistency
+=============================
+
+* [100]_ for [#]_ footnote [ref2]_.
+* for reference_.
+* normal text.
+
+.. [#] This is a auto numbered footnote.
+.. [ref2] This is a named footnote.
+.. [100] This is a numbered footnote.
+.. _reference: http://www.example.com
diff --git a/tests/roots/test-intl/refs_python_domain.po b/tests/roots/test-intl/refs_python_domain.po
new file mode 100644
index 0000000..bed87c4
--- /dev/null
+++ b/tests/roots/test-intl/refs_python_domain.po
@@ -0,0 +1,25 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: issue1363 1363\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-03-16 19:34+0900\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ..\..\index.rst:4
+msgid "i18n with python domain refs"
+msgstr "I18N WITH PYTHON DOMAIN REFS"
+
+#: ..\..\index.rst:8
+msgid "See this decorator: :func:`sensitive_variables`."
+msgstr "SEE THIS DECORATOR: :func:`sensitive_variables`."
+
+#: ..\..\index.rst:12
+msgid "Some description"
+msgstr "SOME DESCRIPTION"
+
diff --git a/tests/roots/test-intl/refs_python_domain.txt b/tests/roots/test-intl/refs_python_domain.txt
new file mode 100644
index 0000000..20a8bc5
--- /dev/null
+++ b/tests/roots/test-intl/refs_python_domain.txt
@@ -0,0 +1,15 @@
+:tocdepth: 2
+
+i18n with python domain refs
+=============================
+
+.. currentmodule:: sensitive
+
+See this decorator: :func:`sensitive_variables`.
+
+.. function:: sensitive_variables(*variables)
+
+ Some description
+
+.. currentmodule:: reporting
+
diff --git a/tests/roots/test-intl/role_xref.po b/tests/roots/test-intl/role_xref.po
new file mode 100644
index 0000000..8730c49
--- /dev/null
+++ b/tests/roots/test-intl/role_xref.po
@@ -0,0 +1,47 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-04 14:00\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n role xref"
+msgstr "I18N ROCK'N ROLE XREF"
+
+msgid "link to :term:`Some term`, :ref:`i18n-role-xref`, :doc:`contents`."
+msgstr "LINK TO :ref:`i18n-role-xref`, :doc:`contents`, :term:`SOME NEW TERM`."
+
+msgid "same type links"
+msgstr "SAME TYPE LINKS"
+
+msgid "link to :term:`Some term` and :term:`Some other term`."
+msgstr "LINK TO :term:`SOME OTHER NEW TERM` AND :term:`SOME NEW TERM`."
+
+msgid "link to :ref:`i18n-role-xref` and :ref:`same-type-links`."
+msgstr "LINK TO :ref:`same-type-links` AND :ref:`i18n-role-xref`."
+
+msgid "link to :doc:`contents` and :doc:`glossary_terms`."
+msgstr "LINK TO :doc:`glossary_terms` AND :doc:`contents`."
+
+msgid "link to :option:`-m` and :option:`--module`."
+msgstr "LINK TO :option:`--module` AND :option:`-m`."
+
+msgid "link to :envvar:`env1` and :envvar:`env2`."
+msgstr "LINK TO :envvar:`env2` AND :envvar:`env1`."
+
+msgid "link to :token:`token1` and :token:`token2`."
+msgstr "LINK TO :token:`token2` AND :token:`token1`."
+
+msgid "link to :keyword:`i18n-role-xref` and :keyword:`same-type-links`."
+msgstr "LINK TO :keyword:`same-type-links` AND :keyword:`i18n-role-xref`."
diff --git a/tests/roots/test-intl/role_xref.txt b/tests/roots/test-intl/role_xref.txt
new file mode 100644
index 0000000..b3d42d1
--- /dev/null
+++ b/tests/roots/test-intl/role_xref.txt
@@ -0,0 +1,40 @@
+:tocdepth: 2
+
+.. _i18n-role-xref:
+
+i18n role xref
+==============
+
+link to :term:`Some term`, :ref:`i18n-role-xref`, :doc:`contents`.
+
+.. _same-type-links:
+
+same type links
+=================
+
+link to :term:`Some term` and :term:`Some other term`.
+
+link to :ref:`i18n-role-xref` and :ref:`same-type-links`.
+
+link to :doc:`contents` and :doc:`glossary_terms`.
+
+link to :option:`-m` and :option:`--module`.
+
+link to :envvar:`env1` and :envvar:`env2`.
+
+link to :token:`token1` and :token:`token2`.
+
+link to :keyword:`i18n-role-xref` and :keyword:`same-type-links`.
+
+
+.. option:: -m <module>
+
+.. option:: --module <module>
+
+.. envvar:: env1
+
+.. envvar:: env2
+
+.. productionlist::
+ token_stmt: `token1` ":" `token2`
+
diff --git a/tests/roots/test-intl/rubric.po b/tests/roots/test-intl/rubric.po
new file mode 100644
index 0000000..2c1214b
--- /dev/null
+++ b/tests/roots/test-intl/rubric.po
@@ -0,0 +1,29 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-11-12 7:00\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with rubric"
+msgstr "I18N WITH RUBRIC"
+
+msgid "rubric title"
+msgstr "RUBRIC TITLE"
+
+msgid "rubric in the block"
+msgstr "RUBRIC IN THE BLOCK"
+
+msgid "block"
+msgstr "BLOCK"
diff --git a/tests/roots/test-intl/rubric.txt b/tests/roots/test-intl/rubric.txt
new file mode 100644
index 0000000..f285d49
--- /dev/null
+++ b/tests/roots/test-intl/rubric.txt
@@ -0,0 +1,14 @@
+:tocdepth: 2
+
+i18n with rubric
+================
+
+.. rubric:: rubric title
+
+rubric in the block
+-------------------
+
+block
+
+ .. rubric:: rubric title
+
diff --git a/tests/roots/test-intl/seealso.po b/tests/roots/test-intl/seealso.po
new file mode 100644
index 0000000..d3b27e5
--- /dev/null
+++ b/tests/roots/test-intl/seealso.po
@@ -0,0 +1,33 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010, Georg Brandl & Team
+# This file is distributed under the same license as the Sphinx <Tests> package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx <Tests> 0.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-12-16 06:06\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with seealso"
+msgstr "I18N WITH SEEALSO"
+
+msgid "short text 1"
+msgstr "SHORT TEXT 1"
+
+msgid "long text 1"
+msgstr "LONG TEXT 1"
+
+msgid "short text 2"
+msgstr "SHORT TEXT 2"
+
+msgid "long text 2"
+msgstr "LONG TEXT 2"
+
diff --git a/tests/roots/test-intl/seealso.txt b/tests/roots/test-intl/seealso.txt
new file mode 100644
index 0000000..ed88599
--- /dev/null
+++ b/tests/roots/test-intl/seealso.txt
@@ -0,0 +1,15 @@
+:tocdepth: 2
+
+i18n with seealso
+============================
+.. #960 directive-seelaso-ignored-in-the-gettext
+
+.. seealso:: short text 1
+
+.. seealso::
+
+ long text 1
+
+.. seealso:: short text 2
+
+ long text 2
diff --git a/tests/roots/test-intl/sphinx.po b/tests/roots/test-intl/sphinx.po
new file mode 100644
index 0000000..cac5d4a
--- /dev/null
+++ b/tests/roots/test-intl/sphinx.po
@@ -0,0 +1,23 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-11-22 08:28\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Welcome"
+msgstr "WELCOME"
+
+msgid "Sphinx %(version)s"
+msgstr "SPHINX %(version)s"
diff --git a/tests/roots/test-intl/subdir/contents.txt b/tests/roots/test-intl/subdir/contents.txt
new file mode 100644
index 0000000..b6509ba
--- /dev/null
+++ b/tests/roots/test-intl/subdir/contents.txt
@@ -0,0 +1,2 @@
+subdir contents
+===============
diff --git a/tests/roots/test-intl/versionchange.po b/tests/roots/test-intl/versionchange.po
new file mode 100644
index 0000000..911d3d9
--- /dev/null
+++ b/tests/roots/test-intl/versionchange.po
@@ -0,0 +1,33 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010, Georg Brandl & Team
+# This file is distributed under the same license as the Sphinx <Tests> package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-12-15 03:17\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with versionchange"
+msgstr "I18N WITH VERSIONCHANGE"
+
+msgid "This is the *first* paragraph of deprecated."
+msgstr "THIS IS THE *FIRST* PARAGRAPH OF DEPRECATED."
+
+msgid "This is the *second* paragraph of deprecated."
+msgstr "THIS IS THE *SECOND* PARAGRAPH OF DEPRECATED."
+
+msgid "This is the *first* paragraph of versionadded."
+msgstr "THIS IS THE *FIRST* PARAGRAPH OF VERSIONADDED."
+
+msgid "This is the *first* paragraph of versionchanged."
+msgstr "THIS IS THE *FIRST* PARAGRAPH OF VERSIONCHANGED."
+
diff --git a/tests/roots/test-intl/versionchange.txt b/tests/roots/test-intl/versionchange.txt
new file mode 100644
index 0000000..4c57e14
--- /dev/null
+++ b/tests/roots/test-intl/versionchange.txt
@@ -0,0 +1,16 @@
+:tocdepth: 2
+
+i18n with versionchange
+============================
+
+.. deprecated:: 1.0
+ This is the *first* paragraph of deprecated.
+
+ This is the *second* paragraph of deprecated.
+
+.. versionadded:: 1.0
+ This is the *first* paragraph of versionadded.
+
+.. versionchanged:: 1.0
+
+ This is the *first* paragraph of versionchanged.
diff --git a/tests/roots/test-intl/warnings.po b/tests/roots/test-intl/warnings.po
new file mode 100644
index 0000000..bf82510
--- /dev/null
+++ b/tests/roots/test-intl/warnings.po
@@ -0,0 +1,23 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010, Georg Brandl & Team
+# This file is distributed under the same license as the Sphinx <Tests> package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx <Tests> 0.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-04 13:06\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with reST warnings"
+msgstr "I18N WITH REST WARNINGS"
+
+msgid "line of ``literal`` markup."
+msgstr "LINE OF ``BROKEN LITERAL MARKUP."
diff --git a/tests/roots/test-intl/warnings.txt b/tests/roots/test-intl/warnings.txt
new file mode 100644
index 0000000..a80fe18
--- /dev/null
+++ b/tests/roots/test-intl/warnings.txt
@@ -0,0 +1,5 @@
+i18n with reST warnings
+========================
+
+line of ``literal`` markup.
+
diff --git a/tests/roots/test-only-directive/conf.py b/tests/roots/test-only-directive/conf.py
new file mode 100644
index 0000000..bcb4305
--- /dev/null
+++ b/tests/roots/test-only-directive/conf.py
@@ -0,0 +1,2 @@
+
+project = 'test-only-directive'
diff --git a/tests/roots/test-only-directive/contents.rst b/tests/roots/test-only-directive/contents.rst
new file mode 100644
index 0000000..9a93be9
--- /dev/null
+++ b/tests/roots/test-only-directive/contents.rst
@@ -0,0 +1,6 @@
+test-only-directive
+===================
+
+.. toctree::
+
+ only
diff --git a/tests/roots/test-only-directive/only.rst b/tests/roots/test-only-directive/only.rst
new file mode 100644
index 0000000..4a3eb48
--- /dev/null
+++ b/tests/roots/test-only-directive/only.rst
@@ -0,0 +1,203 @@
+
+1. Sections in only directives
+==============================
+
+Testing sections in only directives.
+
+.. only:: nonexisting_tag
+
+ Skipped Section
+ ---------------
+ Should not be here.
+
+.. only:: not nonexisting_tag
+
+ 1.1. Section
+ ------------
+ Should be here.
+
+1.2. Section
+------------
+
+.. only:: not nonexisting_tag
+
+ 1.2.1. Subsection
+ ~~~~~~~~~~~~~~~~~
+ Should be here.
+
+.. only:: nonexisting_tag
+
+ Skipped Subsection
+ ~~~~~~~~~~~~~~~~~~
+ Should not be here.
+
+1.3. Section
+------------
+
+1.3.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.4. Section
+------------
+
+.. only:: not nonexisting_tag
+
+ 1.4.1. Subsection
+ ~~~~~~~~~~~~~~~~~
+ Should be here.
+
+1.5. Section
+------------
+
+.. only:: not nonexisting_tag
+
+ 1.5.1. Subsection
+ ~~~~~~~~~~~~~~~~~
+ Should be here.
+
+1.5.2. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.6. Section
+------------
+
+1.6.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.6.2. Subsection
+ ~~~~~~~~~~~~~~~~~
+ Should be here.
+
+1.6.3. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.7. Section
+------------
+
+1.7.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.7.1.1. Subsubsection
+ ......................
+ Should be here.
+
+1.8. Section
+------------
+
+1.8.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.8.1.1. Subsubsection
+......................
+Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.8.1.2. Subsubsection
+ ......................
+ Should be here.
+
+1.9. Section
+------------
+
+.. only:: nonexisting_tag
+
+ Skipped Subsection
+ ~~~~~~~~~~~~~~~~~~
+
+1.9.1. Subsection
+~~~~~~~~~~~~~~~~~
+Should be here.
+
+1.9.1.1. Subsubsection
+......................
+Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.10. Section
+ -------------
+ Should be here.
+
+1.11. Section
+-------------
+
+Text before subsection 11.1.
+
+.. only:: not nonexisting_tag
+
+ More text before subsection 11.1.
+
+ 1.11.1. Subsection
+ ~~~~~~~~~~~~~~~~~~
+ Should be here.
+
+Text after subsection 11.1.
+
+.. only:: not nonexisting_tag
+
+ 1.12. Section
+ -------------
+ Should be here.
+
+ 1.12.1. Subsection
+ ~~~~~~~~~~~~~~~~~~
+ Should be here.
+
+ 1.13. Section
+ -------------
+ Should be here.
+
+.. only:: not nonexisting_tag
+
+ 1.14. Section
+ -------------
+ Should be here.
+
+ .. only:: not nonexisting_tag
+
+ 1.14.1. Subsection
+ ~~~~~~~~~~~~~~~~~~
+ Should be here.
+
+ 1.15. Section
+ -------------
+ Should be here.
+
+.. only:: nonexisting_tag
+
+ Skipped document level heading
+ ==============================
+ Should not be here.
+
+.. only:: not nonexisting_tag
+
+ 2. Included document level heading
+ ==================================
+ Should be here.
+
+3. Document level heading
+=========================
+Should be here.
+
+.. only:: nonexisting_tag
+
+ Skipped document level heading
+ ==============================
+ Should not be here.
+
+.. only:: not nonexisting_tag
+
+ 4. Another included document level heading
+ ==========================================
+ Should be here.
diff --git a/tests/roots/test-setup/doc/conf.py b/tests/roots/test-setup/doc/conf.py
new file mode 100644
index 0000000..a55679a
--- /dev/null
+++ b/tests/roots/test-setup/doc/conf.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+
+project = 'Sphinx smallest project'
+source_suffix = '.txt'
+keep_warnings = True
diff --git a/tests/roots/test-setup/doc/contents.txt b/tests/roots/test-setup/doc/contents.txt
new file mode 100644
index 0000000..cb52405
--- /dev/null
+++ b/tests/roots/test-setup/doc/contents.txt
@@ -0,0 +1,5 @@
+contents
+=========
+
+spam egg ham
+
diff --git a/tests/roots/test-setup/setup.cfg b/tests/roots/test-setup/setup.cfg
new file mode 100644
index 0000000..cf2a7f5
--- /dev/null
+++ b/tests/roots/test-setup/setup.cfg
@@ -0,0 +1,5 @@
+[build_sphinx]
+project = 'My project'
+version = 1.2
+release = 1.2.0
+source-dir = doc
diff --git a/tests/roots/test-setup/setup.py b/tests/roots/test-setup/setup.py
new file mode 100644
index 0000000..3ba5b6f
--- /dev/null
+++ b/tests/roots/test-setup/setup.py
@@ -0,0 +1,9 @@
+from distutils.core import setup
+from sphinx.setup_command import BuildDoc
+
+cmdclass = {'build_sphinx': BuildDoc}
+
+setup(
+ name='sphinxdoc',
+ cmdclass=cmdclass,
+)
diff --git a/tests/roots/test-templating/_templates/autosummary/class.rst b/tests/roots/test-templating/_templates/autosummary/class.rst
new file mode 100644
index 0000000..7f15361
--- /dev/null
+++ b/tests/roots/test-templating/_templates/autosummary/class.rst
@@ -0,0 +1,8 @@
+{% extends "!autosummary/class.rst" %}
+
+{% block methods %}
+
+ .. note:: autosummary/class.rst method block overloading
+
+ {{ super() }}
+{% endblock %}
diff --git a/tests/roots/test-templating/_templates/layout.html b/tests/roots/test-templating/_templates/layout.html
new file mode 100644
index 0000000..f836c77
--- /dev/null
+++ b/tests/roots/test-templating/_templates/layout.html
@@ -0,0 +1,6 @@
+{% extends "!layout.html" %}
+
+{% block extrahead %}
+<!-- layout overloading -->
+{{ super() }}
+{% endblock %}
diff --git a/tests/roots/test-templating/autosummary_templating.txt b/tests/roots/test-templating/autosummary_templating.txt
new file mode 100644
index 0000000..05643a0
--- /dev/null
+++ b/tests/roots/test-templating/autosummary_templating.txt
@@ -0,0 +1,13 @@
+Autosummary templating test
+===========================
+
+.. autosummary::
+ :toctree: generated
+
+ sphinx.application.Sphinx
+
+.. currentmodule:: sphinx.application
+
+.. autoclass:: TemplateBridge
+
+ .. automethod:: render
diff --git a/tests/roots/test-templating/conf.py b/tests/roots/test-templating/conf.py
new file mode 100644
index 0000000..225da82
--- /dev/null
+++ b/tests/roots/test-templating/conf.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+
+project = 'Sphinx templating <Tests>'
+source_suffix = '.txt'
+keep_warnings = True
+templates_path = ['_templates']
+release = version = '2013.120'
+
+extensions = ['sphinx.ext.autosummary']
+autosummary_generate = ['autosummary_templating']
+
diff --git a/tests/roots/test-templating/contents.txt b/tests/roots/test-templating/contents.txt
new file mode 100644
index 0000000..04a40e2
--- /dev/null
+++ b/tests/roots/test-templating/contents.txt
@@ -0,0 +1,7 @@
+Welcome to Sphinx Tests's documentation!
+========================================
+
+.. toctree::
+
+ autosummary_templating
+
diff --git a/tests/run.py b/tests/run.py
new file mode 100755
index 0000000..37922f3
--- /dev/null
+++ b/tests/run.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ Sphinx unit test driver
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ This script runs the Sphinx unit test suite.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+from os import path, chdir, listdir, environ
+import shutil
+
+testroot = path.dirname(__file__) or '.'
+if 'BUILD_TEST_PATH' in environ:
+ # for tox testing
+ newroot = environ['BUILD_TEST_PATH']
+ # tox installs the sphinx package, no need for sys.path.insert
+else:
+ newroot = path.join(testroot, path.pardir, 'build')
+ newroot = path.join(newroot, listdir(newroot)[0], 'tests')
+
+shutil.rmtree(newroot, ignore_errors=True)
+
+if sys.version_info >= (3, 0):
+ print('Copying and converting sources to build/lib/tests...')
+ from distutils.util import copydir_run_2to3
+ copydir_run_2to3(testroot, newroot)
+else:
+ # just copying test directory to parallel testing
+ print('Copying sources to build/lib/tests...')
+ shutil.copytree(testroot, newroot)
+
+# always test the sphinx package from build/lib/
+sys.path.insert(0, path.abspath(path.join(newroot, path.pardir)))
+# switch to the copy/converted dir so nose tests the right tests
+chdir(newroot)
+
+try:
+ import nose
+except ImportError:
+ print('The nose package is needed to run the Sphinx test suite.')
+ sys.exit(1)
+
+try:
+ import docutils
+except ImportError:
+ print('Sphinx requires the docutils package to be installed.')
+ sys.exit(1)
+
+try:
+ import jinja2
+except ImportError:
+ print('Sphinx requires the jinja2 package to be installed.')
+ sys.exit(1)
+
+print('Running Sphinx test suite...')
+nose.main()
diff --git a/tests/test_application.py b/tests/test_application.py
new file mode 100644
index 0000000..3d464eb
--- /dev/null
+++ b/tests/test_application.py
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+"""
+ test_application
+ ~~~~~~~~~~~~~~~~
+
+ Test the Sphinx class.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from StringIO import StringIO
+
+from docutils import nodes
+from sphinx.application import ExtensionError
+from sphinx.domains import Domain
+
+from util import with_app, raises_msg, TestApp
+
+
+ at with_app()
+def test_events(app):
+ def empty(): pass
+ raises_msg(ExtensionError, "Unknown event name: invalid",
+ app.connect, "invalid", empty)
+
+
+ app.add_event("my_event")
+ raises_msg(ExtensionError, "Event 'my_event' already present",
+ app.add_event, "my_event")
+
+ def mock_callback(a_app, *args):
+ assert a_app is app
+ assert emit_args == args
+ return "ret"
+ emit_args = (1, 3, "string")
+ listener_id = app.connect("my_event", mock_callback)
+ assert app.emit("my_event", *emit_args) == ["ret"], "Callback not called"
+
+ app.disconnect(listener_id)
+ assert app.emit("my_event", *emit_args) == [], \
+ "Callback called when disconnected"
+
+
+ at with_app()
+def test_emit_with_nonascii_name_node(app):
+ node = nodes.section(names=[u'\u65e5\u672c\u8a9e'])
+ app.emit('my_event', node)
+
+
+def test_output():
+ status, warnings = StringIO(), StringIO()
+ app = TestApp(status=status, warning=warnings)
+ try:
+ status.truncate(0) # __init__ writes to status
+ status.seek(0)
+ app.info("Nothing here...")
+ assert status.getvalue() == "Nothing here...\n"
+ status.truncate(0)
+ status.seek(0)
+ app.info("Nothing here...", True)
+ assert status.getvalue() == "Nothing here..."
+
+ old_count = app._warncount
+ app.warn("Bad news!")
+ assert warnings.getvalue() == "WARNING: Bad news!\n"
+ assert app._warncount == old_count + 1
+ finally:
+ app.cleanup()
+
+
+def test_extensions():
+ status, warnings = StringIO(), StringIO()
+ app = TestApp(status=status, warning=warnings)
+ try:
+ app.setup_extension('shutil')
+ assert warnings.getvalue().startswith("WARNING: extension 'shutil'")
+ finally:
+ app.cleanup()
+
+def test_domain_override():
+ class A(Domain):
+ name = 'foo'
+ class B(A):
+ name = 'foo'
+ class C(Domain):
+ name = 'foo'
+ status, warnings = StringIO(), StringIO()
+ app = TestApp(status=status, warning=warnings)
+ try:
+ # No domain know named foo.
+ raises_msg(ExtensionError, 'domain foo not yet registered',
+ app.override_domain, A)
+ assert app.add_domain(A) is None
+ assert app.override_domain(B) is None
+ raises_msg(ExtensionError, 'new domain not a subclass of registered '
+ 'foo domain', app.override_domain, C)
+ finally:
+ app.cleanup()
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
new file mode 100644
index 0000000..a7b2cee
--- /dev/null
+++ b/tests/test_autodoc.py
@@ -0,0 +1,914 @@
+# -*- coding: utf-8 -*-
+"""
+ test_autodoc
+ ~~~~~~~~~~~~
+
+ Test the autodoc extension. This tests mainly the Documenters; the auto
+ directives are tested in a test source file translated by test_build.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+from StringIO import StringIO
+
+# "raises" imported for usage by autodoc
+from util import TestApp, Struct, raises
+from nose.tools import with_setup
+
+from docutils.statemachine import ViewList
+
+from sphinx.ext.autodoc import AutoDirective, add_documenter, \
+ ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL
+
+app = None
+
+def setup_module():
+ global app
+ app = TestApp()
+ app.builder.env.app = app
+ app.builder.env.temp_data['docname'] = 'dummy'
+ app.connect('autodoc-process-docstring', process_docstring)
+ app.connect('autodoc-process-signature', process_signature)
+ app.connect('autodoc-skip-member', skip_member)
+
+
+def teardown_module():
+ app.cleanup()
+
+
+directive = options = None
+
+def setup_test():
+ global options, directive
+ global processed_docstrings, processed_signatures, _warnings
+
+ options = Struct(
+ inherited_members = False,
+ undoc_members = False,
+ private_members = False,
+ special_members = False,
+ imported_members = False,
+ show_inheritance = False,
+ noindex = False,
+ annotation = None,
+ synopsis = '',
+ platform = '',
+ deprecated = False,
+ members = [],
+ member_order = 'alphabetic',
+ exclude_members = set(),
+ )
+
+ directive = Struct(
+ env = app.builder.env,
+ genopt = options,
+ result = ViewList(),
+ warn = warnfunc,
+ filename_set = set(),
+ )
+
+ processed_docstrings = []
+ processed_signatures = []
+ _warnings = []
+
+
+_warnings = []
+
+def warnfunc(msg):
+ _warnings.append(msg)
+
+
+processed_docstrings = []
+
+def process_docstring(app, what, name, obj, options, lines):
+ processed_docstrings.append((what, name))
+ if name == 'bar':
+ lines.extend(['42', ''])
+
+processed_signatures = []
+
+def process_signature(app, what, name, obj, options, args, retann):
+ processed_signatures.append((what, name))
+ if name == 'bar':
+ return '42', None
+
+
+def skip_member(app, what, name, obj, skip, options):
+ if name in ('__special1__', '__special2__'):
+ return skip
+ if name.startswith('_'):
+ return True
+ if name == 'skipmeth':
+ return True
+
+
+ at with_setup(setup_test)
+def test_parse_name():
+ def verify(objtype, name, result):
+ inst = AutoDirective._registry[objtype](directive, name)
+ assert inst.parse_name()
+ assert (inst.modname, inst.objpath, inst.args, inst.retann) == result
+
+ # for modules
+ verify('module', 'test_autodoc', ('test_autodoc', [], None, None))
+ verify('module', 'test.test_autodoc', ('test.test_autodoc', [], None, None))
+ verify('module', 'test(arg)', ('test', [], 'arg', None))
+ assert 'signature arguments' in _warnings[0]
+ del _warnings[:]
+
+ # for functions/classes
+ verify('function', 'util.raises', ('util', ['raises'], None, None))
+ verify('function', 'util.raises(exc) -> None',
+ ('util', ['raises'], 'exc', 'None'))
+ directive.env.temp_data['autodoc:module'] = 'util'
+ verify('function', 'raises', ('util', ['raises'], None, None))
+ del directive.env.temp_data['autodoc:module']
+ directive.env.temp_data['py:module'] = 'util'
+ verify('function', 'raises', ('util', ['raises'], None, None))
+ verify('class', 'TestApp', ('util', ['TestApp'], None, None))
+
+ # for members
+ directive.env.temp_data['py:module'] = 'foo'
+ verify('method', 'util.TestApp.cleanup',
+ ('util', ['TestApp', 'cleanup'], None, None))
+ directive.env.temp_data['py:module'] = 'util'
+ directive.env.temp_data['py:class'] = 'Foo'
+ directive.env.temp_data['autodoc:class'] = 'TestApp'
+ verify('method', 'cleanup', ('util', ['TestApp', 'cleanup'], None, None))
+ verify('method', 'TestApp.cleanup',
+ ('util', ['TestApp', 'cleanup'], None, None))
+
+ # and clean up
+ del directive.env.temp_data['py:module']
+ del directive.env.temp_data['py:class']
+ del directive.env.temp_data['autodoc:class']
+
+
+ at with_setup(setup_test)
+def test_format_signature():
+ def formatsig(objtype, name, obj, args, retann):
+ inst = AutoDirective._registry[objtype](directive, name)
+ inst.fullname = name
+ inst.doc_as_attr = False # for class objtype
+ inst.object = obj
+ inst.args = args
+ inst.retann = retann
+ return inst.format_signature()
+
+ # no signatures for modules
+ assert formatsig('module', 'test', None, None, None) == ''
+
+ # test for functions
+ def f(a, b, c=1, **d):
+ pass
+ def g(a='\n'):
+ pass
+ assert formatsig('function', 'f', f, None, None) == '(a, b, c=1, **d)'
+ assert formatsig('function', 'f', f, 'a, b, c, d', None) == '(a, b, c, d)'
+ assert formatsig('function', 'f', f, None, 'None') == \
+ '(a, b, c=1, **d) -> None'
+ assert formatsig('function', 'g', g, None, None) == r"(a='\\n')"
+
+ # test for classes
+ class D:
+ pass
+ class E(object):
+ pass
+ # no signature for classes without __init__
+ for C in (D, E):
+ assert formatsig('class', 'D', C, None, None) == ''
+ class F:
+ def __init__(self, a, b=None):
+ pass
+ class G(F, object):
+ pass
+ for C in (F, G):
+ assert formatsig('class', 'C', C, None, None) == '(a, b=None)'
+ assert formatsig('class', 'C', D, 'a, b', 'X') == '(a, b) -> X'
+
+ #__init__ have signature at first line of docstring
+ class F2:
+ '''some docstring for F2.'''
+ def __init__(self, *args, **kw):
+ '''
+ __init__(a1, a2, kw1=True, kw2=False)
+
+ some docstring for __init__.
+ '''
+ class G2(F2, object):
+ pass
+ for C in (F2, G2):
+ assert formatsig('class', 'C', C, None, None) == \
+ '(a1, a2, kw1=True, kw2=False)'
+
+ # test for methods
+ class H:
+ def foo1(self, b, *c):
+ pass
+ def foo2(b, *c):
+ pass
+ def foo3(self, d='\n'):
+ pass
+ assert formatsig('method', 'H.foo', H.foo1, None, None) == '(b, *c)'
+ assert formatsig('method', 'H.foo', H.foo1, 'a', None) == '(a)'
+ assert formatsig('method', 'H.foo', H.foo2, None, None) == '(b, *c)'
+ assert formatsig('method', 'H.foo', H.foo3, None, None) == r"(d='\\n')"
+
+ # test exception handling (exception is caught and args is '')
+ assert formatsig('function', 'int', int, None, None) == ''
+ del _warnings[:]
+
+ # test processing by event handler
+ assert formatsig('method', 'bar', H.foo1, None, None) == '42'
+
+ # test functions created via functools.partial
+ from functools import partial
+ curried1 = partial(lambda a, b, c: None, 'A')
+ assert formatsig('function', 'curried1', curried1, None, None) == \
+ '(b, c)'
+ curried2 = partial(lambda a, b, c=42: None, 'A')
+ assert formatsig('function', 'curried2', curried2, None, None) == \
+ '(b, c=42)'
+ curried3 = partial(lambda a, b, *c: None, 'A')
+ assert formatsig('function', 'curried3', curried3, None, None) == \
+ '(b, *c)'
+ curried4 = partial(lambda a, b, c=42, *d, **e: None, 'A')
+ assert formatsig('function', 'curried4', curried4, None, None) == \
+ '(b, c=42, *d, **e)'
+
+
+ at with_setup(setup_test)
+def test_get_doc():
+ def getdocl(objtype, obj, encoding=None):
+ inst = AutoDirective._registry[objtype](directive, 'tmp')
+ inst.object = obj
+ ds = inst.get_doc(encoding)
+ # for testing purposes, concat them and strip the empty line at the end
+ return sum(ds, [])[:-1]
+
+ # objects without docstring
+ def f():
+ pass
+ assert getdocl('function', f) == []
+
+ # standard function, diverse docstring styles...
+ def f():
+ """Docstring"""
+ def g():
+ """
+ Docstring
+ """
+ for func in (f, g):
+ assert getdocl('function', func) == ['Docstring']
+
+ # first line vs. other lines indentation
+ def f():
+ """First line
+
+ Other
+ lines
+ """
+ assert getdocl('function', f) == ['First line', '', 'Other', ' lines']
+
+ # charset guessing (this module is encoded in utf-8)
+ def f():
+ """Döcstring"""
+ assert getdocl('function', f) == [u'Döcstring']
+
+ # already-unicode docstrings must be taken literally
+ def f():
+ u"""Döcstring"""
+ assert getdocl('function', f) == [u'Döcstring']
+
+ # class docstring: depends on config value which one is taken
+ class C:
+ """Class docstring"""
+ def __init__(self):
+ """Init docstring"""
+ directive.env.config.autoclass_content = 'class'
+ assert getdocl('class', C) == ['Class docstring']
+ directive.env.config.autoclass_content = 'init'
+ assert getdocl('class', C) == ['Init docstring']
+ directive.env.config.autoclass_content = 'both'
+ assert getdocl('class', C) == ['Class docstring', '', 'Init docstring']
+
+ class D:
+ """Class docstring"""
+ def __init__(self):
+ """Init docstring
+
+ Other
+ lines
+ """
+
+ # Indentation is normalized for 'both'
+ assert getdocl('class', D) == ['Class docstring', '', 'Init docstring',
+ '', 'Other', ' lines']
+
+ #__init__ have signature at first line of docstring
+ class E:
+ """Class docstring"""
+ def __init__(self, *args, **kw):
+ """
+ __init__(a1, a2, kw1=True, kw2=False)
+
+ Init docstring
+ """
+
+ # signature line in the docstring will be kept when
+ # autodoc_docstring_signature == False
+ directive.env.config.autodoc_docstring_signature = False
+ directive.env.config.autoclass_content = 'class'
+ assert getdocl('class', E) == ['Class docstring']
+ directive.env.config.autoclass_content = 'init'
+ assert getdocl('class', E) == ['__init__(a1, a2, kw1=True, kw2=False)',
+ '', 'Init docstring']
+ directive.env.config.autoclass_content = 'both'
+ assert getdocl('class', E) == ['Class docstring', '',
+ '__init__(a1, a2, kw1=True, kw2=False)',
+ '', 'Init docstring']
+
+ # signature line in the docstring will be removed when
+ # autodoc_docstring_signature == True
+ directive.env.config.autodoc_docstring_signature = True #default
+ directive.env.config.autoclass_content = 'class'
+ assert getdocl('class', E) == ['Class docstring']
+ directive.env.config.autoclass_content = 'init'
+ assert getdocl('class', E) == ['Init docstring']
+ directive.env.config.autoclass_content = 'both'
+ assert getdocl('class', E) == ['Class docstring', '', 'Init docstring']
+
+ # class does not have __init__ method
+ class F(object):
+ """Class docstring"""
+
+ # docstring in the __init__ method of base class will be discard
+ for f in (False, True):
+ directive.env.config.autodoc_docstring_signature = f
+ directive.env.config.autoclass_content = 'class'
+ assert getdocl('class', F) == ['Class docstring']
+ directive.env.config.autoclass_content = 'init'
+ assert getdocl('class', F) == ['Class docstring']
+ directive.env.config.autoclass_content = 'both'
+ assert getdocl('class', F) == ['Class docstring']
+
+ # class has __init__ method with no docstring
+ class G(object):
+ """Class docstring"""
+ def __init__(self):
+ pass
+
+ # docstring in the __init__ method of base class will not be used
+ for f in (False, True):
+ directive.env.config.autodoc_docstring_signature = f
+ directive.env.config.autoclass_content = 'class'
+ assert getdocl('class', G) == ['Class docstring']
+ directive.env.config.autoclass_content = 'init'
+ assert getdocl('class', G) == ['Class docstring']
+ directive.env.config.autoclass_content = 'both'
+ assert getdocl('class', G) == ['Class docstring']
+
+
+ at with_setup(setup_test)
+def test_docstring_processing():
+ def process(objtype, name, obj):
+ inst = AutoDirective._registry[objtype](directive, name)
+ inst.object = obj
+ inst.fullname = name
+ return list(inst.process_doc(inst.get_doc()))
+
+ class E:
+ def __init__(self):
+ """Init docstring"""
+
+ # docstring processing by event handler
+ assert process('class', 'bar', E) == ['Init docstring', '', '42', '']
+
+ lid = app.connect('autodoc-process-docstring',
+ cut_lines(1, 1, ['function']))
+ def f():
+ """
+ first line
+ second line
+ third line
+ """
+ assert process('function', 'f', f) == ['second line', '']
+ app.disconnect(lid)
+
+ lid = app.connect('autodoc-process-docstring', between('---', ['function']))
+ def g():
+ """
+ first line
+ ---
+ second line
+ ---
+ third line
+ """
+ assert process('function', 'g', g) == ['second line', '']
+ app.disconnect(lid)
+
+ lid = app.connect('autodoc-process-docstring', between('---', ['function'],
+ exclude=True))
+ def h():
+ """
+ first line
+ ---
+ second line
+ ---
+ third line
+ """
+ assert process('function', 'h', h) == ['first line', 'third line', '']
+ app.disconnect(lid)
+
+
+ at with_setup(setup_test)
+def test_new_documenter():
+ class MyDocumenter(ModuleLevelDocumenter):
+ objtype = 'integer'
+ directivetype = 'data'
+ priority = 100
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ return isinstance(member, int)
+
+ def document_members(self, all_members=False):
+ return
+
+ add_documenter(MyDocumenter)
+
+ def assert_result_contains(item, objtype, name, **kw):
+ inst = AutoDirective._registry[objtype](directive, name)
+ inst.generate(**kw)
+ #print '\n'.join(directive.result)
+ assert len(_warnings) == 0, _warnings
+ assert item in directive.result
+ del directive.result[:]
+
+ options.members = ['integer']
+ assert_result_contains('.. py:data:: integer', 'module', 'test_autodoc')
+
+
+ at with_setup(setup_test, AutoDirective._special_attrgetters.clear)
+def test_attrgetter_using():
+ def assert_getter_works(objtype, name, obj, attrs=[], **kw):
+ getattr_spy = []
+ def special_getattr(obj, name, *defargs):
+ if name in attrs:
+ getattr_spy.append((obj, name))
+ return None
+ return getattr(obj, name, *defargs)
+ AutoDirective._special_attrgetters[type] = special_getattr
+
+ del getattr_spy[:]
+ inst = AutoDirective._registry[objtype](directive, name)
+ inst.generate(**kw)
+
+ hooked_members = [s[1] for s in getattr_spy]
+ documented_members = [s[1] for s in processed_signatures]
+ for attr in attrs:
+ fullname = '.'.join((name, attr))
+ assert attr in hooked_members
+ assert fullname not in documented_members, \
+ '%r was not hooked by special_attrgetter function' % fullname
+
+ options.members = ALL
+ options.inherited_members = False
+ assert_getter_works('class', 'test_autodoc.Class', Class,
+ ['meth'])
+
+ options.inherited_members = True
+ assert_getter_works('class', 'test_autodoc.Class', Class,
+ ['meth', 'inheritedmeth'])
+
+
+ at with_setup(setup_test)
+def test_generate():
+ def assert_warns(warn_str, objtype, name, **kw):
+ inst = AutoDirective._registry[objtype](directive, name)
+ inst.generate(**kw)
+ assert len(directive.result) == 0, directive.result
+ assert len(_warnings) == 1, _warnings
+ assert warn_str in _warnings[0], _warnings
+ del _warnings[:]
+
+ def assert_works(objtype, name, **kw):
+ inst = AutoDirective._registry[objtype](directive, name)
+ inst.generate(**kw)
+ assert directive.result
+ #print '\n'.join(directive.result)
+ assert len(_warnings) == 0, _warnings
+ del directive.result[:]
+
+ def assert_processes(items, objtype, name, **kw):
+ del processed_docstrings[:]
+ del processed_signatures[:]
+ assert_works(objtype, name, **kw)
+ assert set(processed_docstrings) | set(processed_signatures) == \
+ set(items)
+
+ def assert_result_contains(item, objtype, name, **kw):
+ inst = AutoDirective._registry[objtype](directive, name)
+ inst.generate(**kw)
+ #print '\n'.join(directive.result)
+ assert len(_warnings) == 0, _warnings
+ assert item in directive.result
+ del directive.result[:]
+
+ def assert_order(items, objtype, name, member_order, **kw):
+ inst = AutoDirective._registry[objtype](directive, name)
+ inst.options.member_order = member_order
+ inst.generate(**kw)
+ assert len(_warnings) == 0, _warnings
+ items = list(reversed(items))
+ lineiter = iter(directive.result)
+ #for line in directive.result:
+ # if line.strip():
+ # print repr(line)
+ while items:
+ item = items.pop()
+ for line in lineiter:
+ if line == item:
+ break
+ else: # ran out of items!
+ assert False, 'item %r not found in result or not in the ' \
+ ' correct order' % item
+ del directive.result[:]
+
+ options.members = []
+
+ # no module found?
+ assert_warns("import for autodocumenting 'foobar'",
+ 'function', 'foobar', more_content=None)
+ # importing
+ assert_warns("failed to import module 'test_foobar'",
+ 'module', 'test_foobar', more_content=None)
+ # attributes missing
+ assert_warns("failed to import function 'foobar' from module 'util'",
+ 'function', 'util.foobar', more_content=None)
+ # method missing
+ assert_warns("failed to import method 'Class.foobar' from module 'test_autodoc';",
+ 'method', 'test_autodoc.Class.foobar', more_content=None)
+
+ # test auto and given content mixing
+ directive.env.temp_data['py:module'] = 'test_autodoc'
+ assert_result_contains(' Function.', 'method', 'Class.meth')
+ add_content = ViewList()
+ add_content.append('Content.', '', 0)
+ assert_result_contains(' Function.', 'method',
+ 'Class.meth', more_content=add_content)
+ assert_result_contains(' Content.', 'method',
+ 'Class.meth', more_content=add_content)
+
+ # test check_module
+ inst = FunctionDocumenter(directive, 'raises')
+ inst.generate(check_module=True)
+ assert len(directive.result) == 0
+
+ # assert that exceptions can be documented
+ assert_works('exception', 'test_autodoc.CustomEx', all_members=True)
+ assert_works('exception', 'test_autodoc.CustomEx')
+
+ # test diverse inclusion settings for members
+ should = [('class', 'test_autodoc.Class')]
+ assert_processes(should, 'class', 'Class')
+ should.extend([('method', 'test_autodoc.Class.meth')])
+ options.members = ['meth']
+ options.exclude_members = set(['excludemeth'])
+ assert_processes(should, 'class', 'Class')
+ should.extend([('attribute', 'test_autodoc.Class.prop'),
+ ('attribute', 'test_autodoc.Class.descr'),
+ ('attribute', 'test_autodoc.Class.attr'),
+ ('attribute', 'test_autodoc.Class.docattr'),
+ ('attribute', 'test_autodoc.Class.udocattr'),
+ ('attribute', 'test_autodoc.Class.mdocattr'),
+ ('attribute', 'test_autodoc.Class.inst_attr_comment'),
+ ('attribute', 'test_autodoc.Class.inst_attr_inline'),
+ ('attribute', 'test_autodoc.Class.inst_attr_string'),
+ ('method', 'test_autodoc.Class.moore'),
+ ])
+ options.members = ALL
+ assert_processes(should, 'class', 'Class')
+ options.undoc_members = True
+ should.extend((('attribute', 'test_autodoc.Class.skipattr'),
+ ('method', 'test_autodoc.Class.undocmeth'),
+ ('method', 'test_autodoc.Class.roger')))
+ assert_processes(should, 'class', 'Class')
+ options.inherited_members = True
+ should.append(('method', 'test_autodoc.Class.inheritedmeth'))
+ assert_processes(should, 'class', 'Class')
+
+ # test special members
+ options.special_members = ['__special1__']
+ should.append(('method', 'test_autodoc.Class.__special1__'))
+ assert_processes(should, 'class', 'Class')
+ options.special_members = ALL
+ should.append(('method', 'test_autodoc.Class.__special2__'))
+ assert_processes(should, 'class', 'Class')
+ options.special_members = False
+
+ options.members = []
+ # test module flags
+ assert_result_contains('.. py:module:: test_autodoc',
+ 'module', 'test_autodoc')
+ options.synopsis = 'Synopsis'
+ assert_result_contains(' :synopsis: Synopsis', 'module', 'test_autodoc')
+ options.deprecated = True
+ assert_result_contains(' :deprecated:', 'module', 'test_autodoc')
+ options.platform = 'Platform'
+ assert_result_contains(' :platform: Platform', 'module', 'test_autodoc')
+ # test if __all__ is respected for modules
+ options.members = ALL
+ assert_result_contains('.. py:class:: Class(arg)', 'module', 'test_autodoc')
+ try:
+ assert_result_contains('.. py:exception:: CustomEx',
+ 'module', 'test_autodoc')
+ except AssertionError:
+ pass
+ else:
+ assert False, 'documented CustomEx which is not in __all__'
+
+ # test noindex flag
+ options.members = []
+ options.noindex = True
+ assert_result_contains(' :noindex:', 'module', 'test_autodoc')
+ assert_result_contains(' :noindex:', 'class', 'Base')
+
+ # okay, now let's get serious about mixing Python and C signature stuff
+ assert_result_contains('.. py:class:: CustomDict', 'class', 'CustomDict',
+ all_members=True)
+
+ # test inner class handling
+ assert_processes([('class', 'test_autodoc.Outer'),
+ ('class', 'test_autodoc.Outer.Inner'),
+ ('method', 'test_autodoc.Outer.Inner.meth')],
+ 'class', 'Outer', all_members=True)
+
+ # test descriptor docstrings
+ assert_result_contains(' Descriptor instance docstring.',
+ 'attribute', 'test_autodoc.Class.descr')
+
+ # test generation for C modules (which have no source file)
+ directive.env.temp_data['py:module'] = 'time'
+ assert_processes([('function', 'time.asctime')], 'function', 'asctime')
+ assert_processes([('function', 'time.asctime')], 'function', 'asctime')
+
+ # test autodoc_member_order == 'source'
+ directive.env.temp_data['py:module'] = 'test_autodoc'
+ assert_order(['.. py:class:: Class(arg)',
+ ' .. py:attribute:: Class.descr',
+ ' .. py:method:: Class.meth()',
+ ' .. py:method:: Class.undocmeth()',
+ ' .. py:attribute:: Class.attr',
+ ' .. py:attribute:: Class.prop',
+ ' .. py:attribute:: Class.docattr',
+ ' .. py:attribute:: Class.udocattr',
+ ' .. py:attribute:: Class.mdocattr',
+ ' .. py:classmethod:: Class.roger(a, e=5, f=6)',
+ ' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
+ ' .. py:attribute:: Class.inst_attr_comment',
+ ' .. py:attribute:: Class.inst_attr_string',
+ ' .. py:method:: Class.inheritedmeth()',
+ ],
+ 'class', 'Class', member_order='bysource', all_members=True)
+ del directive.env.temp_data['py:module']
+
+ # test attribute initialized to class instance from other module
+ directive.env.temp_data['autodoc:class'] = 'test_autodoc.Class'
+ assert_result_contains(u' should be documented as well - s\xfc\xdf',
+ 'attribute', 'mdocattr')
+ del directive.env.temp_data['autodoc:class']
+
+ # test autodoc_docstring_signature
+ assert_result_contains(
+ '.. py:method:: DocstringSig.meth(FOO, BAR=1) -> BAZ', 'method',
+ 'test_autodoc.DocstringSig.meth')
+ assert_result_contains(
+ ' rest of docstring', 'method', 'test_autodoc.DocstringSig.meth')
+ assert_result_contains(
+ '.. py:method:: DocstringSig.meth2()', 'method',
+ 'test_autodoc.DocstringSig.meth2')
+ assert_result_contains(
+ ' indented line', 'method',
+ 'test_autodoc.DocstringSig.meth2')
+ assert_result_contains(
+ '.. py:classmethod:: Class.moore(a, e, f) -> happiness', 'method',
+ 'test_autodoc.Class.moore')
+
+ # test new attribute documenter behavior
+ directive.env.temp_data['py:module'] = 'test_autodoc'
+ options.undoc_members = True
+ assert_processes([('class', 'test_autodoc.AttCls'),
+ ('attribute', 'test_autodoc.AttCls.a1'),
+ ('attribute', 'test_autodoc.AttCls.a2'),
+ ], 'class', 'AttCls')
+ assert_result_contains(
+ ' :annotation: = hello world', 'attribute', 'AttCls.a1')
+ assert_result_contains(
+ ' :annotation: = None', 'attribute', 'AttCls.a2')
+
+ # test explicit members with instance attributes
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+ directive.env.temp_data['py:module'] = 'test_autodoc'
+ options.inherited_members = False
+ options.undoc_members = False
+ options.members = ALL
+ assert_processes([
+ ('class', 'test_autodoc.InstAttCls'),
+ ('attribute', 'test_autodoc.InstAttCls.ca1'),
+ ('attribute', 'test_autodoc.InstAttCls.ca2'),
+ ('attribute', 'test_autodoc.InstAttCls.ca3'),
+ ('attribute', 'test_autodoc.InstAttCls.ia1'),
+ ('attribute', 'test_autodoc.InstAttCls.ia2'),
+ ], 'class', 'InstAttCls')
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+ options.members = ['ca1', 'ia1']
+ assert_processes([
+ ('class', 'test_autodoc.InstAttCls'),
+ ('attribute', 'test_autodoc.InstAttCls.ca1'),
+ ('attribute', 'test_autodoc.InstAttCls.ia1'),
+ ], 'class', 'InstAttCls')
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+ del directive.env.temp_data['py:module']
+
+ # test descriptor class documentation
+ options.members = ['CustomDataDescriptor']
+ assert_result_contains('.. py:class:: CustomDataDescriptor(doc)',
+ 'module', 'test_autodoc')
+ assert_result_contains(' .. py:method:: CustomDataDescriptor.meth()',
+ 'module', 'test_autodoc')
+
+# --- generate fodder ------------
+
+__all__ = ['Class']
+
+#: documentation for the integer
+integer = 1
+
+class CustomEx(Exception):
+ """My custom exception."""
+
+ def f(self):
+ """Exception method."""
+
+class CustomDataDescriptor(object):
+ """Descriptor class docstring."""
+
+ def __init__(self, doc):
+ self.__doc__ = doc
+
+ def __get__(self, obj, type=None):
+ if obj is None:
+ return self
+ return 42
+
+ def meth(self):
+ """Function."""
+ return "The Answer"
+
+def _funky_classmethod(name, b, c, d, docstring=None):
+ """Generates a classmethod for a class from a template by filling out
+ some arguments."""
+ def template(cls, a, b, c, d=4, e=5, f=6):
+ return a, b, c, d, e, f
+ if sys.version_info >= (2, 5):
+ from functools import partial
+ function = partial(template, b=b, c=c, d=d)
+ else:
+ def function(cls, a, e=5, f=6):
+ return template(a, b, c, d, e, f)
+ function.__name__ = name
+ function.__doc__ = docstring
+ return classmethod(function)
+
+class Base(object):
+ def inheritedmeth(self):
+ """Inherited function."""
+
+class Class(Base):
+ """Class to document."""
+
+ descr = CustomDataDescriptor("Descriptor instance docstring.")
+
+ def meth(self):
+ """Function."""
+
+ def undocmeth(self):
+ pass
+
+ def skipmeth(self):
+ """Method that should be skipped."""
+
+ def excludemeth(self):
+ """Method that should be excluded."""
+
+ # should not be documented
+ skipattr = 'foo'
+
+ #: should be documented -- süß
+ attr = 'bar'
+
+ def prop(self):
+ """Property."""
+ # stay 2.4 compatible (docstring!)
+ prop = property(prop, doc="Property.")
+
+ docattr = 'baz'
+ """should likewise be documented -- süß"""
+
+ udocattr = 'quux'
+ u"""should be documented as well - süß"""
+
+ # initialized to any class imported from another module
+ mdocattr = StringIO()
+ """should be documented as well - süß"""
+
+ roger = _funky_classmethod("roger", 2, 3, 4)
+
+ moore = _funky_classmethod("moore", 9, 8, 7,
+ docstring="moore(a, e, f) -> happiness")
+
+ def __init__(self, arg):
+ self.inst_attr_inline = None #: an inline documented instance attr
+ #: a documented instance attribute
+ self.inst_attr_comment = None
+ self.inst_attr_string = None
+ """a documented instance attribute"""
+
+ def __special1__(self):
+ """documented special method"""
+
+ def __special2__(self):
+ # undocumented special method
+ pass
+
+
+class CustomDict(dict):
+ """Docstring."""
+
+def function(foo, *args, **kwds):
+ """
+ Return spam.
+ """
+ pass
+
+
+class Outer(object):
+ """Foo"""
+
+ class Inner(object):
+ """Foo"""
+
+ def meth(self):
+ """Foo"""
+
+ # should be documented as an alias
+ factory = dict
+
+
+class DocstringSig(object):
+ def meth(self):
+ """meth(FOO, BAR=1) -> BAZ
+First line of docstring
+
+ rest of docstring
+ """
+
+ def meth2(self):
+ """First line, no signature
+ Second line followed by indentation::
+
+ indented line
+ """
+
+class StrRepr(str):
+ def __repr__(self):
+ return self
+
+class AttCls(object):
+ a1 = StrRepr('hello\nworld')
+ a2 = None
+
+class InstAttCls(object):
+ """Class with documented class and instance attributes."""
+
+ #: Doc comment for class attribute InstAttCls.ca1.
+ #: It can have multiple lines.
+ ca1 = 'a'
+
+ ca2 = 'b' #: Doc comment for InstAttCls.ca2. One line only.
+
+ ca3 = 'c'
+ """Docstring for class attribute InstAttCls.ca3."""
+
+ def __init__(self):
+ #: Doc comment for instance attribute InstAttCls.ia1
+ self.ia1 = 'd'
+
+ self.ia2 = 'e'
+ """Docstring for instance attribute InstAttCls.ia2."""
diff --git a/tests/test_autosummary.py b/tests/test_autosummary.py
new file mode 100644
index 0000000..de26a05
--- /dev/null
+++ b/tests/test_autosummary.py
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+"""
+ test_autosummary
+ ~~~~~~~~~~~~~~~~
+
+ Test the autosummary extension.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import sys
+from functools import wraps
+from StringIO import StringIO
+
+from sphinx.ext.autosummary import mangle_signature
+
+from util import test_roots, TestApp
+
+html_warnfile = StringIO()
+
+
+def with_autosummary_app(*args, **kw):
+ default_kw = {
+ 'srcdir': (test_roots / 'test-autosummary'),
+ 'confoverrides': {
+ 'extensions': ['sphinx.ext.autosummary'],
+ 'autosummary_generate': True,
+ 'source_suffix': '.rst'
+ }
+ }
+ default_kw.update(kw)
+ def generator(func):
+ @wraps(func)
+ def deco(*args2, **kwargs2):
+ # Now, modify the python path...
+ srcdir = default_kw['srcdir']
+ sys.path.insert(0, srcdir)
+ try:
+ app = TestApp(*args, **default_kw)
+ func(app, *args2, **kwargs2)
+ finally:
+ if srcdir in sys.path:
+ sys.path.remove(srcdir)
+ # remove the auto-generated dummy_module.rst
+ dummy_rst = srcdir / 'dummy_module.rst'
+ if dummy_rst.isfile():
+ dummy_rst.unlink()
+
+ # don't execute cleanup if test failed
+ app.cleanup()
+ return deco
+ return generator
+
+
+def test_mangle_signature():
+ TEST = """
+ () :: ()
+ (a, b, c, d, e) :: (a, b, c, d, e)
+ (a, b, c=1, d=2, e=3) :: (a, b[, c, d, e])
+ (a, b, aaa=1, bbb=1, ccc=1, eee=1, fff=1, ggg=1, hhh=1, iii=1, jjj=1)\
+ :: (a, b[, aaa, bbb, ccc, ...])
+ (a, b, c=(), d=<foo>) :: (a, b[, c, d])
+ (a, b, c='foobar()', d=123) :: (a, b[, c, d])
+ (a, b[, c]) :: (a, b[, c])
+ (a, b[, cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]) :: (a, b[, ...)
+ (a, b='c=d, e=f, g=h', c=3) :: (a[, b, c])
+ (a, b='c=d, \\'e=f,\\' g=h', c=3) :: (a[, b, c])
+ (a, b='c=d, ', e='\\\\' g=h, c=3) :: (a[, b, e, c])
+ (a, b={'c=d, ': 3, '\\\\': 3}) :: (a[, b])
+ (a=1, b=2, c=3) :: ([a, b, c])
+ (a=1, b=<SomeClass: a, b, c>, c=3) :: ([a, b, c])
+ """
+
+ TEST = [map(lambda x: x.strip(), x.split("::")) for x in TEST.split("\n")
+ if '::' in x]
+ for inp, outp in TEST:
+ res = mangle_signature(inp).strip().replace(u"\u00a0", " ")
+ assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
+
+
+ at with_autosummary_app(buildername='html', warning=html_warnfile)
+def test_get_items_summary(app):
+ app.builddir.rmtree(True)
+
+ # monkey-patch Autosummary.get_items so we can easily get access to it's
+ # results..
+ import sphinx.ext.autosummary
+ orig_get_items = sphinx.ext.autosummary.Autosummary.get_items
+
+ autosummary_items = {}
+
+ def new_get_items(self, names, *args, **kwargs):
+ results = orig_get_items(self, names, *args, **kwargs)
+ for name, result in zip(names, results):
+ autosummary_items[name] = result
+ return results
+
+ sphinx.ext.autosummary.Autosummary.get_items = new_get_items
+ try:
+ app.builder.build_all()
+ finally:
+ sphinx.ext.autosummary.Autosummary.get_items = orig_get_items
+
+ html_warnings = html_warnfile.getvalue()
+ assert html_warnings == ''
+
+ expected_values = {
+ 'withSentence': 'I have a sentence which spans multiple lines.',
+ 'noSentence': "this doesn't start with a",
+ 'emptyLine': "This is the real summary",
+ 'module_attr': 'This is a module attribute',
+ 'C.class_attr': 'This is a class attribute',
+ 'C.prop_attr1': 'This is a function docstring',
+ 'C.prop_attr2': 'This is a attribute docstring',
+ 'C.C2': 'This is a nested inner class docstring',
+ }
+ for key, expected in expected_values.iteritems():
+ assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\
+ ' expected %r' % (key, autosummary_items[key], expected)
+
+
+ at with_autosummary_app(buildername='html')
+def test_process_doc_event(app):
+ app.builddir.rmtree(True)
+
+ def handler(app, what, name, obj, options, lines):
+ assert isinstance(lines, list)
+ app.connect('autodoc-process-docstring', handler)
+ app.builder.build_all()
diff --git a/tests/test_build.py b/tests/test_build.py
new file mode 100644
index 0000000..c355b16
--- /dev/null
+++ b/tests/test_build.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+"""
+ test_build
+ ~~~~~~~~~~
+
+ Test all builders that have no special checks.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from util import with_app, test_root, path, SkipTest, TestApp
+from textwrap import dedent
+
+try:
+ from docutils.writers.manpage import Writer as ManWriter
+except ImportError:
+ ManWriter = None
+
+
+def teardown_module():
+ (test_root / '_build').rmtree(True)
+
+
+def test_build():
+ for buildername in ('pickle', 'json', 'linkcheck', 'text', 'htmlhelp',
+ 'qthelp', 'epub', 'changes', 'singlehtml', 'xml',
+ 'pseudoxml'):
+ app = TestApp(buildername=buildername)
+ yield lambda app: app.builder.build_all(), app
+ app.cleanup()
+
+
+ at with_app(buildername='man')
+def test_man(app):
+ if ManWriter is None:
+ raise SkipTest('man writer is not available')
+ app.builder.build_all()
+ assert (app.outdir / 'SphinxTests.1').exists()
+
+
+def _test_nonascii_path(app):
+ srcdir = path(app.srcdir)
+ mb_name = u'\u65e5\u672c\u8a9e'
+ try:
+ (srcdir / mb_name).makedirs()
+ except UnicodeEncodeError:
+ from path import FILESYSTEMENCODING
+ raise SkipTest(
+ 'nonascii filename not supported on this filesystem encoding: '
+ '%s', FILESYSTEMENCODING)
+
+ (srcdir / mb_name / (mb_name + '.txt')).write_text(dedent("""
+ multi byte file name page
+ ==========================
+ """))
+
+ master_doc = srcdir / 'contents.txt'
+ master_doc.write_bytes((master_doc.text() + dedent("""
+ .. toctree::
+
+ %(mb_name)s/%(mb_name)s
+ """ % {'mb_name': mb_name})
+ ).encode('utf-8'))
+ app.builder.build_all()
+
+
+def test_nonascii_path():
+ (test_root / '_build').rmtree(True) #keep this to build first gettext
+
+ builder_names = ['gettext', 'html', 'dirhtml', 'singlehtml', 'latex',
+ 'texinfo', 'pickle', 'json', 'linkcheck', 'text',
+ 'htmlhelp', 'qthelp', 'epub', 'changes', 'xml',
+ 'pseudoxml']
+ if ManWriter is not None:
+ builder_names.append('man')
+
+ for buildername in builder_names:
+ app = TestApp(buildername=buildername, srcdir='(temp)')
+ yield _test_nonascii_path, app
+ app.cleanup()
diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py
new file mode 100644
index 0000000..9bde44b
--- /dev/null
+++ b/tests/test_build_gettext.py
@@ -0,0 +1,150 @@
+# -*- coding: utf-8 -*-
+"""
+ test_build_gettext
+ ~~~~~~~~~~~~~~~~~~
+
+ Test the build process with gettext builder with the test root.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import gettext
+import os
+import re
+from subprocess import Popen, PIPE
+
+from util import test_root, test_roots, with_app, SkipTest
+
+
+def teardown_module():
+ (test_root / '_build').rmtree(True)
+ (test_roots / 'test-intl' / '_build').rmtree(True),
+
+
+ at with_app(buildername='gettext')
+def test_all(app):
+ # Generic build; should fail only when the builder is horribly broken.
+ app.builder.build_all()
+
+
+ at with_app(buildername='gettext')
+def test_build(app):
+ # Do messages end up in the correct location?
+ app.builder.build(['extapi', 'subdir/includes'])
+ # top-level documents end up in a message catalog
+ assert (app.outdir / 'extapi.pot').isfile()
+ # directory items are grouped into sections
+ assert (app.outdir / 'subdir.pot').isfile()
+
+
+ at with_app(buildername='gettext')
+def test_seealso(app):
+ # regression test for issue #960
+ app.builder.build(['markup'])
+ catalog = (app.outdir / 'markup.pot').text(encoding='utf-8')
+ assert 'msgid "something, something else, something more"' in catalog
+
+
+ at with_app(buildername='gettext')
+def test_gettext(app):
+ app.builder.build(['markup'])
+
+ (app.outdir / 'en' / 'LC_MESSAGES').makedirs()
+ cwd = os.getcwd()
+ os.chdir(app.outdir)
+ try:
+ try:
+ p = Popen(['msginit', '--no-translator', '-i', 'markup.pot',
+ '--locale', 'en_US'],
+ stdout=PIPE, stderr=PIPE)
+ except OSError:
+ raise SkipTest # most likely msginit was not found
+ else:
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ print stdout
+ print stderr
+ assert False, 'msginit exited with return code %s' % \
+ p.returncode
+ assert (app.outdir / 'en_US.po').isfile(), 'msginit failed'
+ try:
+ p = Popen(['msgfmt', 'en_US.po', '-o',
+ os.path.join('en', 'LC_MESSAGES', 'test_root.mo')],
+ stdout=PIPE, stderr=PIPE)
+ except OSError:
+ raise SkipTest # most likely msgfmt was not found
+ else:
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ print stdout
+ print stderr
+ assert False, 'msgfmt exited with return code %s' % \
+ p.returncode
+ assert (app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo').isfile(), \
+ 'msgfmt failed'
+ finally:
+ os.chdir(cwd)
+
+ _ = gettext.translation('test_root', app.outdir, languages=['en']).gettext
+ assert _("Testing various markup") == u"Testing various markup"
+
+
+ at with_app(buildername='gettext',
+ srcdir=(test_roots / 'test-intl'),
+ doctreedir=(test_roots / 'test-intl' / '_build' / 'doctree'),
+ confoverrides={'gettext_compact': False})
+def test_gettext_index_entries(app):
+ # regression test for #976
+ app.builder.build(['index_entries'])
+
+ _msgid_getter = re.compile(r'msgid "(.*)"').search
+ def msgid_getter(msgid):
+ m = _msgid_getter(msgid)
+ if m:
+ return m.groups()[0]
+ return None
+
+ pot = (app.outdir / 'index_entries.pot').text(encoding='utf-8')
+ msgids = filter(None, map(msgid_getter, pot.splitlines()))
+
+ expected_msgids = [
+ "i18n with index entries",
+ "index target section",
+ "this is :index:`Newsletter` target paragraph.",
+ "various index entries",
+ "That's all.",
+ "Mailing List",
+ "Newsletter",
+ "Recipients List",
+ "First",
+ "Second",
+ "Third",
+ "Entry",
+ "See",
+ "Module",
+ "Keyword",
+ "Operator",
+ "Object",
+ "Exception",
+ "Statement",
+ "Builtin",
+ ]
+ for expect in expected_msgids:
+ assert expect in msgids
+ msgids.remove(expect)
+
+ # unexpected msgid existent
+ assert msgids == []
+
+
+ at with_app(buildername='gettext',
+ srcdir=(test_roots / 'test-intl'),
+ doctreedir=(test_roots / 'test-intl' / '_build' / 'doctree'))
+def test_gettext_template(app):
+ app.builder.build_all()
+ assert (app.outdir / 'sphinx.pot').isfile()
+
+ result = (app.outdir / 'sphinx.pot').text(encoding='utf-8')
+ assert "Welcome" in result
+ assert "Sphinx %(version)s" in result
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
new file mode 100644
index 0000000..0c2efe4
--- /dev/null
+++ b/tests/test_build_html.py
@@ -0,0 +1,378 @@
+# -*- coding: utf-8 -*-
+"""
+ test_build_html
+ ~~~~~~~~~~~~~~~
+
+ Test the HTML builder and check output against XPath.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import sys
+import htmlentitydefs
+from StringIO import StringIO
+
+try:
+ import pygments
+except ImportError:
+ pygments = None
+
+from sphinx import __version__
+from util import test_root, remove_unicode_literals, gen_with_app, with_app
+from etree13 import ElementTree as ET
+
+
+def teardown_module():
+ (test_root / '_build').rmtree(True)
+
+
+html_warnfile = StringIO()
+
+ENV_WARNINGS = """\
+%(root)s/autodoc_fodder.py:docstring of autodoc_fodder\\.MarkupError:2: \
+WARNING: Explicit markup ends without a blank line; unexpected \
+unindent\\.\\n?
+%(root)s/images.txt:9: WARNING: image file not readable: foo.png
+%(root)s/images.txt:23: WARNING: nonlocal image URI found: \
+http://www.python.org/logo.png
+%(root)s/includes.txt:\\d*: WARNING: Encoding 'utf-8-sig' used for \
+reading included file u'.*?wrongenc.inc' seems to be wrong, try giving an \
+:encoding: option\\n?
+%(root)s/includes.txt:4: WARNING: download file not readable: .*?nonexisting.png
+%(root)s/markup.txt:\\d+: WARNING: Malformed :option: u'Python c option', does \
+not contain option marker - or -- or /
+%(root)s/objects.txt:\\d*: WARNING: using old C markup; please migrate to \
+new-style markup \(e.g. c:function instead of cfunction\), see \
+http://sphinx-doc.org/domains.html
+"""
+
+HTML_WARNINGS = ENV_WARNINGS + """\
+%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
+None:\\d+: WARNING: citation not found: missing
+%(root)s/markup.txt:: WARNING: invalid single index entry u''
+%(root)s/markup.txt:: WARNING: invalid pair index entry u''
+%(root)s/markup.txt:: WARNING: invalid pair index entry u'keyword; '
+"""
+
+if sys.version_info >= (3, 0):
+ ENV_WARNINGS = remove_unicode_literals(ENV_WARNINGS)
+ HTML_WARNINGS = remove_unicode_literals(HTML_WARNINGS)
+
+
+def tail_check(check):
+ rex = re.compile(check)
+ def checker(nodes):
+ for node in nodes:
+ if node.tail and rex.search(node.tail):
+ return True
+ assert False, '%r not found in tail of any nodes %s' % (check, nodes)
+ return checker
+
+
+HTML_XPATH = {
+ 'images.html': [
+ (".//img[@src='_images/img.png']", ''),
+ (".//img[@src='_images/img1.png']", ''),
+ (".//img[@src='_images/simg.png']", ''),
+ (".//img[@src='_images/svgimg.svg']", ''),
+ ],
+ 'subdir/images.html': [
+ (".//img[@src='../_images/img1.png']", ''),
+ (".//img[@src='../_images/rimg.png']", ''),
+ ],
+ 'subdir/includes.html': [
+ (".//a[@href='../_downloads/img.png']", ''),
+ (".//img[@src='../_images/img.png']", ''),
+ (".//p", 'This is an include file.'),
+ ],
+ 'includes.html': [
+ (".//pre", u'Max Strauß'),
+ (".//a[@href='_downloads/img.png']", ''),
+ (".//a[@href='_downloads/img1.png']", ''),
+ (".//pre", u'"quotes"'),
+ (".//pre", u"'included'"),
+ ],
+ 'autodoc.html': [
+ (".//dt[@id='test_autodoc.Class']", ''),
+ (".//dt[@id='test_autodoc.function']/em", r'\*\*kwds'),
+ (".//dd/p", r'Return spam\.'),
+ ],
+ 'extapi.html': [
+ (".//strong", 'from function: Foo'),
+ (".//strong", 'from class: Bar'),
+ ],
+ 'markup.html': [
+ (".//title", 'set by title directive'),
+ (".//p/em", 'Section author: Georg Brandl'),
+ (".//p/em", 'Module author: Georg Brandl'),
+ # created by the meta directive
+ (".//meta[@name='author'][@content='Me']", ''),
+ (".//meta[@name='keywords'][@content='docs, sphinx']", ''),
+ # a label created by ``.. _label:``
+ (".//div[@id='label']", ''),
+ # code with standard code blocks
+ (".//pre", '^some code$'),
+ # an option list
+ (".//span[@class='option']", '--help'),
+ # admonitions
+ (".//p[@class='first admonition-title']", 'My Admonition'),
+ (".//p[@class='last']", 'Note text.'),
+ (".//p[@class='last']", 'Warning text.'),
+ # inline markup
+ (".//li/strong", r'^command\\n$'),
+ (".//li/strong", r'^program\\n$'),
+ (".//li/em", r'^dfn\\n$'),
+ (".//li/tt/span[@class='pre']", r'^kbd\\n$'),
+ (".//li/em", u'File \N{TRIANGULAR BULLET} Close'),
+ (".//li/tt/span[@class='pre']", '^a/$'),
+ (".//li/tt/em/span[@class='pre']", '^varpart$'),
+ (".//li/tt/em/span[@class='pre']", '^i$'),
+ (".//a[@href='http://www.python.org/dev/peps/pep-0008']"
+ "[@class='pep reference external']/strong", 'PEP 8'),
+ (".//a[@href='http://tools.ietf.org/html/rfc1.html']"
+ "[@class='rfc reference external']/strong", 'RFC 1'),
+ (".//a[@href='objects.html#envvar-HOME']"
+ "[@class='reference internal']/tt/span[@class='pre']", 'HOME'),
+ (".//a[@href='#with']"
+ "[@class='reference internal']/tt/span[@class='pre']", '^with$'),
+ (".//a[@href='#grammar-token-try_stmt']"
+ "[@class='reference internal']/tt/span", '^statement$'),
+ (".//a[@href='subdir/includes.html']"
+ "[@class='reference internal']/em", 'Including in subdir'),
+ (".//a[@href='objects.html#cmdoption-python-c']"
+ "[@class='reference internal']/em", 'Python -c option'),
+ # abbreviations
+ (".//abbr[@title='abbreviation']", '^abbr$'),
+ # version stuff
+ (".//div[@class='versionadded']/p/span", 'New in version 0.6: '),
+ (".//div[@class='versionadded']/p/span",
+ tail_check('First paragraph of versionadded')),
+ (".//div[@class='versionchanged']/p/span",
+ tail_check('First paragraph of versionchanged')),
+ (".//div[@class='versionchanged']/p",
+ 'Second paragraph of versionchanged'),
+ # footnote reference
+ (".//a[@class='footnote-reference']", r'\[1\]'),
+ # created by reference lookup
+ (".//a[@href='contents.html#ref1']", ''),
+ # ``seealso`` directive
+ (".//div/p[@class='first admonition-title']", 'See also'),
+ # a ``hlist`` directive
+ (".//table[@class='hlist']/tr/td/ul/li", '^This$'),
+ # a ``centered`` directive
+ (".//p[@class='centered']/strong", 'LICENSE'),
+ # a glossary
+ (".//dl/dt[@id='term-boson']", 'boson'),
+ # a production list
+ (".//pre/strong", 'try_stmt'),
+ (".//pre/a[@href='#grammar-token-try1_stmt']/tt/span", 'try1_stmt'),
+ # tests for ``only`` directive
+ (".//p", 'A global substitution.'),
+ (".//p", 'In HTML.'),
+ (".//p", 'In both.'),
+ (".//p", 'Always present'),
+ ],
+ 'objects.html': [
+ (".//dt[@id='mod.Cls.meth1']", ''),
+ (".//dt[@id='errmod.Error']", ''),
+ (".//dt/tt", r'long\(parameter,\s* list\)'),
+ (".//dt/tt", 'another one'),
+ (".//a[@href='#mod.Cls'][@class='reference internal']", ''),
+ (".//dl[@class='userdesc']", ''),
+ (".//dt[@id='userdesc-myobj']", ''),
+ (".//a[@href='#userdesc-myobj'][@class='reference internal']", ''),
+ # C references
+ (".//span[@class='pre']", 'CFunction()'),
+ (".//a[@href='#c.Sphinx_DoSomething']", ''),
+ (".//a[@href='#c.SphinxStruct.member']", ''),
+ (".//a[@href='#c.SPHINX_USE_PYTHON']", ''),
+ (".//a[@href='#c.SphinxType']", ''),
+ (".//a[@href='#c.sphinx_global']", ''),
+ # reference from old C markup extension
+ (".//a[@href='#c.Sphinx_Func']", ''),
+ # test global TOC created by toctree()
+ (".//ul[@class='current']/li[@class='toctree-l1 current']/a[@href='']",
+ 'Testing object descriptions'),
+ (".//li[@class='toctree-l1']/a[@href='markup.html']",
+ 'Testing various markup'),
+ # test unknown field names
+ (".//th[@class='field-name']", 'Field_name:'),
+ (".//th[@class='field-name']", 'Field_name all lower:'),
+ (".//th[@class='field-name']", 'FIELD_NAME:'),
+ (".//th[@class='field-name']", 'FIELD_NAME ALL CAPS:'),
+ (".//th[@class='field-name']", 'Field_Name:'),
+ (".//th[@class='field-name']", 'Field_Name All Word Caps:'),
+ (".//th[@class='field-name']", 'Field_name:'),
+ (".//th[@class='field-name']", 'Field_name First word cap:'),
+ (".//th[@class='field-name']", 'FIELd_name:'),
+ (".//th[@class='field-name']", 'FIELd_name PARTial caps:'),
+ # custom sidebar
+ (".//h4", 'Custom sidebar'),
+ # docfields
+ (".//td[@class='field-body']/strong", '^moo$'),
+ (".//td[@class='field-body']/strong",
+ tail_check(r'\(Moo\) .* Moo')),
+ (".//td[@class='field-body']/ul/li/strong", '^hour$'),
+ (".//td[@class='field-body']/ul/li/em", '^DuplicateType$'),
+ (".//td[@class='field-body']/ul/li/em",
+ tail_check(r'.* Some parameter')),
+ ],
+ 'contents.html': [
+ (".//meta[@name='hc'][@content='hcval']", ''),
+ (".//meta[@name='hc_co'][@content='hcval_co']", ''),
+ (".//meta[@name='testopt'][@content='testoverride']", ''),
+ (".//td[@class='label']", r'\[Ref1\]'),
+ (".//td[@class='label']", ''),
+ (".//li[@class='toctree-l1']/a", 'Testing various markup'),
+ (".//li[@class='toctree-l2']/a", 'Inline markup'),
+ (".//title", 'Sphinx <Tests>'),
+ (".//div[@class='footer']", 'Georg Brandl & Team'),
+ (".//a[@href='http://python.org/']"
+ "[@class='reference external']", ''),
+ (".//li/a[@href='genindex.html']/em", 'Index'),
+ (".//li/a[@href='py-modindex.html']/em", 'Module Index'),
+ (".//li/a[@href='search.html']/em", 'Search Page'),
+ # custom sidebar only for contents
+ (".//h4", 'Contents sidebar'),
+ # custom JavaScript
+ (".//script[@src='file://moo.js']", ''),
+ ],
+ 'bom.html': [
+ (".//title", " File with UTF-8 BOM"),
+ ],
+ 'extensions.html': [
+ (".//a[@href='http://python.org/dev/']", "http://python.org/dev/"),
+ (".//a[@href='http://bugs.python.org/issue1000']", "issue 1000"),
+ (".//a[@href='http://bugs.python.org/issue1042']", "explicit caption"),
+ ],
+ '_static/statictmpl.html': [
+ (".//project", 'Sphinx <Tests>'),
+ ],
+ 'genindex.html': [
+ # index entries
+ (".//a/strong", "Main"),
+ (".//a/strong", "[1]"),
+ (".//a/strong", "Other"),
+ (".//a", "entry"),
+ (".//dt/a", "double"),
+ ]
+}
+
+if pygments:
+ HTML_XPATH['includes.html'].extend([
+ (".//pre/span[@class='s']", u'üöä'),
+ (".//div[@class='inc-pyobj1 highlight-text']//pre",
+ r'^class Foo:\n pass\n\s*$'),
+ (".//div[@class='inc-pyobj2 highlight-text']//pre",
+ r'^ def baz\(\):\n pass\n\s*$'),
+ (".//div[@class='inc-lines highlight-text']//pre",
+ r'^class Foo:\n pass\nclass Bar:\n$'),
+ (".//div[@class='inc-startend highlight-text']//pre",
+ ur'^foo = "Including Unicode characters: üöä"\n$'),
+ (".//div[@class='inc-preappend highlight-text']//pre",
+ r'(?m)^START CODE$'),
+ (".//div[@class='inc-pyobj-dedent highlight-python']//span",
+ r'def'),
+ (".//div[@class='inc-tab3 highlight-text']//pre",
+ r'-| |-'),
+ (".//div[@class='inc-tab8 highlight-python']//pre/span",
+ r'-| |-'),
+ ])
+ HTML_XPATH['subdir/includes.html'].extend([
+ (".//pre/span", 'line 1'),
+ (".//pre/span", 'line 2'),
+ ])
+
+class NslessParser(ET.XMLParser):
+ """XMLParser that throws away namespaces in tag names."""
+
+ def _fixname(self, key):
+ try:
+ return self._names[key]
+ except KeyError:
+ name = key
+ br = name.find('}')
+ if br > 0:
+ name = name[br+1:]
+ self._names[key] = name = self._fixtext(name)
+ return name
+
+
+def check_xpath(etree, fname, path, check):
+ nodes = list(etree.findall(path))
+ assert nodes != [], ('did not find any node matching xpath '
+ '%r in file %s' % (path, fname))
+ if hasattr(check, '__call__'):
+ check(nodes)
+ elif not check:
+ # only check for node presence
+ pass
+ else:
+ rex = re.compile(check)
+ for node in nodes:
+ if node.text and rex.search(node.text):
+ break
+ else:
+ assert False, ('%r not found in any node matching '
+ 'path %s in %s: %r' % (check, path, fname,
+ [node.text for node in nodes]))
+
+def check_static_entries(outdir):
+ staticdir = outdir / '_static'
+ assert staticdir.isdir()
+ # a file from a directory entry in html_static_path
+ assert (staticdir / 'README').isfile()
+ # a directory from a directory entry in html_static_path
+ assert (staticdir / 'subdir' / 'foo.css').isfile()
+ # a file from a file entry in html_static_path
+ assert (staticdir / 'templated.css').isfile()
+ assert (staticdir / 'templated.css').text().splitlines()[1] == __version__
+ # a file from _static, but matches exclude_patterns
+ assert not (staticdir / 'excluded.css').exists()
+
+def check_extra_entries(outdir):
+ assert (outdir / 'robots.txt').isfile()
+
+ at gen_with_app(buildername='html', warning=html_warnfile, cleanenv=True,
+ confoverrides={'html_context.hckey_co': 'hcval_co'},
+ tags=['testtag'])
+def test_html(app):
+ app.builder.build_all()
+ html_warnings = html_warnfile.getvalue().replace(os.sep, '/')
+ html_warnings_exp = HTML_WARNINGS % {
+ 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
+ assert re.match(html_warnings_exp + '$', html_warnings), \
+ 'Warnings don\'t match:\n' + \
+ '--- Expected (regex):\n' + html_warnings_exp + \
+ '--- Got:\n' + html_warnings
+
+ for fname, paths in HTML_XPATH.iteritems():
+ parser = NslessParser()
+ parser.entity.update(htmlentitydefs.entitydefs)
+ fp = open(os.path.join(app.outdir, fname), 'rb')
+ try:
+ etree = ET.parse(fp, parser)
+ finally:
+ fp.close()
+ for path, check in paths:
+ yield check_xpath, etree, fname, path, check
+
+ check_static_entries(app.builder.outdir)
+ check_extra_entries(app.builder.outdir)
+
+ at with_app(buildername='html', srcdir='(empty)',
+ confoverrides={'html_sidebars': {'*': ['globaltoc.html']}},
+ )
+def test_html_with_globaltoc_and_hidden_toctree(app):
+ # issue #1157: combination of 'globaltoc.html' and hidden toctree cause
+ # exception.
+ (app.srcdir / 'contents.rst').write_text(
+ '\n.. toctree::'
+ '\n'
+ '\n.. toctree::'
+ '\n :hidden:'
+ '\n')
+ app.builder.build_all()
diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py
new file mode 100644
index 0000000..78aa71c
--- /dev/null
+++ b/tests/test_build_latex.py
@@ -0,0 +1,98 @@
+# -*- coding: utf-8 -*-
+"""
+ test_build_latex
+ ~~~~~~~~~~~~~~~~
+
+ Test the build process with LaTeX builder with the test root.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import sys
+from StringIO import StringIO
+from subprocess import Popen, PIPE
+
+from sphinx.writers.latex import LaTeXTranslator
+
+from util import test_root, SkipTest, remove_unicode_literals, with_app
+from test_build_html import ENV_WARNINGS
+
+
+def teardown_module():
+ (test_root / '_build').rmtree(True)
+
+
+latex_warnfile = StringIO()
+
+LATEX_WARNINGS = ENV_WARNINGS + """\
+None:None: WARNING: citation not found: missing
+None:None: WARNING: no matching candidate for image URI u'foo.\\*'
+WARNING: invalid pair index entry u''
+WARNING: invalid pair index entry u'keyword; '
+"""
+
+if sys.version_info >= (3, 0):
+ LATEX_WARNINGS = remove_unicode_literals(LATEX_WARNINGS)
+
+
+ at with_app(buildername='latex', warning=latex_warnfile, cleanenv=True)
+def test_latex(app):
+ LaTeXTranslator.ignore_missing_images = True
+ app.builder.build_all()
+ latex_warnings = latex_warnfile.getvalue().replace(os.sep, '/')
+ latex_warnings_exp = LATEX_WARNINGS % {
+ 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
+ assert re.match(latex_warnings_exp + '$', latex_warnings), \
+ 'Warnings don\'t match:\n' + \
+ '--- Expected (regex):\n' + latex_warnings_exp + \
+ '--- Got:\n' + latex_warnings
+
+ # file from latex_additional_files
+ assert (app.outdir / 'svgimg.svg').isfile()
+
+ # only run latex if all needed packages are there
+ def kpsetest(filename):
+ try:
+ p = Popen(['kpsewhich', filename], stdout=PIPE)
+ except OSError:
+ # no kpsewhich... either no tex distribution is installed or it is
+ # a "strange" one -- don't bother running latex
+ return None
+ else:
+ p.communicate()
+ if p.returncode != 0:
+ # not found
+ return False
+ # found
+ return True
+
+ if kpsetest('article.sty') is None:
+ raise SkipTest('not running latex, it doesn\'t seem to be installed')
+ for filename in ['fancyhdr.sty', 'fancybox.sty', 'titlesec.sty',
+ 'amsmath.sty', 'framed.sty', 'color.sty', 'fancyvrb.sty',
+ 'threeparttable.sty']:
+ if not kpsetest(filename):
+ raise SkipTest('not running latex, the %s package doesn\'t '
+ 'seem to be installed' % filename)
+
+ # now, try to run latex over it
+ cwd = os.getcwd()
+ os.chdir(app.outdir)
+ try:
+ try:
+ p = Popen(['pdflatex', '--interaction=nonstopmode',
+ 'SphinxTests.tex'], stdout=PIPE, stderr=PIPE)
+ except OSError:
+ raise SkipTest # most likely pdflatex was not found
+ else:
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ print stdout
+ print stderr
+ del app.cleanup_trees[:]
+ assert False, 'latex exited with return code %s' % p.returncode
+ finally:
+ os.chdir(cwd)
diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py
new file mode 100644
index 0000000..2f51943
--- /dev/null
+++ b/tests/test_build_texinfo.py
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+"""
+ test_build_texinfo
+ ~~~~~~~~~~~~~~~~~~
+
+ Test the build process with Texinfo builder with the test root.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import sys
+from StringIO import StringIO
+from subprocess import Popen, PIPE
+
+from sphinx.writers.texinfo import TexinfoTranslator
+
+from util import test_root, SkipTest, remove_unicode_literals, with_app
+from test_build_html import ENV_WARNINGS
+
+
+def teardown_module():
+ (test_root / '_build').rmtree(True)
+
+
+texinfo_warnfile = StringIO()
+
+TEXINFO_WARNINGS = ENV_WARNINGS + """\
+None:None: WARNING: citation not found: missing
+None:None: WARNING: no matching candidate for image URI u'foo.\\*'
+None:None: WARNING: no matching candidate for image URI u'svgimg.\\*'
+"""
+
+if sys.version_info >= (3, 0):
+ TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS)
+
+
+ at with_app(buildername='texinfo', warning=texinfo_warnfile, cleanenv=True)
+def test_texinfo(app):
+ TexinfoTranslator.ignore_missing_images = True
+ app.builder.build_all()
+ texinfo_warnings = texinfo_warnfile.getvalue().replace(os.sep, '/')
+ texinfo_warnings_exp = TEXINFO_WARNINGS % {
+ 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
+ assert re.match(texinfo_warnings_exp + '$', texinfo_warnings), \
+ 'Warnings don\'t match:\n' + \
+ '--- Expected (regex):\n' + texinfo_warnings_exp + \
+ '--- Got:\n' + texinfo_warnings
+ # now, try to run makeinfo over it
+ cwd = os.getcwd()
+ os.chdir(app.outdir)
+ try:
+ try:
+ p = Popen(['makeinfo', '--no-split', 'SphinxTests.texi'],
+ stdout=PIPE, stderr=PIPE)
+ except OSError:
+ raise SkipTest # most likely makeinfo was not found
+ else:
+ stdout, stderr = p.communicate()
+ retcode = p.returncode
+ if retcode != 0:
+ print stdout
+ print stderr
+ del app.cleanup_trees[:]
+ assert False, 'makeinfo exited with return code %s' % retcode
+ finally:
+ os.chdir(cwd)
diff --git a/tests/test_build_text.py b/tests/test_build_text.py
new file mode 100644
index 0000000..e6e4d5b
--- /dev/null
+++ b/tests/test_build_text.py
@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*-
+"""
+ test_build_text
+ ~~~~~~~~~~~~~~~
+
+ Test the build process with Text builder with the test root.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils.utils import column_width
+from sphinx.writers.text import MAXWIDTH
+
+from util import with_app
+
+
+def with_text_app(*args, **kw):
+ default_kw = {
+ 'buildername': 'text',
+ 'srcdir': '(empty)',
+ 'confoverrides': {
+ 'project': 'text',
+ 'master_doc': 'contents',
+ },
+ }
+ default_kw.update(kw)
+ return with_app(*args, **default_kw)
+
+
+ at with_text_app()
+def test_maxwitdh_with_prefix(app):
+ long_string = u' '.join([u"ham"] * 30)
+ contents = (
+ u".. seealso:: %(long_string)s\n\n"
+ u"* %(long_string)s\n"
+ u"* %(long_string)s\n"
+ u"\nspam egg\n"
+ ) % locals()
+
+ (app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
+ app.builder.build_all()
+ result = (app.outdir / 'contents.txt').text(encoding='utf-8')
+
+ lines = result.splitlines()
+ line_widths = [column_width(line) for line in lines]
+ assert max(line_widths) < MAXWIDTH
+ assert lines[0].startswith('See also: ham')
+ assert lines[1].startswith(' ham')
+ assert lines[2] == ''
+ assert lines[3].startswith('* ham')
+ assert lines[4].startswith(' ham')
+ assert lines[5] == ''
+ assert lines[6].startswith('* ham')
+ assert lines[7].startswith(' ham')
+ assert lines[8] == ''
+ assert lines[9].startswith('spam egg')
+
+
+ at with_text_app()
+def test_lineblock(app):
+ # regression test for #1109: need empty line after line block
+ contents = (
+ u"* one\n"
+ u"\n"
+ u" | line-block 1\n"
+ u" | line-block 2\n"
+ u"\n"
+ u"followed paragraph.\n"
+ )
+
+ (app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
+ app.builder.build_all()
+ result = (app.outdir / 'contents.txt').text(encoding='utf-8')
+
+ expect = (
+ u"* one\n"
+ u"\n"
+ u" line-block 1\n"
+ u" line-block 2\n"
+ u"\n"
+ u"followed paragraph.\n"
+ )
+
+ assert result == expect
+
+
+ at with_text_app()
+def test_nonascii_title_line(app):
+ title = u'\u65e5\u672c\u8a9e'
+ underline = u'=' * column_width(title)
+ content = u'\n'.join((title, underline, u''))
+
+ (app.srcdir / 'contents.rst').write_text(content, encoding='utf-8')
+ app.builder.build_all()
+ result = (app.outdir / 'contents.txt').text(encoding='utf-8')
+
+ expect_underline = underline.replace('=', '*')
+ result_underline = result.splitlines()[2].strip()
+ assert expect_underline == result_underline
+
+
+ at with_text_app()
+def test_nonascii_table(app):
+ text = u'\u65e5\u672c\u8a9e'
+ contents = (u"\n.. list-table::"
+ "\n"
+ "\n - - spam"
+ "\n - egg"
+ "\n"
+ "\n - - %(text)s"
+ "\n - %(text)s"
+ "\n" % locals())
+
+ (app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
+ app.builder.build_all()
+ result = (app.outdir / 'contents.txt').text(encoding='utf-8')
+
+ lines = [line.strip() for line in result.splitlines() if line.strip()]
+ line_widths = [column_width(line) for line in lines]
+ assert len(set(line_widths)) == 1 # same widths
+
+
+ at with_text_app()
+def test_nonascii_maxwidth(app):
+ sb_text = u'abc' #length=3
+ mb_text = u'\u65e5\u672c\u8a9e' #length=3
+
+ sb_line = ' '.join([sb_text] * int(MAXWIDTH / 3))
+ mb_line = ' '.join([mb_text] * int(MAXWIDTH / 3))
+ mix_line = ' '.join([sb_text, mb_text] * int(MAXWIDTH / 6))
+
+ contents = u'\n\n'.join((sb_line, mb_line, mix_line))
+
+ (app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
+ app.builder.build_all()
+ result = (app.outdir / 'contents.txt').text(encoding='utf-8')
+
+ lines = [line.strip() for line in result.splitlines() if line.strip()]
+ line_widths = [column_width(line) for line in lines]
+ assert max(line_widths) < MAXWIDTH
+
+
+ at with_text_app()
+def test_table_with_empty_cell(app):
+ contents = (u"""
+ +-----+-----+
+ | XXX | XXX |
+ +-----+-----+
+ | | XXX |
+ +-----+-----+
+ | XXX | |
+ +-----+-----+
+ """)
+
+ (app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8')
+ app.builder.build_all()
+ result = (app.outdir / 'contents.txt').text(encoding='utf-8')
+
+ lines = [line.strip() for line in result.splitlines() if line.strip()]
+ assert lines[0] == "+-------+-------+"
+ assert lines[1] == "| XXX | XXX |"
+ assert lines[2] == "+-------+-------+"
+ assert lines[3] == "| | XXX |"
+ assert lines[4] == "+-------+-------+"
+ assert lines[5] == "| XXX | |"
+ assert lines[6] == "+-------+-------+"
diff --git a/tests/test_config.py b/tests/test_config.py
new file mode 100644
index 0000000..1e00091
--- /dev/null
+++ b/tests/test_config.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+"""
+ test_config
+ ~~~~~~~~~~~
+
+ Test the sphinx.config.Config class and its handling in the
+ Application class.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import sys
+
+from util import TestApp, with_app, with_tempdir, raises, raises_msg, write_file
+
+from sphinx.config import Config
+from sphinx.errors import ExtensionError, ConfigError, VersionRequirementError
+from sphinx.util.pycompat import b
+
+
+ at with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True',
+ 'latex_elements.docclass': 'scrartcl'})
+def test_core_config(app):
+ cfg = app.config
+
+ # simple values
+ assert 'project' in cfg.__dict__
+ assert cfg.project == 'Sphinx <Tests>'
+ assert cfg.templates_path == ['_templates']
+
+ # overrides
+ assert cfg.master_doc == 'master'
+ assert cfg.latex_elements['docclass'] == 'scrartcl'
+
+ # simple default values
+ assert 'locale_dirs' not in cfg.__dict__
+ assert cfg.locale_dirs == []
+ assert cfg.trim_footnote_reference_space == False
+
+ # complex default values
+ assert 'html_title' not in cfg.__dict__
+ assert cfg.html_title == 'Sphinx <Tests> 0.6alpha1 documentation'
+
+ # complex default values mustn't raise
+ for valuename in cfg.config_values:
+ getattr(cfg, valuename)
+
+ # "contains" gives True both for set and unset values
+ assert 'project' in cfg
+ assert 'html_title' in cfg
+ assert 'nonexisting_value' not in cfg
+
+ # invalid values
+ raises(AttributeError, getattr, cfg, '_value')
+ raises(AttributeError, getattr, cfg, 'nonexisting_value')
+
+ # non-value attributes are deleted from the namespace
+ raises(AttributeError, getattr, cfg, 'sys')
+
+ # setting attributes
+ cfg.project = 'Foo'
+ assert cfg.project == 'Foo'
+
+ # alternative access via item interface
+ cfg['project'] = 'Sphinx Tests'
+ assert cfg['project'] == cfg.project == 'Sphinx Tests'
+
+
+ at with_app()
+def test_extension_values(app):
+ cfg = app.config
+
+ # default value
+ assert cfg.value_from_ext == []
+ # non-default value
+ assert cfg.value_from_conf_py == 84
+
+ # no duplicate values allowed
+ raises_msg(ExtensionError, 'already present', app.add_config_value,
+ 'html_title', 'x', True)
+ raises_msg(ExtensionError, 'already present', app.add_config_value,
+ 'value_from_ext', 'x', True)
+
+
+ at with_tempdir
+def test_errors_warnings(dir):
+ # test the error for syntax errors in the config file
+ write_file(dir / 'conf.py', u'project = \n', 'ascii')
+ raises_msg(ConfigError, 'conf.py', Config, dir, 'conf.py', {}, None)
+
+ # test the automatic conversion of 2.x only code in configs
+ write_file(dir / 'conf.py', u'# -*- coding: utf-8\n\n'
+ u'project = u"Jägermeister"\n', 'utf-8')
+ cfg = Config(dir, 'conf.py', {}, None)
+ cfg.init_values()
+ assert cfg.project == u'Jägermeister'
+
+ # test the warning for bytestrings with non-ascii content
+ # bytestrings with non-ascii content are a syntax error in python3 so we
+ # skip the test there
+ if sys.version_info >= (3, 0):
+ return
+ write_file(dir / 'conf.py', u'# -*- coding: latin-1\nproject = "fooä"\n',
+ 'latin-1')
+ cfg = Config(dir, 'conf.py', {}, None)
+ warned = [False]
+ def warn(msg):
+ warned[0] = True
+ cfg.check_unicode(warn)
+ assert warned[0]
+
+
+ at with_tempdir
+def test_errors_if_setup_is_not_callable(dir):
+ # test the error to call setup() in the config file
+ (dir / 'conf.py').write_text(u'setup = 1')
+ raises_msg(ConfigError, 'callable', TestApp, srcdir=dir)
+
+
+def test_needs_sphinx():
+ raises(VersionRequirementError, TestApp,
+ confoverrides={'needs_sphinx': '9.9'})
+
+
+ at with_tempdir
+def test_config_eol(tmpdir):
+ # test config file's eol patterns: LF, CRLF
+ configfile = tmpdir / 'conf.py'
+ for eol in ('\n', '\r\n'):
+ configfile.write_bytes(b('project = "spam"' + eol))
+ cfg = Config(tmpdir, 'conf.py', {}, None)
+ cfg.init_values()
+ assert cfg.project == u'spam'
diff --git a/tests/test_coverage.py b/tests/test_coverage.py
new file mode 100644
index 0000000..e6747b0
--- /dev/null
+++ b/tests/test_coverage.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+"""
+ test_coverage
+ ~~~~~~~~~~~~~
+
+ Test the coverage builder.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import pickle
+
+from util import with_app
+
+
+ at with_app(buildername='coverage')
+def test_build(app):
+ app.builder.build_all()
+
+ py_undoc = (app.outdir / 'python.txt').text()
+ assert py_undoc.startswith('Undocumented Python objects\n'
+ '===========================\n')
+ assert 'test_autodoc\n------------\n' in py_undoc
+ assert ' * Class -- missing methods:\n' in py_undoc
+ assert ' * process_docstring\n' in py_undoc
+ assert ' * function\n' not in py_undoc # these two are documented
+ assert ' * Class\n' not in py_undoc # in autodoc.txt
+
+ assert ' * mod -- No module named mod' # in the "failed import" section
+
+ c_undoc = (app.outdir / 'c.txt').text()
+ assert c_undoc.startswith('Undocumented C API elements\n'
+ '===========================\n')
+ assert 'api.h' in c_undoc
+ assert ' * Py_SphinxTest' in c_undoc
+
+ undoc_py, undoc_c = pickle.loads((app.outdir / 'undoc.pickle').bytes())
+ assert len(undoc_c) == 1
+ # the key is the full path to the header file, which isn't testable
+ assert undoc_c.values()[0] == [('function', 'Py_SphinxTest')]
+
+ assert 'test_autodoc' in undoc_py
+ assert 'funcs' in undoc_py['test_autodoc']
+ assert 'process_docstring' in undoc_py['test_autodoc']['funcs']
+ assert 'classes' in undoc_py['test_autodoc']
+ assert 'Class' in undoc_py['test_autodoc']['classes']
+ assert 'undocmeth' in undoc_py['test_autodoc']['classes']['Class']
diff --git a/tests/test_cpp_domain.py b/tests/test_cpp_domain.py
new file mode 100644
index 0000000..8e1cb22
--- /dev/null
+++ b/tests/test_cpp_domain.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+"""
+ test_cpp_domain
+ ~~~~~~~~~~~~~~~
+
+ Tests the C++ Domain
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from util import raises
+
+from sphinx.domains.cpp import DefinitionParser, DefinitionError
+
+
+def parse(name, string):
+ return getattr(DefinitionParser(string), 'parse_' + name)()
+
+
+def test_type_definitions():
+ rv = parse('member_object', ' const std::string & name = 42')
+ assert unicode(rv) == 'const std::string& name = 42'
+
+ rv = parse('member_object', ' const std::string & name leftover')
+ assert unicode(rv) == 'const std::string& name'
+
+ rv = parse('member_object', ' const std::string & name [n] leftover')
+ assert unicode(rv) == 'const std::string& name[n]'
+
+ rv = parse('member_object', 'const std::vector< unsigned int, long> &name')
+ assert unicode(rv) == 'const std::vector<unsigned int, long>& name'
+
+ x = 'std::vector<std::pair<std::string, int>>& module::test(register ' \
+ 'foo, bar, std::string baz="foobar, blah, bleh") const = 0'
+ assert unicode(parse('function', x)) == x
+
+ x = 'module::myclass::operator std::vector<std::string>()'
+ assert unicode(parse('function', x)) == x
+ x = 'explicit module::myclass::foo::foo()'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int printf(const char* fmt, ...)'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int foo(const unsigned int j)'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int foo(const unsigned int const j)'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int foo(const int* const ptr)'
+ assert unicode(parse('function', x)) == x
+
+ x = 'std::vector<std::pair<std::string, long long>> module::blah'
+ assert unicode(parse('type_object', x)) == x
+
+ assert unicode(parse('type_object', 'long long int foo')) == 'long long foo'
+
+ x = 'void operator()(const boost::array<VertexID, 2>& v) const'
+ assert unicode(parse('function', x)) == x
+
+ x = 'void operator()(const boost::array<VertexID, 2, "foo, bar">& v) const'
+ assert unicode(parse('function', x)) == x
+
+ x = 'MyClass::MyClass(MyClass::MyClass&&)'
+ assert unicode(parse('function', x)) == x
+
+ x = 'constexpr int get_value()'
+ assert unicode(parse('function', x)) == x
+
+ x = 'static constexpr int get_value()'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int get_value() const noexcept'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int get_value() const noexcept = delete'
+ assert unicode(parse('function', x)) == x
+
+ x = 'MyClass::MyClass(MyClass::MyClass&&) = default'
+ assert unicode(parse('function', x)) == x
+
+ x = 'MyClass::a_virtual_function() const override'
+ assert unicode(parse('function', x)) == x
+
+ x = 'MyClass::a_member_function() volatile'
+ assert unicode(parse('function', x)) == x
+
+ x = 'MyClass::a_member_function() const volatile'
+ assert unicode(parse('function', x)) == x
+
+ x = 'MyClass::a_member_function() &&'
+ assert unicode(parse('function', x)) == x
+
+ x = 'MyClass::a_member_function() &'
+ assert unicode(parse('function', x)) == x
+
+ x = 'MyClass::a_member_function() const &'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int main(int argc, char* argv[][])'
+ assert unicode(parse('function', x)) == x
+
+ x = 'std::vector<std::pair<std::string, int>>& module::test(register ' \
+ 'foo, bar[n], std::string baz="foobar, blah, bleh") const = 0'
+ assert unicode(parse('function', x)) == x
+
+ x = 'module::myclass foo[n]'
+ assert unicode(parse('member_object', x)) == x
+
+ x = 'int foo(Foo f=Foo(double(), std::make_pair(int(2), double(3.4))))'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int foo(A a=x(a))'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int foo(B b=x(a)'
+ raises(DefinitionError, parse, 'function', x)
+
+ x = 'int foo)C c=x(a))'
+ raises(DefinitionError, parse, 'function', x)
+
+ x = 'int foo(D d=x(a'
+ raises(DefinitionError, parse, 'function', x)
+
+
+def test_bases():
+ x = 'A'
+ assert unicode(parse('class', x)) == x
+
+ x = 'A : B'
+ assert unicode(parse('class', x)) == x
+
+ x = 'A : private B'
+ assert unicode(parse('class', x)) == 'A : B'
+
+ x = 'A : public B'
+ assert unicode(parse('class', x)) == x
+
+ x = 'A : B, C'
+ assert unicode(parse('class', x)) == x
+
+ x = 'A : B, protected C, D'
+ assert unicode(parse('class', x)) == x
+
+
+def test_operators():
+ x = parse('function', 'void operator new [ ] ()')
+ assert unicode(x) == 'void operator new[]()'
+
+ x = parse('function', 'void operator delete ()')
+ assert unicode(x) == 'void operator delete()'
+
+ for op in '*-+=/%!':
+ x = parse('function', 'void operator %s ()' % op)
+ assert unicode(x) == 'void operator%s()' % op
diff --git a/tests/test_doctest.py b/tests/test_doctest.py
new file mode 100644
index 0000000..2aab541
--- /dev/null
+++ b/tests/test_doctest.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+"""
+ test_doctest
+ ~~~~~~~~~~~~
+
+ Test the doctest extension.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import StringIO
+
+from util import with_app
+
+
+status = StringIO.StringIO()
+cleanup_called = 0
+
+ at with_app(buildername='doctest', status=status)
+def test_build(app):
+ global cleanup_called
+ cleanup_called = 0
+ app.builder.build_all()
+ if app.statuscode != 0:
+ print >>sys.stderr, status.getvalue()
+ assert False, 'failures in doctests'
+ # in doctest.txt, there are two named groups and the default group,
+ # so the cleanup function must be called three times
+ assert cleanup_called == 3, 'testcleanup did not get executed enough times'
+
+def cleanup_call():
+ global cleanup_called
+ cleanup_called += 1
diff --git a/tests/test_docutilsconf.py b/tests/test_docutilsconf.py
new file mode 100644
index 0000000..4aeaa56
--- /dev/null
+++ b/tests/test_docutilsconf.py
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+"""
+ test_docutilsconf
+ ~~~~~~~~~~~~~~~~~
+
+ Test docutils.conf support for several writers.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+from StringIO import StringIO
+from functools import wraps
+
+from util import test_roots, TestApp, path, SkipTest
+
+
+html_warnfile = StringIO()
+root = test_roots / 'test-docutilsconf'
+
+
+# need cleanenv to rebuild everytime.
+# docutils.conf change did not effect to rebuild.
+def with_conf_app(docutilsconf='', *args, **kwargs):
+ default_kw = {
+ 'srcdir': root,
+ 'cleanenv': True,
+ }
+ default_kw.update(kwargs)
+ def generator(func):
+ @wraps(func)
+ def deco(*args2, **kwargs2):
+ app = TestApp(*args, **default_kw)
+ (app.srcdir / 'docutils.conf').write_text(docutilsconf)
+ try:
+ cwd = os.getcwd()
+ os.chdir(app.srcdir)
+ func(app, *args2, **kwargs2)
+ finally:
+ os.chdir(cwd)
+ # don't execute cleanup if test failed
+ app.cleanup()
+ return deco
+ return generator
+
+
+def regex_count(expr, result):
+ return len(re.findall(expr, result))
+
+
+ at with_conf_app(buildername='html')
+def test_html_with_default_docutilsconf(app):
+ app.builder.build(['contents'])
+ result = (app.outdir / 'contents.html').text(encoding='utf-8')
+
+ assert regex_count(r'<th class="field-name">', result) == 1
+ assert regex_count(r'<th class="field-name" colspan="2">', result) == 1
+ assert regex_count(r'<td class="option-group">', result) == 1
+ assert regex_count(r'<td class="option-group" colspan="2">', result) == 1
+
+
+ at with_conf_app(buildername='html', docutilsconf=(
+ '\n[html4css1 writer]'
+ '\noption-limit:1'
+ '\nfield-name-limit:1'
+ '\n')
+)
+def test_html_with_docutilsconf(app):
+ app.builder.build(['contents'])
+ result = (app.outdir / 'contents.html').text(encoding='utf-8')
+
+ assert regex_count(r'<th class="field-name">', result) == 0
+ assert regex_count(r'<th class="field-name" colspan="2">', result) == 2
+ assert regex_count(r'<td class="option-group">', result) == 0
+ assert regex_count(r'<td class="option-group" colspan="2">', result) == 2
+
+
+ at with_conf_app(buildername='html', warning=html_warnfile)
+def test_html(app):
+ app.builder.build(['contents'])
+ assert html_warnfile.getvalue() == ''
+
+
+ at with_conf_app(buildername='latex', warning=html_warnfile)
+def test_latex(app):
+ app.builder.build(['contents'])
+ assert html_warnfile.getvalue() == ''
+
+
+ at with_conf_app(buildername='man', warning=html_warnfile)
+def test_man(app):
+ app.builder.build(['contents'])
+ assert html_warnfile.getvalue() == ''
+
+
+ at with_conf_app(buildername='texinfo', warning=html_warnfile)
+def test_texinfo(app):
+ app.builder.build(['contents'])
+
+
+ at with_conf_app(buildername='html', srcdir='(empty)',
+ docutilsconf='[general]\nsource_link=true\n')
+def test_docutils_source_link(app):
+ srcdir = path(app.srcdir)
+ (srcdir / 'conf.py').write_text('')
+ (srcdir / 'contents.rst').write_text('')
+ app.builder.build_all()
+
+
+ at with_conf_app(buildername='html', srcdir='(empty)',
+ docutilsconf='[general]\nsource_link=true\n')
+def test_docutils_source_link_with_nonascii_file(app):
+ srcdir = path(app.srcdir)
+ mb_name = u'\u65e5\u672c\u8a9e'
+ try:
+ (srcdir / (mb_name + '.txt')).write_text('')
+ except UnicodeEncodeError:
+ from path import FILESYSTEMENCODING
+ raise SkipTest(
+ 'nonascii filename not supported on this filesystem encoding: '
+ '%s', FILESYSTEMENCODING)
+
+ (srcdir / 'conf.py').write_text('')
+ (srcdir / 'contents.rst').write_text('')
+
+ app.builder.build_all()
diff --git a/tests/test_env.py b/tests/test_env.py
new file mode 100644
index 0000000..eaaa212
--- /dev/null
+++ b/tests/test_env.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+"""
+ test_env
+ ~~~~~~~~
+
+ Test the BuildEnvironment class.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import sys
+
+from util import TestApp, remove_unicode_literals, path
+
+from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.builders.latex import LaTeXBuilder
+
+app = env = None
+warnings = []
+
+def setup_module():
+ global app, env
+ app = TestApp(srcdir='(temp)', freshenv=True)
+ env = app.env
+ env.set_warnfunc(lambda *args: warnings.append(args))
+
+def teardown_module():
+ app.cleanup()
+
+def warning_emitted(file, text):
+ for warning in warnings:
+ if len(warning) == 2 and file in warning[1] and text in warning[0]:
+ return True
+ return False
+
+# Tests are run in the order they appear in the file, therefore we can
+# afford to not run update() in the setup but in its own test
+
+def test_first_update():
+ msg, num, it = env.update(app.config, app.srcdir, app.doctreedir, app)
+ assert msg.endswith('%d added, 0 changed, 0 removed' % len(env.found_docs))
+ docnames = set()
+ for docname in it: # the generator does all the work
+ docnames.add(docname)
+ assert docnames == env.found_docs == set(env.all_docs)
+ # test if exclude_patterns works ok
+ assert 'subdir/excluded' not in env.found_docs
+
+def test_images():
+ assert warning_emitted('images', 'image file not readable: foo.png')
+ assert warning_emitted('images', 'nonlocal image URI found: '
+ 'http://www.python.org/logo.png')
+
+ tree = env.get_doctree('images')
+ app._warning.reset()
+ htmlbuilder = StandaloneHTMLBuilder(app)
+ htmlbuilder.imgpath = 'dummy'
+ htmlbuilder.post_process_images(tree)
+ image_uri_message = "no matching candidate for image URI u'foo.*'"
+ if sys.version_info >= (3, 0):
+ image_uri_message = remove_unicode_literals(image_uri_message)
+ assert image_uri_message in app._warning.content[-1]
+ assert set(htmlbuilder.images.keys()) == \
+ set(['subdir/img.png', 'img.png', 'subdir/simg.png', 'svgimg.svg'])
+ assert set(htmlbuilder.images.values()) == \
+ set(['img.png', 'img1.png', 'simg.png', 'svgimg.svg'])
+
+ app._warning.reset()
+ latexbuilder = LaTeXBuilder(app)
+ latexbuilder.post_process_images(tree)
+ assert image_uri_message in app._warning.content[-1]
+ assert set(latexbuilder.images.keys()) == \
+ set(['subdir/img.png', 'subdir/simg.png', 'img.png', 'img.pdf',
+ 'svgimg.pdf'])
+ assert set(latexbuilder.images.values()) == \
+ set(['img.pdf', 'img.png', 'img1.png', 'simg.png', 'svgimg.pdf'])
+
+def test_second_update():
+ # delete, add and "edit" (change saved mtime) some files and update again
+ env.all_docs['contents'] = 0
+ root = path(app.srcdir)
+ # important: using "autodoc" because it is the last one to be included in
+ # the contents.txt toctree; otherwise section numbers would shift
+ (root / 'autodoc.txt').unlink()
+ (root / 'new.txt').write_text('New file\n========\n')
+ msg, num, it = env.update(app.config, app.srcdir, app.doctreedir, app)
+ assert '1 added, 3 changed, 1 removed' in msg
+ docnames = set()
+ for docname in it:
+ docnames.add(docname)
+ # "includes" and "images" are in there because they contain references
+ # to nonexisting downloadable or image files, which are given another
+ # chance to exist
+ assert docnames == set(['contents', 'new', 'includes', 'images'])
+ assert 'autodoc' not in env.all_docs
+ assert 'autodoc' not in env.found_docs
+
+def test_object_inventory():
+ refs = env.domaindata['py']['objects']
+
+ assert 'func_without_module' in refs
+ assert refs['func_without_module'] == ('objects', 'function')
+ assert 'func_without_module2' in refs
+ assert 'mod.func_in_module' in refs
+ assert 'mod.Cls' in refs
+ assert 'mod.Cls.meth1' in refs
+ assert 'mod.Cls.meth2' in refs
+ assert 'mod.Cls.meths' in refs
+
+ assert 'mod.Error' not in refs
+ assert 'errmod.Error' in refs
+
+ assert 'func_in_module' not in refs
+ assert 'func_noindex' not in refs
+
+ assert env.domaindata['py']['modules']['mod'] == \
+ ('objects', 'Module synopsis.', 'UNIX', False)
+
+ assert env.domains['py'].data is env.domaindata['py']
+ assert env.domains['c'].data is env.domaindata['c']
diff --git a/tests/test_footnote.py b/tests/test_footnote.py
new file mode 100644
index 0000000..964bb3e
--- /dev/null
+++ b/tests/test_footnote.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+"""
+ test_footnote
+ ~~~~~~~~~~~~~
+
+ Test for footnote and citation.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from util import test_root, with_app
+
+
+def teardown_module():
+ (test_root / '_build').rmtree(True)
+
+
+ at with_app(buildername='html')
+def test_html(app):
+ app.builder.build(['footnote'])
+ result = (app.outdir / 'footnote.html').text(encoding='utf-8')
+ expects = [
+ '<a class="footnote-reference" href="#id5" id="id1">[1]</a>',
+ '<a class="footnote-reference" href="#id6" id="id2">[2]</a>',
+ '<a class="footnote-reference" href="#foo" id="id3">[3]</a>',
+ '<a class="reference internal" href="#bar" id="id4">[bar]</a>',
+ '<a class="fn-backref" href="#id1">[1]</a>',
+ '<a class="fn-backref" href="#id2">[2]</a>',
+ '<a class="fn-backref" href="#id3">[3]</a>',
+ '<a class="fn-backref" href="#id4">[bar]</a>',
+ ]
+ for expect in expects:
+ matches = re.findall(re.escape(expect), result)
+ assert len(matches) == 1
diff --git a/tests/test_highlighting.py b/tests/test_highlighting.py
new file mode 100644
index 0000000..b4e5149
--- /dev/null
+++ b/tests/test_highlighting.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+"""
+ test_highlighting
+ ~~~~~~~~~~~~~~~~~
+
+ Test the Pygments highlighting bridge.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from pygments.lexer import RegexLexer
+from pygments.token import Text, Name
+from pygments.formatters.html import HtmlFormatter
+
+from sphinx.highlighting import PygmentsBridge
+
+from util import with_app, SkipTest
+
+try:
+ import pygments
+except ImportError:
+ raise SkipTest('pygments not available')
+
+
+class MyLexer(RegexLexer):
+ name = 'testlexer'
+
+ tokens = {
+ 'root': [
+ ('a', Name),
+ ('b', Text),
+ ],
+ }
+
+
+class MyFormatter(HtmlFormatter):
+ def format(self, tokensource, outfile):
+ for tok in tokensource:
+ outfile.write(tok[1])
+
+
+class ComplainOnUnhighlighted(PygmentsBridge):
+ def unhighlighted(self, source):
+ raise AssertionError("should highlight %r" % source)
+
+
+ at with_app()
+def test_add_lexer(app):
+ app.add_lexer('test', MyLexer())
+
+ bridge = PygmentsBridge('html')
+ ret = bridge.highlight_block('ab', 'test')
+ assert '<span class="n">a</span>b' in ret
+
+def test_detect_interactive():
+ bridge = ComplainOnUnhighlighted('html')
+ blocks = [
+ """
+ >>> testing()
+ True
+ """,
+ ]
+ for block in blocks:
+ ret = bridge.highlight_block(block.lstrip(), 'python')
+ assert ret.startswith("<div class=\"highlight\">")
+
+def test_set_formatter():
+ PygmentsBridge.html_formatter = MyFormatter
+ try:
+ bridge = PygmentsBridge('html')
+ ret = bridge.highlight_block('foo\n', 'python')
+ assert ret == 'foo\n'
+ finally:
+ PygmentsBridge.html_formatter = HtmlFormatter
+
+def test_trim_doctest_flags():
+ PygmentsBridge.html_formatter = MyFormatter
+ try:
+ bridge = PygmentsBridge('html', trim_doctest_flags=True)
+ ret = bridge.highlight_block('>>> 1+2 # doctest: SKIP\n3\n', 'pycon')
+ assert ret == '>>> 1+2 \n3\n'
+ finally:
+ PygmentsBridge.html_formatter = HtmlFormatter
diff --git a/tests/test_i18n.py b/tests/test_i18n.py
new file mode 100644
index 0000000..06f6b28
--- /dev/null
+++ b/tests/test_i18n.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+"""
+ test_i18n
+ ~~~~~~~~~
+
+ Test locale features.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from util import with_app
+
+
+ at with_app(confoverrides={'language': 'de'})
+def test_i18n(app):
+ app.builder.build_all()
diff --git a/tests/test_intersphinx.py b/tests/test_intersphinx.py
new file mode 100644
index 0000000..8f0263b
--- /dev/null
+++ b/tests/test_intersphinx.py
@@ -0,0 +1,180 @@
+# -*- coding: utf-8 -*-
+"""
+ test_intersphinx
+ ~~~~~~~~~~~~~~~~
+
+ Test the intersphinx extension.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import zlib
+import posixpath
+try:
+ from io import BytesIO
+except ImportError:
+ from cStringIO import StringIO as BytesIO
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.ext.intersphinx import read_inventory_v1, read_inventory_v2, \
+ load_mappings, missing_reference
+
+from util import with_app, with_tempdir, write_file
+
+
+inventory_v1 = '''\
+# Sphinx inventory version 1
+# Project: foo
+# Version: 1.0
+module mod foo.html
+module.cls class foo.html
+'''.encode('utf-8')
+
+inventory_v2 = '''\
+# Sphinx inventory version 2
+# Project: foo
+# Version: 2.0
+# The remainder of this file is compressed with zlib.
+'''.encode('utf-8') + zlib.compress('''\
+module1 py:module 0 foo.html#module-module1 Long Module desc
+module2 py:module 0 foo.html#module-$ -
+module1.func py:function 1 sub/foo.html#$ -
+CFunc c:function 2 cfunc.html#CFunc -
+a term std:term -1 glossary.html#term-a-term -
+'''.encode('utf-8'))
+
+
+def test_read_inventory_v1():
+ f = BytesIO(inventory_v1)
+ f.readline()
+ invdata = read_inventory_v1(f, '/util', posixpath.join)
+ assert invdata['py:module']['module'] == \
+ ('foo', '1.0', '/util/foo.html#module-module', '-')
+ assert invdata['py:class']['module.cls'] == \
+ ('foo', '1.0', '/util/foo.html#module.cls', '-')
+
+
+def test_read_inventory_v2():
+ f = BytesIO(inventory_v2)
+ f.readline()
+ invdata1 = read_inventory_v2(f, '/util', posixpath.join)
+
+ # try again with a small buffer size to test the chunking algorithm
+ f = BytesIO(inventory_v2)
+ f.readline()
+ invdata2 = read_inventory_v2(f, '/util', posixpath.join, bufsize=5)
+
+ assert invdata1 == invdata2
+
+ assert len(invdata1['py:module']) == 2
+ assert invdata1['py:module']['module1'] == \
+ ('foo', '2.0', '/util/foo.html#module-module1', 'Long Module desc')
+ assert invdata1['py:module']['module2'] == \
+ ('foo', '2.0', '/util/foo.html#module-module2', '-')
+ assert invdata1['py:function']['module1.func'][2] == \
+ '/util/sub/foo.html#module1.func'
+ assert invdata1['c:function']['CFunc'][2] == '/util/cfunc.html#CFunc'
+ assert invdata1['std:term']['a term'][2] == \
+ '/util/glossary.html#term-a-term'
+
+
+ at with_app(confoverrides={'extensions': 'sphinx.ext.intersphinx'})
+ at with_tempdir
+def test_missing_reference(tempdir, app):
+ inv_file = tempdir / 'inventory'
+ write_file(inv_file, inventory_v2)
+ app.config.intersphinx_mapping = {
+ 'http://docs.python.org/': inv_file,
+ 'py3k': ('http://docs.python.org/py3k/', inv_file),
+ }
+ app.config.intersphinx_cache_limit = 0
+
+ # load the inventory and check if it's done correctly
+ load_mappings(app)
+ inv = app.env.intersphinx_inventory
+
+ assert inv['py:module']['module2'] == \
+ ('foo', '2.0', 'http://docs.python.org/foo.html#module-module2', '-')
+
+ # create fake nodes and check referencing
+
+ def fake_node(domain, type, target, content, **attrs):
+ contnode = nodes.emphasis(content, content)
+ node = addnodes.pending_xref('')
+ node['reftarget'] = target
+ node['reftype'] = type
+ node['refdomain'] = domain
+ node.attributes.update(attrs)
+ node += contnode
+ return node, contnode
+
+ def reference_check(*args, **kwds):
+ node, contnode = fake_node(*args, **kwds)
+ return missing_reference(app, app.env, node, contnode)
+
+ # check resolution when a target is found
+ rn = reference_check('py', 'func', 'module1.func', 'foo')
+ assert isinstance(rn, nodes.reference)
+ assert rn['refuri'] == 'http://docs.python.org/sub/foo.html#module1.func'
+ assert rn['reftitle'] == '(in foo v2.0)'
+ assert rn[0].astext() == 'foo'
+
+ # create unresolvable nodes and check None return value
+ assert reference_check('py', 'foo', 'module1.func', 'foo') is None
+ assert reference_check('py', 'func', 'foo', 'foo') is None
+ assert reference_check('py', 'func', 'foo', 'foo') is None
+
+ # check handling of prefixes
+
+ # prefix given, target found: prefix is stripped
+ rn = reference_check('py', 'mod', 'py3k:module2', 'py3k:module2')
+ assert rn[0].astext() == 'module2'
+
+ # prefix given, but not in title: nothing stripped
+ rn = reference_check('py', 'mod', 'py3k:module2', 'module2')
+ assert rn[0].astext() == 'module2'
+
+ # prefix given, but explicit: nothing stripped
+ rn = reference_check('py', 'mod', 'py3k:module2', 'py3k:module2',
+ refexplicit=True)
+ assert rn[0].astext() == 'py3k:module2'
+
+ # prefix given, target not found and nonexplicit title: prefix is stripped
+ node, contnode = fake_node('py', 'mod', 'py3k:unknown', 'py3k:unknown',
+ refexplicit=False)
+ rn = missing_reference(app, app.env, node, contnode)
+ assert rn is None
+ assert contnode[0].astext() == 'unknown'
+
+ # prefix given, target not found and explicit title: nothing is changed
+ node, contnode = fake_node('py', 'mod', 'py3k:unknown', 'py3k:unknown',
+ refexplicit=True)
+ rn = missing_reference(app, app.env, node, contnode)
+ assert rn is None
+ assert contnode[0].astext() == 'py3k:unknown'
+
+
+ at with_app(confoverrides={'extensions': 'sphinx.ext.intersphinx'})
+ at with_tempdir
+def test_load_mappings_warnings(tempdir, app):
+ """
+ load_mappings issues a warning if new-style mapping
+ identifiers are not alphanumeric
+ """
+ inv_file = tempdir / 'inventory'
+ write_file(inv_file, inventory_v2)
+ app.config.intersphinx_mapping = {
+ 'http://docs.python.org/': inv_file,
+ 'py3k': ('http://docs.python.org/py3k/', inv_file),
+ 'repoze.workflow': ('http://docs.repoze.org/workflow/', inv_file),
+ 'django-taggit': ('http://django-taggit.readthedocs.org/en/latest/',
+ inv_file)
+ }
+
+ app.config.intersphinx_cache_limit = 0
+ # load the inventory and check if it's done correctly
+ load_mappings(app)
+ assert len(app._warning.content) == 2
diff --git a/tests/test_intl.py b/tests/test_intl.py
new file mode 100644
index 0000000..ca0273c
--- /dev/null
+++ b/tests/test_intl.py
@@ -0,0 +1,689 @@
+# -*- coding: utf-8 -*-
+"""
+ test_intl
+ ~~~~~~~~~
+
+ Test message patching for internationalization purposes. Runs the text
+ builder in the test root.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+from StringIO import StringIO
+from subprocess import Popen, PIPE
+from xml.etree import ElementTree
+
+from sphinx.util.pycompat import relpath
+
+from util import test_roots, path, with_app, SkipTest
+
+
+warnfile = StringIO()
+root = test_roots / 'test-intl'
+doctreedir = root / '_build' / 'doctree'
+
+
+def with_intl_app(*args, **kw):
+ default_kw = {
+ 'srcdir': root,
+ 'doctreedir': doctreedir,
+ 'confoverrides': {
+ 'language': 'xx', 'locale_dirs': ['.'],
+ 'gettext_compact': False,
+ },
+ }
+ default_kw.update(kw)
+ return with_app(*args, **default_kw)
+
+
+def setup_module():
+ # Delete remnants left over after failed build
+ (root / 'xx').rmtree(True)
+ (root / 'xx' / 'LC_MESSAGES').makedirs()
+ # Compile all required catalogs into binary format (*.mo).
+ for dirpath, dirs, files in os.walk(root):
+ dirpath = path(dirpath)
+ for f in [f for f in files if f.endswith('.po')]:
+ po = dirpath / f
+ mo = root / 'xx' / 'LC_MESSAGES' / (
+ relpath(po[:-3], root) + '.mo')
+ if not mo.parent.exists():
+ mo.parent.makedirs()
+ try:
+ p = Popen(['msgfmt', po, '-o', mo],
+ stdout=PIPE, stderr=PIPE)
+ except OSError:
+ raise SkipTest # most likely msgfmt was not found
+ else:
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ print stdout
+ print stderr
+ assert False, \
+ 'msgfmt exited with return code %s' % p.returncode
+ assert mo.isfile(), 'msgfmt failed'
+
+
+def teardown_module():
+ (root / '_build').rmtree(True)
+ (root / 'xx').rmtree(True)
+
+
+def elem_gettexts(elem):
+ def itertext(self):
+ # this function copied from Python-2.7 'ElementTree.itertext'.
+ # for compatibility to Python-2.5, 2.6, 3.1
+ tag = self.tag
+ if not isinstance(tag, basestring) and tag is not None:
+ return
+ if self.text:
+ yield self.text
+ for e in self:
+ for s in itertext(e):
+ yield s
+ if e.tail:
+ yield e.tail
+ return filter(None, [s.strip() for s in itertext(elem)])
+
+
+def elem_getref(elem):
+ return elem.attrib.get('refid') or elem.attrib.get('refuri')
+
+
+def assert_elem(elem, texts=None, refs=None, names=None):
+ if texts is not None:
+ _texts = elem_gettexts(elem)
+ assert _texts == texts
+ if refs is not None:
+ _refs = map(elem_getref, elem.findall('reference'))
+ assert _refs == refs
+ if names is not None:
+ _names = elem.attrib.get('names').split()
+ assert _names == names
+
+
+ at with_intl_app(buildername='text')
+def test_simple(app):
+ app.builder.build(['bom'])
+ result = (app.outdir / 'bom.txt').text(encoding='utf-8')
+ expect = (u"\nDatei mit UTF-8"
+ u"\n***************\n" # underline matches new translation
+ u"\nThis file has umlauts: äöü.\n")
+ assert result == expect
+
+
+ at with_intl_app(buildername='text')
+def test_subdir(app):
+ app.builder.build(['subdir/contents'])
+ result = (app.outdir / 'subdir' / 'contents.txt').text(encoding='utf-8')
+ assert result.startswith(u"\nsubdir contents\n***************\n")
+
+
+ at with_intl_app(buildername='text', warning=warnfile)
+def test_i18n_warnings_in_translation(app):
+ app.builddir.rmtree(True)
+ app.builder.build(['warnings'])
+ result = (app.outdir / 'warnings.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH REST WARNINGS"
+ u"\n***********************\n"
+ u"\nLINE OF >>``<<BROKEN LITERAL MARKUP.\n")
+
+ assert result == expect
+
+ warnings = warnfile.getvalue().replace(os.sep, '/')
+ warning_expr = u'.*/warnings.txt:4: ' \
+ u'WARNING: Inline literal start-string without end-string.\n'
+ assert re.search(warning_expr, warnings)
+
+
+ at with_intl_app(buildername='html', cleanenv=True)
+def test_i18n_footnote_break_refid(app):
+ """test for #955 cant-build-html-with-footnotes-when-using"""
+ app.builder.build(['footnote'])
+ result = (app.outdir / 'footnote.html').text(encoding='utf-8')
+ # expect no error by build
+
+
+ at with_intl_app(buildername='xml', warning=warnfile)
+def test_i18n_footnote_regression(app):
+ # regression test for fix #955, #1176
+ app.builddir.rmtree(True)
+ app.builder.build(['footnote'])
+ et = ElementTree.parse(app.outdir / 'footnote.xml')
+ secs = et.findall('section')
+
+ para0 = secs[0].findall('paragraph')
+ assert_elem(
+ para0[0],
+ texts=['I18N WITH FOOTNOTE', 'INCLUDE THIS CONTENTS',
+ '2', '[ref]', '1', '100', '.'],
+ refs=['i18n-with-footnote', 'ref'])
+
+ footnote0 = secs[0].findall('footnote')
+ assert_elem(
+ footnote0[0],
+ texts=['1','THIS IS A AUTO NUMBERED FOOTNOTE.'],
+ names=['1'])
+ assert_elem(
+ footnote0[1],
+ texts=['100','THIS IS A NUMBERED FOOTNOTE.'],
+ names=['100'])
+ assert_elem(
+ footnote0[2],
+ texts=['2','THIS IS A AUTO NUMBERED NAMED FOOTNOTE.'],
+ names=['named'])
+
+ citation0 = secs[0].findall('citation')
+ assert_elem(
+ citation0[0],
+ texts=['ref','THIS IS A NAMED FOOTNOTE.'],
+ names=['ref'])
+
+ warnings = warnfile.getvalue().replace(os.sep, '/')
+ warning_expr = u'.*/footnote.xml:\\d*: SEVERE: Duplicate ID: ".*".\n'
+ assert not re.search(warning_expr, warnings)
+
+
+ at with_intl_app(buildername='xml', cleanenv=True)
+def test_i18n_footnote_backlink(app):
+ # i18n test for #1058
+ app.builder.build(['footnote'])
+ et = ElementTree.parse(app.outdir / 'footnote.xml')
+ secs = et.findall('section')
+
+ para0 = secs[0].findall('paragraph')
+ refs0 = para0[0].findall('footnote_reference')
+ refid2id = dict([
+ (r.attrib.get('refid'), r.attrib.get('ids')) for r in refs0])
+
+ footnote0 = secs[0].findall('footnote')
+ for footnote in footnote0:
+ ids = footnote.attrib.get('ids')
+ backrefs = footnote.attrib.get('backrefs')
+ assert refid2id[ids] == backrefs
+
+
+ at with_intl_app(buildername='xml', warning=warnfile)
+def test_i18n_refs_python_domain(app):
+ app.builder.build(['refs_python_domain'])
+ et = ElementTree.parse(app.outdir / 'refs_python_domain.xml')
+ secs = et.findall('section')
+
+ # regression test for fix #1363
+ para0 = secs[0].findall('paragraph')
+ assert_elem(
+ para0[0],
+ texts=['SEE THIS DECORATOR:', 'sensitive_variables()', '.'],
+ refs=['sensitive.sensitive_variables'])
+
+
+ at with_intl_app(buildername='text', warning=warnfile, cleanenv=True)
+def test_i18n_warn_for_number_of_references_inconsistency(app):
+ app.builddir.rmtree(True)
+ app.builder.build(['refs_inconsistency'])
+ result = (app.outdir / 'refs_inconsistency.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH REFS INCONSISTENCY"
+ u"\n****************************\n"
+ u"\n* FOR FOOTNOTE [ref2].\n"
+ u"\n* reference FOR reference.\n"
+ u"\n* ORPHAN REFERENCE: I18N WITH REFS INCONSISTENCY.\n"
+ u"\n[1] THIS IS A AUTO NUMBERED FOOTNOTE.\n"
+ u"\n[ref2] THIS IS A NAMED FOOTNOTE.\n"
+ u"\n[100] THIS IS A NUMBERED FOOTNOTE.\n")
+ assert result == expect
+
+ warnings = warnfile.getvalue().replace(os.sep, '/')
+ warning_fmt = u'.*/refs_inconsistency.txt:\\d+: ' \
+ u'WARNING: inconsistent %s in translated message\n'
+ expected_warning_expr = (
+ warning_fmt % 'footnote references' +
+ warning_fmt % 'references' +
+ warning_fmt % 'references')
+ assert re.search(expected_warning_expr, warnings)
+
+
+ at with_intl_app(buildername='html', cleanenv=True)
+def test_i18n_link_to_undefined_reference(app):
+ app.builder.build(['refs_inconsistency'])
+ result = (app.outdir / 'refs_inconsistency.html').text(encoding='utf-8')
+
+ expected_expr = ('<a class="reference external" '
+ 'href="http://www.example.com">reference</a>')
+ assert len(re.findall(expected_expr, result)) == 2
+
+ expected_expr = ('<a class="reference internal" '
+ 'href="#reference">reference</a>')
+ assert len(re.findall(expected_expr, result)) == 0
+
+ expected_expr = ('<a class="reference internal" '
+ 'href="#i18n-with-refs-inconsistency">I18N WITH '
+ 'REFS INCONSISTENCY</a>')
+ assert len(re.findall(expected_expr, result)) == 1
+
+
+ at with_intl_app(buildername='xml', cleanenv=True)
+def test_i18n_keep_external_links(app):
+ # regression test for #1044
+ app.builder.build(['external_links'])
+ et = ElementTree.parse(app.outdir / 'external_links.xml')
+ secs = et.findall('section')
+
+ para0 = secs[0].findall('paragraph')
+ # external link check
+ assert_elem(
+ para0[0],
+ texts=['EXTERNAL LINK TO', 'Python', '.'],
+ refs=['http://python.org/index.html'])
+
+ # internal link check
+ assert_elem(
+ para0[1],
+ texts=['EXTERNAL LINKS', 'IS INTERNAL LINK.'],
+ refs=['i18n-with-external-links'])
+
+ # inline link check
+ assert_elem(
+ para0[2],
+ texts=['INLINE LINK BY', 'THE SPHINX SITE', '.'],
+ refs=['http://sphinx-doc.org'])
+
+ # unnamed link check
+ assert_elem(
+ para0[3],
+ texts=['UNNAMED', 'LINK', '.'],
+ refs=['http://google.com'])
+
+ # link target swapped translation
+ para1 = secs[1].findall('paragraph')
+ assert_elem(
+ para1[0],
+ texts=['LINK TO', 'external2', 'AND', 'external1', '.'],
+ refs=['http://example.com/external2',
+ 'http://example.com/external1'])
+ assert_elem(
+ para1[1],
+ texts=['LINK TO', 'THE PYTHON SITE', 'AND', 'THE SPHINX SITE',
+ '.'],
+ refs=['http://python.org', 'http://sphinx-doc.org'])
+
+ # multiple references in the same line
+ para2 = secs[2].findall('paragraph')
+ assert_elem(
+ para2[0],
+ texts=['LINK TO', 'EXTERNAL LINKS', ',', 'Python', ',',
+ 'THE SPHINX SITE', ',', 'UNNAMED', 'AND',
+ 'THE PYTHON SITE', '.'],
+ refs=['i18n-with-external-links', 'http://python.org/index.html',
+ 'http://sphinx-doc.org', 'http://google.com',
+ 'http://python.org'])
+
+
+ at with_intl_app(buildername='text', warning=warnfile, cleanenv=True)
+def test_i18n_literalblock_warning(app):
+ app.builddir.rmtree(True) #for warnings acceleration
+ app.builder.build(['literalblock'])
+ result = (app.outdir / 'literalblock.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH LITERAL BLOCK"
+ u"\n***********************\n"
+ u"\nCORRECT LITERAL BLOCK:\n"
+ u"\n this is"
+ u"\n literal block\n"
+ u"\nMISSING LITERAL BLOCK:\n"
+ u"\n<SYSTEM MESSAGE:")
+ assert result.startswith(expect)
+
+ warnings = warnfile.getvalue().replace(os.sep, '/')
+ expected_warning_expr = u'.*/literalblock.txt:\\d+: ' \
+ u'WARNING: Literal block expected; none found.'
+ assert re.search(expected_warning_expr, warnings)
+
+
+ at with_intl_app(buildername='text')
+def test_i18n_definition_terms(app):
+ # regression test for #975
+ app.builder.build(['definition_terms'])
+ result = (app.outdir / 'definition_terms.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH DEFINITION TERMS"
+ u"\n**************************\n"
+ u"\nSOME TERM"
+ u"\n THE CORRESPONDING DEFINITION\n"
+ u"\nSOME OTHER TERM"
+ u"\n THE CORRESPONDING DEFINITION #2\n")
+
+ assert result == expect
+
+
+ at with_intl_app(buildername='text', warning=warnfile)
+def test_i18n_glossary_terms(app):
+ # regression test for #1090
+ app.builddir.rmtree(True) #for warnings acceleration
+ app.builder.build(['glossary_terms'])
+ result = (app.outdir / 'glossary_terms.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH GLOSSARY TERMS"
+ u"\n************************\n"
+ u"\nSOME NEW TERM"
+ u"\n THE CORRESPONDING GLOSSARY\n"
+ u"\nSOME OTHER NEW TERM"
+ u"\n THE CORRESPONDING GLOSSARY #2\n"
+ u"\nLINK TO *SOME NEW TERM*.\n")
+ assert result == expect
+
+ warnings = warnfile.getvalue().replace(os.sep, '/')
+ assert 'term not in glossary' not in warnings
+
+
+ at with_intl_app(buildername='xml', warning=warnfile)
+def test_i18n_role_xref(app):
+ # regression test for #1090, #1193
+ app.builddir.rmtree(True) #for warnings acceleration
+ app.builder.build(['role_xref'])
+ et = ElementTree.parse(app.outdir / 'role_xref.xml')
+ sec1, sec2 = et.findall('section')
+
+ para1, = sec1.findall('paragraph')
+ assert_elem(
+ para1,
+ texts=['LINK TO', "I18N ROCK'N ROLE XREF", ',', 'CONTENTS', ',',
+ 'SOME NEW TERM', '.'],
+ refs=['i18n-role-xref', 'contents',
+ 'glossary_terms#term-some-term'])
+
+ para2 = sec2.findall('paragraph')
+ assert_elem(
+ para2[0],
+ texts=['LINK TO', 'SOME OTHER NEW TERM', 'AND', 'SOME NEW TERM',
+ '.'],
+ refs=['glossary_terms#term-some-other-term',
+ 'glossary_terms#term-some-term'])
+ assert_elem(
+ para2[1],
+ texts=['LINK TO', 'SAME TYPE LINKS', 'AND',
+ "I18N ROCK'N ROLE XREF", '.'],
+ refs=['same-type-links', 'i18n-role-xref'])
+ assert_elem(
+ para2[2],
+ texts=['LINK TO', 'I18N WITH GLOSSARY TERMS', 'AND', 'CONTENTS',
+ '.'],
+ refs=['glossary_terms', 'contents'])
+ assert_elem(
+ para2[3],
+ texts=['LINK TO', '--module', 'AND', '-m', '.'],
+ refs=['cmdoption--module', 'cmdoption-m'])
+ assert_elem(
+ para2[4],
+ texts=['LINK TO', 'env2', 'AND', 'env1', '.'],
+ refs=['envvar-env2', 'envvar-env1'])
+ assert_elem(
+ para2[5],
+ texts=['LINK TO', 'token2', 'AND', 'token1', '.'],
+ refs=[]) #TODO: how do I link token role to productionlist?
+ assert_elem(
+ para2[6],
+ texts=['LINK TO', 'same-type-links', 'AND', "i18n-role-xref", '.'],
+ refs=['same-type-links', 'i18n-role-xref'])
+
+ #warnings
+ warnings = warnfile.getvalue().replace(os.sep, '/')
+ assert 'term not in glossary' not in warnings
+ assert 'undefined label' not in warnings
+ assert 'unknown document' not in warnings
+
+
+ at with_intl_app(buildername='xml', warning=warnfile)
+def test_i18n_label_target(app):
+ # regression test for #1193, #1265
+ app.builder.build(['label_target'])
+ et = ElementTree.parse(app.outdir / 'label_target.xml')
+ secs = et.findall('section')
+
+ para0 = secs[0].findall('paragraph')
+ assert_elem(
+ para0[0],
+ texts=['X SECTION AND LABEL', 'POINT TO', 'implicit-target', 'AND',
+ 'X SECTION AND LABEL', 'POINT TO', 'section-and-label', '.'],
+ refs=['implicit-target', 'section-and-label'])
+
+ para1 = secs[1].findall('paragraph')
+ assert_elem(
+ para1[0],
+ texts=['X EXPLICIT-TARGET', 'POINT TO', 'explicit-target', 'AND',
+ 'X EXPLICIT-TARGET', 'POINT TO DUPLICATED ID LIKE', 'id1',
+ '.'],
+ refs=['explicit-target', 'id1'])
+
+ para2 = secs[2].findall('paragraph')
+ assert_elem(
+ para2[0],
+ texts=['X IMPLICIT SECTION NAME', 'POINT TO',
+ 'implicit-section-name', '.'],
+ refs=['implicit-section-name'])
+
+ sec2 = secs[2].findall('section')
+
+ para2_0 = sec2[0].findall('paragraph')
+ assert_elem(
+ para2_0[0],
+ texts=['`X DUPLICATED SUB SECTION`_', 'IS BROKEN LINK.'],
+ refs=[])
+
+ para3 = secs[3].findall('paragraph')
+ assert_elem(
+ para3[0],
+ texts=['X', 'bridge label',
+ 'IS NOT TRANSLATABLE BUT LINKED TO TRANSLATED ' +
+ 'SECTION TITLE.'],
+ refs=['label-bridged-target-section'])
+ assert_elem(
+ para3[1],
+ texts=['X', 'bridge label', 'POINT TO',
+ 'LABEL BRIDGED TARGET SECTION', 'AND', 'bridge label2',
+ 'POINT TO', 'SECTION AND LABEL', '. THE SECOND APPEARED',
+ 'bridge label2', 'POINT TO CORRECT TARGET.'],
+ refs=['label-bridged-target-section',
+ 'section-and-label',
+ 'section-and-label'])
+
+
+ at with_intl_app(buildername='text', warning=warnfile)
+def test_i18n_glossary_terms_inconsistency(app):
+ # regression test for #1090
+ app.builddir.rmtree(True) #for warnings acceleration
+ app.builder.build(['glossary_terms_inconsistency'])
+ result = (app.outdir / 'glossary_terms_inconsistency.txt'
+ ).text(encoding='utf-8')
+ expect = (u"\nI18N WITH GLOSSARY TERMS INCONSISTENCY"
+ u"\n**************************************\n"
+ u"\n1. LINK TO *SOME NEW TERM*.\n")
+ assert result == expect
+
+ warnings = warnfile.getvalue().replace(os.sep, '/')
+ expected_warning_expr = (
+ u'.*/glossary_terms_inconsistency.txt:\\d+: '
+ u'WARNING: inconsistent term references in translated message\n')
+ assert re.search(expected_warning_expr, warnings)
+
+
+ at with_intl_app(buildername='text')
+def test_seealso(app):
+ app.builder.build(['seealso'])
+ result = (app.outdir / 'seealso.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH SEEALSO"
+ u"\n*****************\n"
+ u"\nSee also: SHORT TEXT 1\n"
+ u"\nSee also: LONG TEXT 1\n"
+ u"\nSee also: SHORT TEXT 2\n"
+ u"\n LONG TEXT 2\n")
+ assert result == expect
+
+
+ at with_intl_app(buildername='text')
+def test_i18n_figure_caption(app):
+ # regression test for #940
+ app.builder.build(['figure_caption'])
+ result = (app.outdir / 'figure_caption.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH FIGURE CAPTION"
+ u"\n************************\n"
+ u"\n [image]MY CAPTION OF THE FIGURE\n"
+ u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
+ u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n"
+ u"\n"
+ u"\nFIGURE IN THE BLOCK"
+ u"\n===================\n"
+ u"\nBLOCK\n"
+ u"\n [image]MY CAPTION OF THE FIGURE\n"
+ u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
+ u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n")
+
+ assert result == expect
+
+
+ at with_intl_app(buildername='text')
+def test_i18n_rubric(app):
+ # regression test for pull request #190
+ app.builder.build(['rubric'])
+ result = (app.outdir / 'rubric.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH RUBRIC"
+ u"\n****************\n"
+ u"\n-[ RUBRIC TITLE ]-\n"
+ u"\n"
+ u"\nRUBRIC IN THE BLOCK"
+ u"\n===================\n"
+ u"\nBLOCK\n"
+ u"\n -[ RUBRIC TITLE ]-\n")
+
+ assert result == expect
+
+
+ at with_intl_app(buildername='html')
+def test_i18n_index_entries(app):
+ # regression test for #976
+ app.builder.build(['index_entries'])
+ result = (app.outdir / 'genindex.html').text(encoding='utf-8')
+
+ def wrap(tag, keyword):
+ start_tag = "<%s[^>]*>" % tag
+ end_tag = "</%s>" % tag
+ return r"%s\s*%s\s*%s" % (start_tag, keyword, end_tag)
+
+ expected_exprs = [
+ wrap('a', 'NEWSLETTER'),
+ wrap('a', 'MAILING LIST'),
+ wrap('a', 'RECIPIENTS LIST'),
+ wrap('a', 'FIRST SECOND'),
+ wrap('a', 'SECOND THIRD'),
+ wrap('a', 'THIRD, FIRST'),
+ wrap('dt', 'ENTRY'),
+ wrap('dt', 'SEE'),
+ wrap('a', 'MODULE'),
+ wrap('a', 'KEYWORD'),
+ wrap('a', 'OPERATOR'),
+ wrap('a', 'OBJECT'),
+ wrap('a', 'EXCEPTION'),
+ wrap('a', 'STATEMENT'),
+ wrap('a', 'BUILTIN'),
+ ]
+ for expr in expected_exprs:
+ assert re.search(expr, result, re.M)
+
+
+ at with_intl_app(buildername='html', cleanenv=True)
+def test_versionchange(app):
+ app.builder.build(['versionchange'])
+ result = (app.outdir / 'versionchange.html').text(encoding='utf-8')
+
+ def get_content(result, name):
+ matched = re.search(r'<div class="%s">\n*(.*?)</div>' % name,
+ result, re.DOTALL)
+ if matched:
+ return matched.group(1)
+ else:
+ return ''
+
+ expect1 = (
+ u"""<p><span class="versionmodified">Deprecated since version 1.0: </span>"""
+ u"""THIS IS THE <em>FIRST</em> PARAGRAPH OF DEPRECATED.</p>\n"""
+ u"""<p>THIS IS THE <em>SECOND</em> PARAGRAPH OF DEPRECATED.</p>\n""")
+ matched_content = get_content(result, "deprecated")
+ assert expect1 == matched_content
+
+ expect2 = (
+ u"""<p><span class="versionmodified">New in version 1.0: </span>"""
+ u"""THIS IS THE <em>FIRST</em> PARAGRAPH OF VERSIONADDED.</p>\n""")
+ matched_content = get_content(result, "versionadded")
+ assert expect2 == matched_content
+
+ expect3 = (
+ u"""<p><span class="versionmodified">Changed in version 1.0: </span>"""
+ u"""THIS IS THE <em>FIRST</em> PARAGRAPH OF VERSIONCHANGED.</p>\n""")
+ matched_content = get_content(result, "versionchanged")
+ assert expect3 == matched_content
+
+
+ at with_intl_app(buildername='text', cleanenv=True)
+def test_i18n_docfields(app):
+ app.builder.build(['docfields'])
+ result = (app.outdir / 'docfields.txt').text(encoding='utf-8')
+ expect = (u"\nI18N WITH DOCFIELDS"
+ u"\n*******************\n"
+ u"\nclass class Cls1\n"
+ u"\n Parameters:"
+ u"\n **param** -- DESCRIPTION OF PARAMETER param\n"
+ u"\nclass class Cls2\n"
+ u"\n Parameters:"
+ u"\n * **foo** -- DESCRIPTION OF PARAMETER foo\n"
+ u"\n * **bar** -- DESCRIPTION OF PARAMETER bar\n"
+ u"\nclass class Cls3(values)\n"
+ u"\n Raises ValueError:"
+ u"\n IF THE VALUES ARE OUT OF RANGE\n"
+ u"\nclass class Cls4(values)\n"
+ u"\n Raises:"
+ u"\n * **TypeError** -- IF THE VALUES ARE NOT VALID\n"
+ u"\n * **ValueError** -- IF THE VALUES ARE OUT OF RANGE\n"
+ u"\nclass class Cls5\n"
+ u"\n Returns:"
+ u'\n A NEW "Cls3" INSTANCE\n')
+ assert result == expect
+
+
+ at with_intl_app(buildername='text', cleanenv=True)
+def test_i18n_admonitions(app):
+ # #1206: gettext did not translate admonition directive's title
+ # seealso: http://docutils.sourceforge.net/docs/ref/rst/directives.html#admonitions
+ app.builder.build(['admonitions'])
+ result = (app.outdir / 'admonitions.txt').text(encoding='utf-8')
+ directives = (
+ "attention", "caution", "danger", "error", "hint",
+ "important", "note", "tip", "warning", "admonition",)
+ for d in directives:
+ assert d.upper() + " TITLE" in result
+ assert d.upper() + " BODY" in result
+
+
+ at with_intl_app(buildername='html', cleanenv=True)
+def test_i18n_docfields_html(app):
+ app.builder.build(['docfields'])
+ result = (app.outdir / 'docfields.html').text(encoding='utf-8')
+ # expect no error by build
+
+
+ at with_intl_app(buildername='html')
+def test_gettext_template(app):
+ app.builder.build_all()
+ result = (app.outdir / 'index.html').text(encoding='utf-8')
+ assert "WELCOME" in result
+ assert "SPHINX 2013.120" in result
+
+
+ at with_intl_app(buildername='html')
+def test_rebuild_by_mo_mtime(app):
+ app.builder.build_update()
+ _, count, _ = app.env.update(app.config, app.srcdir, app.doctreedir, app)
+ assert count == 0
+
+ mo = (app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').bytes()
+ (app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').write_bytes(mo)
+ _, count, _ = app.env.update(app.config, app.srcdir, app.doctreedir, app)
+ assert count == 1
diff --git a/tests/test_linkcode.py b/tests/test_linkcode.py
new file mode 100644
index 0000000..83b7209
--- /dev/null
+++ b/tests/test_linkcode.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+"""
+ test_linkcode
+ ~~~~~~~~~~~~~
+
+ Test the sphinx.ext.linkcode extension.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+from util import with_app
+
+
+ at with_app(srcdir='(temp)', buildername='html', tags=['test_linkcode'])
+def test_html(app):
+ app.builder.build_all()
+
+ stuff = (app.outdir / 'objects.html').text(encoding='utf-8')
+
+ assert 'http://foobar/source/foolib.py' in stuff
+ assert 'http://foobar/js/' in stuff
+ assert 'http://foobar/c/' in stuff
+ assert 'http://foobar/cpp/' in stuff
diff --git a/tests/test_markup.py b/tests/test_markup.py
new file mode 100644
index 0000000..4f0b0de
--- /dev/null
+++ b/tests/test_markup.py
@@ -0,0 +1,139 @@
+# -*- coding: utf-8 -*-
+"""
+ test_markup
+ ~~~~~~~~~~~
+
+ Test various Sphinx-specific markup extensions.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from docutils import frontend, utils, nodes
+from docutils.parsers import rst
+
+from sphinx.util import texescape
+from sphinx.util.pycompat import b
+from sphinx.writers.html import HTMLWriter, SmartyPantsHTMLTranslator
+from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
+
+from util import TestApp
+
+
+app = settings = parser = None
+
+def setup_module():
+ global app, settings, parser
+ texescape.init() # otherwise done by the latex builder
+ app = TestApp(cleanenv=True)
+ optparser = frontend.OptionParser(
+ components=(rst.Parser, HTMLWriter, LaTeXWriter))
+ settings = optparser.get_default_values()
+ settings.env = app.builder.env
+ settings.env.patch_lookup_functions()
+ settings.env.temp_data['docname'] = 'dummy'
+ parser = rst.Parser()
+
+def teardown_module():
+ app.cleanup()
+
+# since we're not resolving the markup afterwards, these nodes may remain
+class ForgivingTranslator:
+ def visit_pending_xref(self, node):
+ pass
+ def depart_pending_xref(self, node):
+ pass
+
+class ForgivingHTMLTranslator(SmartyPantsHTMLTranslator, ForgivingTranslator):
+ pass
+
+class ForgivingLaTeXTranslator(LaTeXTranslator, ForgivingTranslator):
+ pass
+
+
+def verify_re(rst, html_expected, latex_expected):
+ document = utils.new_document(b('test data'), settings)
+ document['file'] = 'dummy'
+ parser.parse(rst, document)
+ for msg in document.traverse(nodes.system_message):
+ if msg['level'] == 1:
+ msg.replace_self([])
+
+ if html_expected:
+ html_translator = ForgivingHTMLTranslator(app.builder, document)
+ document.walkabout(html_translator)
+ html_translated = ''.join(html_translator.fragment).strip()
+ assert re.match(html_expected, html_translated), 'from ' + rst
+
+ if latex_expected:
+ latex_translator = ForgivingLaTeXTranslator(document, app.builder)
+ latex_translator.first_document = -1 # don't write \begin{document}
+ document.walkabout(latex_translator)
+ latex_translated = ''.join(latex_translator.body).strip()
+ assert re.match(latex_expected, latex_translated), 'from ' + repr(rst)
+
+def verify(rst, html_expected, latex_expected):
+ if html_expected:
+ html_expected = re.escape(html_expected) + '$'
+ if latex_expected:
+ latex_expected = re.escape(latex_expected) + '$'
+ verify_re(rst, html_expected, latex_expected)
+
+
+def test_inline():
+ # correct interpretation of code with whitespace
+ _html = ('<p><tt class="(samp )?docutils literal"><span class="pre">'
+ 'code</span> <span class="pre">sample</span></tt></p>')
+ yield verify_re, '``code sample``', _html, r'\\code{code sample}'
+ yield verify_re, ':samp:`code sample`', _html, r'\\code{code sample}'
+
+ # interpolation of braces in samp and file roles (HTML only)
+ yield (verify, ':samp:`a{b}c`',
+ '<p><tt class="samp docutils literal"><span class="pre">a</span>'
+ '<em><span class="pre">b</span></em>'
+ '<span class="pre">c</span></tt></p>',
+ '\\code{a\\emph{b}c}')
+
+ # interpolation of arrows in menuselection
+ yield (verify, ':menuselection:`a --> b`',
+ u'<p><em class="menuselection">a \N{TRIANGULAR BULLET} b</em></p>',
+ '\\emph{a \\(\\rightarrow\\) b}')
+
+ # interpolation of ampersands in guilabel/menuselection
+ yield (verify, ':guilabel:`&Foo -&&- &Bar`',
+ u'<p><em class="guilabel"><span class="accelerator">F</span>oo '
+ '-&- <span class="accelerator">B</span>ar</em></p>',
+ r'\emph{\DUspan{accelerator}{F}oo -\&- \DUspan{accelerator}{B}ar}')
+
+ # non-interpolation of dashes in option role
+ yield (verify_re, ':option:`--with-option`',
+ '<p><em( class="xref std std-option")?>--with-option</em></p>$',
+ r'\\emph{\\texttt{-{-}with-option}}$')
+
+ # verify smarty-pants quotes
+ yield verify, '"John"', '<p>“John”</p>', "``John''"
+ # ... but not in literal text
+ yield (verify, '``"John"``',
+ '<p><tt class="docutils literal"><span class="pre">'
+ '"John"</span></tt></p>',
+ '\\code{"John"}')
+
+ # verify classes for inline roles
+ yield (verify, ':manpage:`mp(1)`',
+ '<p><em class="manpage">mp(1)</em></p>',
+ '\\emph{\\texttt{mp(1)}}')
+
+def test_latex_escaping():
+ # correct escaping in normal mode
+ yield (verify, u'Γ\\\\∞$', None,
+ ur'\(\Gamma\)\textbackslash{}\(\infty\)\$')
+ # in verbatim code fragments
+ yield (verify, u'::\n\n @Γ\\∞${}', None,
+ u'\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n'
+ u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
+ u'\\end{Verbatim}')
+ # in URIs
+ yield (verify_re, u'`test <http://example.com/~me/>`_', None,
+ ur'\\href{http://example.com/~me/}{test}.*')
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
new file mode 100644
index 0000000..a0d4445
--- /dev/null
+++ b/tests/test_metadata.py
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+"""
+ test_metadata
+ ~~~~~~~~~~~~~
+
+ Test our handling of metadata in files with bibliographic metadata.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+# adapted from an example of bibliographic metadata at
+# http://docutils.sourceforge.net/docs/user/rst/demo.txt
+
+from util import TestApp
+
+from nose.tools import assert_equal
+
+
+app = env = None
+warnings = []
+
+def setup_module():
+ # Is there a better way of generating this doctree than manually iterating?
+ global app, env
+ app = TestApp(srcdir='(temp)')
+ env = app.env
+ msg, num, it = env.update(app.config, app.srcdir, app.doctreedir, app)
+ for docname in it:
+ pass
+
+def teardown_module():
+ app.cleanup()
+
+def test_docinfo():
+ """
+ Inspect the 'docinfo' metadata stored in the first node of the document.
+ Note this doesn't give us access to data stored in subsequence blocks
+ that might be considered document metadata, such as 'abstract' or
+ 'dedication' blocks, or the 'meta' role. Doing otherwise is probably more
+ messing with the internals of sphinx than this rare use case merits.
+ """
+ exampledocinfo = env.metadata['metadata']
+ expecteddocinfo = {
+ 'author': u'David Goodger',
+ 'authors': [u'Me', u'Myself', u'I'],
+ 'address': u'123 Example Street\nExample, EX Canada\nA1B 2C3',
+ 'field name': u'This is a generic bibliographic field.',
+ 'field name 2': (u'Generic bibliographic fields may contain multiple '
+ u'body elements.\n\nLike this.'),
+ 'status': u'This is a "work in progress"',
+ 'version': u'1',
+ 'copyright': (u'This document has been placed in the public domain. '
+ u'You\nmay do with it as you wish. You may copy, modify,'
+ u'\nredistribute, reattribute, sell, buy, rent, lease,\n'
+ u'destroy, or improve it, quote it at length, excerpt,\n'
+ u'incorporate, collate, fold, staple, or mutilate it, or '
+ u'do\nanything else to it that your or anyone else\'s '
+ u'heart\ndesires.'),
+ 'contact': u'goodger at python.org',
+ 'date': u'2006-05-21',
+ 'organization': u'humankind',
+ 'revision': u'4564',
+ }
+ # I like this way of comparing dicts - easier to see the error.
+ for key in exampledocinfo:
+ yield assert_equal, exampledocinfo.get(key), expecteddocinfo.get(key)
+ # but then we still have to check for missing keys
+ yield assert_equal, set(expecteddocinfo.keys()), set(exampledocinfo.keys())
diff --git a/tests/test_only_directive.py b/tests/test_only_directive.py
new file mode 100644
index 0000000..4717ff9
--- /dev/null
+++ b/tests/test_only_directive.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+"""
+ test_only_directive
+ ~~~~~~~~~~~~~~~~~~~
+
+ Test the only directive with the test root.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from docutils import nodes
+
+from util import with_app, test_roots
+
+
+def teardown_module():
+ (test_roots / 'test-only-directive' / '_build').rmtree(True)
+
+
+ at with_app(buildername='text', srcdir=(test_roots / 'test-only-directive'))
+def test_sectioning(app):
+
+ def getsects(section):
+ if not isinstance(section, nodes.section):
+ return [getsects(n) for n in section.children]
+ title = section.next_node(nodes.title).astext().strip()
+ subsects = []
+ children = section.children[:]
+ while children:
+ node = children.pop(0)
+ if isinstance(node, nodes.section):
+ subsects.append(node)
+ continue
+ children = list(node.children) + children
+ return [title, [getsects(subsect) for subsect in subsects]]
+
+ def testsects(prefix, sects, indent=0):
+ title = sects[0]
+ parent_num = title.split()[0]
+ assert prefix == parent_num, \
+ 'Section out of place: %r' % title
+ for i, subsect in enumerate(sects[1]):
+ num = subsect[0].split()[0]
+ assert re.match('[0-9]+[.0-9]*[.]', num), \
+ 'Unnumbered section: %r' % subsect[0]
+ testsects(prefix + str(i+1) + '.', subsect, indent+4)
+
+ app.builder.build(['only'])
+ doctree = app.env.get_doctree('only')
+ app.env.process_only_nodes(doctree, app.builder)
+
+ parts = [getsects(n)
+ for n in filter(lambda n: isinstance(n, nodes.section),
+ doctree.children)]
+ for i, s in enumerate(parts):
+ testsects(str(i+1) + '.', s, 4)
+ assert len(parts) == 4, 'Expected 4 document level headings, got:\n%s' % \
+ '\n'.join([p[0] for p in parts])
diff --git a/tests/test_py_domain.py b/tests/test_py_domain.py
new file mode 100644
index 0000000..68634d8
--- /dev/null
+++ b/tests/test_py_domain.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+"""
+ test_py_domain
+ ~~~~~~~~~~~~~~
+
+ Tests the Python Domain
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx import addnodes
+from sphinx.domains.python import py_sig_re, _pseudo_parse_arglist
+
+
+def parse(sig):
+ m = py_sig_re.match(sig)
+ if m is None:
+ raise ValueError
+ name_prefix, name, arglist, retann = m.groups()
+ signode = addnodes.desc_signature(sig, '')
+ _pseudo_parse_arglist(signode, arglist)
+ return signode.astext()
+
+
+def test_function_signatures():
+
+ rv = parse('func(a=1) -> int object')
+ assert unicode(rv) == u'a=1'
+
+ rv = parse('func(a=1, [b=None])')
+ assert unicode(rv) == u'a=1, [b=None]'
+
+ rv = parse('func(a=1[, b=None])')
+ assert unicode(rv) == u'a=1, [b=None]'
+
+ rv = parse("compile(source : string, filename, symbol='file')")
+ assert unicode(rv) == u"source : string, filename, symbol='file'"
+
+ rv = parse('func(a=[], [b=None])')
+ assert unicode(rv) == u'a=[], [b=None]'
+
+ rv = parse('func(a=[][, b=None])')
+ assert unicode(rv) == u'a=[], [b=None]'
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
new file mode 100644
index 0000000..8f63070
--- /dev/null
+++ b/tests/test_quickstart.py
@@ -0,0 +1,292 @@
+# -*- coding: utf-8 -*-
+"""
+ test_quickstart
+ ~~~~~~~~~~~~~~~
+
+ Test the sphinx.quickstart module.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import time
+from StringIO import StringIO
+import tempfile
+
+from util import raises, with_tempdir, with_app, SkipTest
+
+from sphinx import application
+from sphinx import quickstart as qs
+from sphinx.util.console import nocolor, coloron
+from sphinx.util.pycompat import execfile_
+
+
+warnfile = StringIO()
+
+
+def setup_module():
+ nocolor()
+
+def mock_raw_input(answers, needanswer=False):
+ called = set()
+ def raw_input(prompt):
+ if prompt in called:
+ raise AssertionError('answer for %r missing and no default '
+ 'present' % prompt)
+ called.add(prompt)
+ if sys.version_info < (3, 0):
+ prompt = str(prompt) # Python2.x raw_input emulation
+ # `raw_input` encode `prompt` by default encoding to print.
+ else:
+ prompt = unicode(prompt) # Python3.x input emulation
+ # `input` decode prompt by default encoding before print.
+ for question in answers:
+ if prompt.startswith(qs.PROMPT_PREFIX + question):
+ return answers[question]
+ if needanswer:
+ raise AssertionError('answer for %r missing' % prompt)
+ return ''
+ return raw_input
+
+try:
+ real_raw_input = raw_input
+except NameError:
+ real_raw_input = input
+
+def teardown_module():
+ qs.term_input = real_raw_input
+ qs.TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
+ coloron()
+
+
+def test_quickstart_inputstrip():
+ d = {}
+ answers = {
+ 'Q1': 'Y\r', # input() return with '\r' on Python-3.2.0 for Windows
+ 'Q2': ' Yes \r',
+ 'Q3': 'N',
+ 'Q4': 'N ',
+ }
+ qs.term_input = mock_raw_input(answers)
+ qs.do_prompt(d, 'k1', 'Q1')
+ assert d['k1'] == 'Y'
+ qs.do_prompt(d, 'k2', 'Q2')
+ assert d['k2'] == 'Yes'
+ qs.do_prompt(d, 'k3', 'Q3')
+ assert d['k3'] == 'N'
+ qs.do_prompt(d, 'k4', 'Q4')
+ assert d['k4'] == 'N'
+
+
+def test_do_prompt():
+ d = {}
+ answers = {
+ 'Q2': 'v2',
+ 'Q3': 'v3',
+ 'Q4': 'yes',
+ 'Q5': 'no',
+ 'Q6': 'foo',
+ }
+ qs.term_input = mock_raw_input(answers)
+ try:
+ qs.do_prompt(d, 'k1', 'Q1')
+ except AssertionError:
+ assert 'k1' not in d
+ else:
+ assert False, 'AssertionError not raised'
+ qs.do_prompt(d, 'k1', 'Q1', default='v1')
+ assert d['k1'] == 'v1'
+ qs.do_prompt(d, 'k3', 'Q3', default='v3_default')
+ assert d['k3'] == 'v3'
+ qs.do_prompt(d, 'k2', 'Q2')
+ assert d['k2'] == 'v2'
+ qs.do_prompt(d, 'k4', 'Q4', validator=qs.boolean)
+ assert d['k4'] is True
+ qs.do_prompt(d, 'k5', 'Q5', validator=qs.boolean)
+ assert d['k5'] is False
+ raises(AssertionError, qs.do_prompt, d, 'k6', 'Q6', validator=qs.boolean)
+
+
+def test_do_prompt_with_nonascii():
+ d = {}
+ answers = {
+ 'Q1': u'\u30c9\u30a4\u30c4',
+ }
+ qs.term_input = mock_raw_input(answers)
+ try:
+ qs.do_prompt(d, 'k1', 'Q1', default=u'\u65e5\u672c')
+ except UnicodeEncodeError:
+ raise SkipTest(
+ 'non-ASCII console input not supported on this encoding: %s',
+ qs.TERM_ENCODING)
+ assert d['k1'] == u'\u30c9\u30a4\u30c4'
+
+
+ at with_tempdir
+def test_quickstart_defaults(tempdir):
+ answers = {
+ 'Root path': tempdir,
+ 'Project name': 'Sphinx Test',
+ 'Author name': 'Georg Brandl',
+ 'Project version': '0.1',
+ }
+ qs.term_input = mock_raw_input(answers)
+ d = {}
+ qs.ask_user(d)
+ qs.generate(d)
+
+ conffile = tempdir / 'conf.py'
+ assert conffile.isfile()
+ ns = {}
+ execfile_(conffile, ns)
+ assert ns['extensions'] == []
+ assert ns['templates_path'] == ['_templates']
+ assert ns['source_suffix'] == '.rst'
+ assert ns['master_doc'] == 'index'
+ assert ns['project'] == 'Sphinx Test'
+ assert ns['copyright'] == '%s, Georg Brandl' % time.strftime('%Y')
+ assert ns['version'] == '0.1'
+ assert ns['release'] == '0.1'
+ assert ns['html_static_path'] == ['_static']
+ assert ns['latex_documents'] == [
+ ('index', 'SphinxTest.tex', 'Sphinx Test Documentation',
+ 'Georg Brandl', 'manual')]
+
+ assert (tempdir / '_static').isdir()
+ assert (tempdir / '_templates').isdir()
+ assert (tempdir / 'index.rst').isfile()
+ assert (tempdir / 'Makefile').isfile()
+ assert (tempdir / 'make.bat').isfile()
+
+
+ at with_tempdir
+def test_quickstart_all_answers(tempdir):
+ answers = {
+ 'Root path': tempdir,
+ 'Separate source and build': 'y',
+ 'Name prefix for templates': '.',
+ 'Project name': u'STASI™'.encode('utf-8'),
+ 'Author name': u'Wolfgang Schäuble & G\'Beckstein'.encode('utf-8'),
+ 'Project version': '2.0',
+ 'Project release': '2.0.1',
+ 'Source file suffix': '.txt',
+ 'Name of your master document': 'contents',
+ 'autodoc': 'y',
+ 'doctest': 'yes',
+ 'intersphinx': 'no',
+ 'todo': 'n',
+ 'coverage': 'no',
+ 'pngmath': 'N',
+ 'mathjax': 'no',
+ 'ifconfig': 'no',
+ 'viewcode': 'no',
+ 'Create Makefile': 'no',
+ 'Create Windows command file': 'no',
+ 'Do you want to use the epub builder': 'yes',
+ }
+ qs.term_input = mock_raw_input(answers, needanswer=True)
+ qs.TERM_ENCODING = 'utf-8'
+ d = {}
+ qs.ask_user(d)
+ qs.generate(d)
+
+ conffile = tempdir / 'source' / 'conf.py'
+ assert conffile.isfile()
+ ns = {}
+ execfile_(conffile, ns)
+ assert ns['extensions'] == ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
+ assert ns['templates_path'] == ['.templates']
+ assert ns['source_suffix'] == '.txt'
+ assert ns['master_doc'] == 'contents'
+ assert ns['project'] == u'STASI™'
+ assert ns['copyright'] == u'%s, Wolfgang Schäuble & G\'Beckstein' % \
+ time.strftime('%Y')
+ assert ns['version'] == '2.0'
+ assert ns['release'] == '2.0.1'
+ assert ns['html_static_path'] == ['.static']
+ assert ns['latex_documents'] == [
+ ('contents', 'STASI.tex', u'STASI™ Documentation',
+ u'Wolfgang Schäuble \\& G\'Beckstein', 'manual')]
+ assert ns['epub_author'] == u'Wolfgang Schäuble & G\'Beckstein'
+ assert ns['man_pages'] == [
+ ('contents', 'stasi', u'STASI™ Documentation',
+ [u'Wolfgang Schäuble & G\'Beckstein'], 1)]
+ assert ns['texinfo_documents'] == [
+ ('contents', 'STASI', u'STASI™ Documentation',
+ u'Wolfgang Schäuble & G\'Beckstein', 'STASI',
+ 'One line description of project.', 'Miscellaneous'),]
+
+ assert (tempdir / 'build').isdir()
+ assert (tempdir / 'source' / '.static').isdir()
+ assert (tempdir / 'source' / '.templates').isdir()
+ assert (tempdir / 'source' / 'contents.txt').isfile()
+
+
+ at with_tempdir
+def test_generated_files_eol(tempdir):
+ answers = {
+ 'Root path': tempdir,
+ 'Project name': 'Sphinx Test',
+ 'Author name': 'Georg Brandl',
+ 'Project version': '0.1',
+ }
+ qs.term_input = mock_raw_input(answers)
+ d = {}
+ qs.ask_user(d)
+ qs.generate(d)
+
+ def assert_eol(filename, eol):
+ content = filename.bytes().decode('unicode-escape')
+ assert all([l[-len(eol):]==eol for l in content.splitlines(True)])
+
+ assert_eol(tempdir / 'make.bat', '\r\n')
+ assert_eol(tempdir / 'Makefile', '\n')
+
+
+ at with_tempdir
+def test_quickstart_and_build(tempdir):
+ answers = {
+ 'Root path': tempdir,
+ 'Project name': u'Fullwidth characters: \u30c9\u30a4\u30c4',
+ 'Author name': 'Georg Brandl',
+ 'Project version': '0.1',
+ }
+ qs.term_input = mock_raw_input(answers)
+ d = {}
+ qs.ask_user(d)
+ qs.generate(d)
+
+ app = application.Sphinx(
+ tempdir, #srcdir
+ tempdir, #confdir
+ (tempdir / '_build' / 'html'), #outdir
+ (tempdir / '_build' / '.doctree'), #doctreedir
+ 'html', #buildername
+ status=StringIO(),
+ warning=warnfile)
+ app.builder.build_all()
+ warnings = warnfile.getvalue()
+ assert not warnings
+
+
+ at with_tempdir
+def test_default_filename(tempdir):
+ answers = {
+ 'Root path': tempdir,
+ 'Project name': u'\u30c9\u30a4\u30c4', #Fullwidth characters only
+ 'Author name': 'Georg Brandl',
+ 'Project version': '0.1',
+ }
+ qs.term_input = mock_raw_input(answers)
+ d = {}
+ qs.ask_user(d)
+ qs.generate(d)
+
+ conffile = tempdir / 'conf.py'
+ assert conffile.isfile()
+ ns = {}
+ execfile_(conffile, ns)
+ assert ns['latex_documents'][0][1] == 'sphinx.tex'
+ assert ns['man_pages'][0][1] == 'sphinx'
+ assert ns['texinfo_documents'][0][1] == 'sphinx'
diff --git a/tests/test_rst_domain.py b/tests/test_rst_domain.py
new file mode 100644
index 0000000..9f70f5b
--- /dev/null
+++ b/tests/test_rst_domain.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+"""
+ test_rst_domain
+ ~~~~~~~~~~~~~~~
+
+ Tests the reStructuredText domain.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.domains.rst import parse_directive
+
+def test_parse_directive():
+
+ s = parse_directive(u' foö ')
+ assert s == (u'foö', '')
+
+ s = parse_directive(u' .. foö :: ')
+ assert s == (u'foö', ' ')
+
+ s = parse_directive(u'.. foö:: args1 args2')
+ assert s == (u'foö', ' args1 args2')
+
+ s = parse_directive('.. :: bar')
+ assert s == ('.. :: bar', '')
diff --git a/tests/test_search.py b/tests/test_search.py
new file mode 100644
index 0000000..2efd753
--- /dev/null
+++ b/tests/test_search.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+"""
+ test_search
+ ~~~~~~~~~~~
+
+ Test the search index builder.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import frontend, utils
+from docutils.parsers import rst
+
+from sphinx.search import IndexBuilder
+from sphinx.util.pycompat import b
+
+
+settings = parser = None
+
+def setup_module():
+ global settings, parser
+ optparser = frontend.OptionParser(components=(rst.Parser,))
+ settings = optparser.get_default_values()
+ parser = rst.Parser()
+
+
+FILE_CONTENTS = '''\
+.. test that comments are not indexed: boson
+
+test that non-comments are indexed: fermion
+'''
+
+def test_wordcollector():
+ doc = utils.new_document(b('test data'), settings)
+ doc['file'] = 'dummy'
+ parser.parse(FILE_CONTENTS, doc)
+
+ ix = IndexBuilder(None, 'en', {}, None)
+ ix.feed('filename', 'title', doc)
+ assert 'boson' not in ix._mapping
+ assert 'fermion' in ix._mapping
diff --git a/tests/test_searchadapters.py b/tests/test_searchadapters.py
new file mode 100644
index 0000000..81d7c17
--- /dev/null
+++ b/tests/test_searchadapters.py
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+"""
+ test_searchadapters
+ ~~~~~~~~~~~~~~~~~~~
+
+ Test the Web Support Package search adapters.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+from StringIO import StringIO
+
+from sphinx.websupport import WebSupport
+
+from test_websupport import sqlalchemy_missing
+from util import test_root, skip_if, skip_unless_importable
+
+
+def clear_builddir():
+ (test_root / 'websupport').rmtree(True)
+
+
+def teardown_module():
+ (test_root / 'generated').rmtree(True)
+ clear_builddir()
+
+
+def search_adapter_helper(adapter):
+ clear_builddir()
+
+ settings = {'builddir': os.path.join(test_root, 'websupport'),
+ 'status': StringIO(),
+ 'warning': StringIO()}
+ settings.update({'srcdir': test_root,
+ 'search': adapter})
+ support = WebSupport(**settings)
+ support.build()
+
+ s = support.search
+
+ # Test the adapters query method. A search for "Epigraph" should return
+ # one result.
+ results = s.query(u'Epigraph')
+ assert len(results) == 1, \
+ '%s search adapter returned %s search result(s), should have been 1'\
+ % (adapter, len(results))
+
+ # Make sure documents are properly updated by the search adapter.
+ s.init_indexing(changed=['markup'])
+ s.add_document(u'markup', u'title', u'SomeLongRandomWord')
+ s.finish_indexing()
+ # Now a search for "Epigraph" should return zero results.
+ results = s.query(u'Epigraph')
+ assert len(results) == 0, \
+ '%s search adapter returned %s search result(s), should have been 0'\
+ % (adapter, len(results))
+ # A search for "SomeLongRandomWord" should return one result.
+ results = s.query(u'SomeLongRandomWord')
+ assert len(results) == 1, \
+ '%s search adapter returned %s search result(s), should have been 1'\
+ % (adapter, len(results))
+ # Make sure it works through the WebSupport API
+ html = support.get_search_results(u'SomeLongRandomWord')
+
+
+ at skip_unless_importable('xapian', 'needs xapian bindings installed')
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+def test_xapian():
+ search_adapter_helper('xapian')
+
+
+ at skip_unless_importable('whoosh', 'needs whoosh package installed')
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+def test_whoosh():
+ search_adapter_helper('whoosh')
diff --git a/tests/test_setup_command.py b/tests/test_setup_command.py
new file mode 100644
index 0000000..c165b2d
--- /dev/null
+++ b/tests/test_setup_command.py
@@ -0,0 +1,105 @@
+# -*- coding: utf-8 -*-
+"""
+ test_setup_command
+ ~~~~~~~~~~~~~~~~~~~
+
+ Test setup_command for distutils.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import sys
+import subprocess
+from functools import wraps
+import tempfile
+import sphinx
+
+from util import with_tempdir, test_roots, SkipTest
+from path import path
+from textwrap import dedent
+
+root = test_roots / 'test-setup'
+
+
+def with_setup_command(root, *args, **kwds):
+ """
+ Run `setup.py build_sphinx` with args and kwargs,
+ pass it to the test and clean up properly.
+ """
+ def generator(func):
+ @wraps(func)
+ def deco(*args2, **kwargs2):
+ tempdir = path(tempfile.mkdtemp())
+ pkgrootdir = (tempdir / 'root')
+ root.copytree(pkgrootdir)
+ cwd = os.getcwd()
+ os.chdir(pkgrootdir)
+ pythonpath = os.path.dirname(os.path.dirname(sphinx.__file__))
+ if os.getenv('PYTHONPATH'):
+ pythonpath = os.getenv('PYTHONPATH') + os.pathsep + pythonpath
+ command = [sys.executable, 'setup.py', 'build_sphinx']
+ command.extend(args)
+ try:
+ proc = subprocess.Popen(
+ command,
+ env=dict(os.environ, PYTHONPATH=pythonpath),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ func(pkgrootdir, proc)
+ finally:
+ tempdir.rmtree(ignore_errors=True)
+ os.chdir(cwd)
+ return deco
+ return generator
+
+
+ at with_setup_command(root)
+def test_build_sphinx(pkgroot, proc):
+ out, err = proc.communicate()
+ print(out)
+ print(err)
+ assert proc.returncode == 0
+
+
+ at with_setup_command(root)
+def test_build_sphinx_with_nonascii_path(pkgroot, proc):
+ mb_name = u'\u65e5\u672c\u8a9e'
+ srcdir = (pkgroot / 'doc')
+ try:
+ (srcdir / mb_name).makedirs()
+ except UnicodeEncodeError:
+ from path import FILESYSTEMENCODING
+ raise SkipTest(
+ 'non-ASCII filename not supported on this filesystem encoding: '
+ '%s', FILESYSTEMENCODING)
+
+ (srcdir / mb_name / (mb_name + '.txt')).write_text(dedent("""
+ multi byte file name page
+ ==========================
+ """))
+
+ master_doc = srcdir / 'contents.txt'
+ master_doc.write_bytes((master_doc.text() + dedent("""
+ .. toctree::
+
+ %(mb_name)s/%(mb_name)s
+ """ % locals())
+ ).encode('utf-8'))
+
+ out, err = proc.communicate()
+ print(out)
+ print(err)
+ assert proc.returncode == 0
+
+
+ at with_setup_command(root, '-b', 'linkcheck')
+def test_build_sphinx_return_nonzero_status(pkgroot, proc):
+ srcdir = (pkgroot / 'doc')
+ (srcdir / 'contents.txt').write_text(
+ 'http://localhost.unexistentdomain/index.html')
+ out, err = proc.communicate()
+ print(out)
+ print(err)
+ assert proc.returncode != 0, 'expect non-zero status for setup.py'
diff --git a/tests/test_templating.py b/tests/test_templating.py
new file mode 100644
index 0000000..e8fafca
--- /dev/null
+++ b/tests/test_templating.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+"""
+ test_templating
+ ~~~~~~~~~~~~~~~~
+
+ Test templating.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from util import test_roots, with_app
+
+
+def teardown_module():
+ (test_roots / 'test-templating' / '_build').rmtree(True),
+
+
+ at with_app(buildername='html', srcdir=(test_roots / 'test-templating'))
+def test_layout_overloading(app):
+ app.builder.build_all()
+
+ result = (app.outdir / 'contents.html').text(encoding='utf-8')
+
+ assert '<!-- layout overloading -->' in result
+
+
+ at with_app(buildername='html', srcdir=(test_roots / 'test-templating'))
+def test_autosummary_class_template_overloading(app):
+ app.builder.build_all()
+
+ result = (app.outdir / 'generated' / 'sphinx.application.Sphinx.html').text(
+ encoding='utf-8')
+
+ assert 'autosummary/class.rst method block overloading' in result
+
diff --git a/tests/test_theming.py b/tests/test_theming.py
new file mode 100644
index 0000000..7f91a32
--- /dev/null
+++ b/tests/test_theming.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+"""
+ test_theming
+ ~~~~~~~~~~~~
+
+ Test the Theme class.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import zipfile
+
+from sphinx.theming import Theme, ThemeError
+
+from util import with_app, raises
+
+
+ at with_app(confoverrides={'html_theme': 'ziptheme',
+ 'html_theme_options.testopt': 'foo'})
+def test_theme_api(app):
+ cfg = app.config
+
+ # test Theme class API
+ assert set(Theme.themes.keys()) == \
+ set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku',
+ 'traditional', 'testtheme', 'ziptheme', 'epub', 'nature',
+ 'pyramid'])
+ assert Theme.themes['testtheme'][1] is None
+ assert isinstance(Theme.themes['ziptheme'][1], zipfile.ZipFile)
+
+ # test Theme instance API
+ theme = app.builder.theme
+ assert theme.name == 'ziptheme'
+ assert theme.themedir_created
+ themedir = theme.themedir
+ assert theme.base.name == 'basic'
+ assert len(theme.get_dirchain()) == 2
+
+ # direct setting
+ assert theme.get_confstr('theme', 'stylesheet') == 'custom.css'
+ # inherited setting
+ assert theme.get_confstr('options', 'nosidebar') == 'false'
+ # nonexisting setting
+ assert theme.get_confstr('theme', 'foobar', 'def') == 'def'
+ raises(ThemeError, theme.get_confstr, 'theme', 'foobar')
+
+ # options API
+ raises(ThemeError, theme.get_options, {'nonexisting': 'foo'})
+ options = theme.get_options(cfg.html_theme_options)
+ assert options['testopt'] == 'foo'
+ assert options['nosidebar'] == 'false'
+
+ # cleanup temp directories
+ theme.cleanup()
+ assert not os.path.exists(themedir)
diff --git a/tests/test_util_nodes.py b/tests/test_util_nodes.py
new file mode 100644
index 0000000..9ddc049
--- /dev/null
+++ b/tests/test_util_nodes.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+"""
+ test_util_nodes
+ ~~~~~~~~~~~~~~~
+
+ Tests uti.nodes functions.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from textwrap import dedent
+
+from docutils import nodes
+from docutils.parsers import rst
+from docutils.utils import new_document
+from docutils import frontend
+
+from sphinx.util.nodes import extract_messages
+
+
+def _get_doctree(text):
+ settings = frontend.OptionParser(
+ components=(rst.Parser,)).get_default_values()
+ document = new_document('dummy.txt', settings)
+ rst.Parser().parse(text, document)
+ return document
+
+
+def assert_node_count(messages, node_type, expect_count):
+ count = 0
+ node_list = [node for node, msg in messages]
+ for node in node_list:
+ if isinstance(node, node_type):
+ count += 1
+
+ assert count == expect_count, (
+ "Count of %r in the %r is %d instead of %d"
+ % (node_type, node_list, count, expect_count))
+
+
+def test_extract_messages():
+ text = dedent(
+ """
+ .. admonition:: admonition title
+
+ admonition body
+ """
+ )
+ yield (
+ assert_node_count,
+ extract_messages(_get_doctree(text)),
+ nodes.title, 1,
+ )
+
+ text = dedent(
+ """
+ .. figure:: foo.jpg
+
+ this is title
+ """
+ )
+ yield (
+ assert_node_count,
+ extract_messages(_get_doctree(text)),
+ nodes.caption, 1,
+ )
+
+ text = dedent(
+ """
+ .. rubric:: spam
+ """
+ )
+ yield (
+ assert_node_count,
+ extract_messages(_get_doctree(text)),
+ nodes.rubric, 1,
+ )
+
+
+ text = dedent(
+ """
+ | spam
+ | egg
+ """
+ )
+ yield (
+ assert_node_count,
+ extract_messages(_get_doctree(text)),
+ nodes.line, 2,
+ )
+
+
+ text = dedent(
+ """
+ section
+ =======
+
+ +----------------+
+ | | **Title 1** |
+ | | Message 1 |
+ +----------------+
+ """
+ )
+ yield (
+ assert_node_count,
+ extract_messages(_get_doctree(text)),
+ nodes.line, 2,
+ )
+
+
+ text = dedent(
+ """
+ * | **Title 1**
+ | Message 1
+ """
+ )
+ yield (
+ assert_node_count,
+ extract_messages(_get_doctree(text)),
+ nodes.line, 2,
+ )
diff --git a/tests/test_versioning.py b/tests/test_versioning.py
new file mode 100644
index 0000000..bf2f65e
--- /dev/null
+++ b/tests/test_versioning.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+"""
+ test_versioning
+ ~~~~~~~~~~~~~~~
+
+ Test the versioning implementation.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import pickle
+
+from docutils.parsers.rst.directives.html import MetaBody
+
+from sphinx import addnodes
+from sphinx.versioning import add_uids, merge_doctrees, get_ratio
+from sphinx.util.pycompat import all
+
+from util import test_root, TestApp
+
+
+app = original = original_uids = None
+
+def setup_module():
+ global app, original, original_uids
+ app = TestApp()
+ app.builder.env.app = app
+ app.connect('doctree-resolved', on_doctree_resolved)
+ app.build()
+ original = doctrees['versioning/original']
+ original_uids = [n.uid for n in add_uids(original, is_paragraph)]
+
+def teardown_module():
+ app.cleanup()
+ (test_root / '_build').rmtree(True)
+
+doctrees = {}
+
+def on_doctree_resolved(app, doctree, docname):
+ doctrees[docname] = doctree
+
+def is_paragraph(node):
+ return node.__class__.__name__ == 'paragraph'
+
+def test_get_ratio():
+ assert get_ratio('', 'a')
+ assert get_ratio('a', '')
+
+def test_add_uids():
+ assert len(original_uids) == 3
+
+def test_picklablility():
+ # we have to modify the doctree so we can pickle it
+ copy = original.copy()
+ copy.reporter = None
+ copy.transformer = None
+ copy.settings.warning_stream = None
+ copy.settings.env = None
+ copy.settings.record_dependencies = None
+ for metanode in copy.traverse(MetaBody.meta):
+ metanode.__class__ = addnodes.meta
+ loaded = pickle.loads(pickle.dumps(copy, pickle.HIGHEST_PROTOCOL))
+ assert all(getattr(n, 'uid', False) for n in loaded.traverse(is_paragraph))
+
+def test_modified():
+ modified = doctrees['versioning/modified']
+ new_nodes = list(merge_doctrees(original, modified, is_paragraph))
+ uids = [n.uid for n in modified.traverse(is_paragraph)]
+ assert not new_nodes
+ assert original_uids == uids
+
+def test_added():
+ added = doctrees['versioning/added']
+ new_nodes = list(merge_doctrees(original, added, is_paragraph))
+ uids = [n.uid for n in added.traverse(is_paragraph)]
+ assert len(new_nodes) == 1
+ assert original_uids == uids[:-1]
+
+def test_deleted():
+ deleted = doctrees['versioning/deleted']
+ new_nodes = list(merge_doctrees(original, deleted, is_paragraph))
+ uids = [n.uid for n in deleted.traverse(is_paragraph)]
+ assert not new_nodes
+ assert original_uids[::2] == uids
+
+def test_deleted_end():
+ deleted_end = doctrees['versioning/deleted_end']
+ new_nodes = list(merge_doctrees(original, deleted_end, is_paragraph))
+ uids = [n.uid for n in deleted_end.traverse(is_paragraph)]
+ assert not new_nodes
+ assert original_uids[:-1] == uids
+
+def test_insert():
+ insert = doctrees['versioning/insert']
+ new_nodes = list(merge_doctrees(original, insert, is_paragraph))
+ uids = [n.uid for n in insert.traverse(is_paragraph)]
+ assert len(new_nodes) == 1
+ assert original_uids[0] == uids[0]
+ assert original_uids[1:] == uids[2:]
+
+def test_insert_beginning():
+ insert_beginning = doctrees['versioning/insert_beginning']
+ new_nodes = list(merge_doctrees(original, insert_beginning, is_paragraph))
+ uids = [n.uid for n in insert_beginning.traverse(is_paragraph)]
+ assert len(new_nodes) == 1
+ assert len(uids) == 4
+ assert original_uids == uids[1:]
+ assert original_uids[0] != uids[0]
+
+def test_insert_similar():
+ insert_similar = doctrees['versioning/insert_similar']
+ new_nodes = list(merge_doctrees(original, insert_similar, is_paragraph))
+ uids = [n.uid for n in insert_similar.traverse(is_paragraph)]
+ assert len(new_nodes) == 1
+ assert new_nodes[0].rawsource == u'Anyway I need more'
+ assert original_uids[0] == uids[0]
+ assert original_uids[1:] == uids[2:]
diff --git a/tests/test_websupport.py b/tests/test_websupport.py
new file mode 100644
index 0000000..9376a2a
--- /dev/null
+++ b/tests/test_websupport.py
@@ -0,0 +1,276 @@
+# -*- coding: utf-8 -*-
+"""
+ test_websupport
+ ~~~~~~~~~~~~~~~
+
+ Test the Web Support Package
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+from StringIO import StringIO
+
+try:
+ from functools import wraps
+except ImportError:
+ # functools is new in 2.5
+ wraps = lambda f: (lambda w: w)
+
+from sphinx.websupport import WebSupport
+from sphinx.websupport.errors import DocumentNotFoundError, \
+ CommentNotAllowedError, UserNotAuthorizedError
+from sphinx.websupport.storage import StorageBackend
+from sphinx.websupport.storage.differ import CombinedHtmlDiff
+try:
+ from sphinx.websupport.storage.sqlalchemystorage import Session, \
+ Comment, CommentVote
+ from sphinx.websupport.storage.sqlalchemy_db import Node
+ sqlalchemy_missing = False
+except ImportError:
+ sqlalchemy_missing = True
+
+from util import test_root, raises, skip_if
+
+
+default_settings = {'builddir': os.path.join(test_root, 'websupport'),
+ 'status': StringIO(),
+ 'warning': StringIO()}
+
+def teardown_module():
+ (test_root / 'generated').rmtree(True)
+ (test_root / 'websupport').rmtree(True)
+
+
+def with_support(*args, **kwargs):
+ """Make a WebSupport object and pass it the test."""
+ settings = default_settings.copy()
+ settings.update(kwargs)
+
+ def generator(func):
+ @wraps(func)
+ def new_func(*args2, **kwargs2):
+ support = WebSupport(**settings)
+ func(support, *args2, **kwargs2)
+ return new_func
+ return generator
+
+
+class NullStorage(StorageBackend):
+ pass
+
+
+ at with_support(storage=NullStorage())
+def test_no_srcdir(support):
+ """Make sure the correct exception is raised if srcdir is not given."""
+ raises(RuntimeError, support.build)
+
+
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+ at with_support(srcdir=test_root)
+def test_build(support):
+ support.build()
+
+
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+ at with_support()
+def test_get_document(support):
+ raises(DocumentNotFoundError, support.get_document, 'nonexisting')
+
+ contents = support.get_document('contents')
+ assert contents['title'] and contents['body'] \
+ and contents['sidebar'] and contents['relbar']
+
+
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+ at with_support()
+def test_comments(support):
+ session = Session()
+ nodes = session.query(Node).all()
+ first_node = nodes[0]
+ second_node = nodes[1]
+
+ # Create a displayed comment and a non displayed comment.
+ comment = support.add_comment('First test comment',
+ node_id=first_node.id,
+ username='user_one')
+ hidden_comment = support.add_comment('Hidden comment',
+ node_id=first_node.id,
+ displayed=False)
+ # Make sure that comments can't be added to a comment where
+ # displayed == False, since it could break the algorithm that
+ # converts a nodes comments to a tree.
+ raises(CommentNotAllowedError, support.add_comment, 'Not allowed',
+ parent_id=str(hidden_comment['id']))
+ # Add a displayed and not displayed child to the displayed comment.
+ support.add_comment('Child test comment', parent_id=str(comment['id']),
+ username='user_one')
+ support.add_comment('Hidden child test comment',
+ parent_id=str(comment['id']), displayed=False)
+ # Add a comment to another node to make sure it isn't returned later.
+ support.add_comment('Second test comment',
+ node_id=second_node.id,
+ username='user_two')
+
+ # Access the comments as a moderator.
+ data = support.get_data(first_node.id, moderator=True)
+ comments = data['comments']
+ children = comments[0]['children']
+ assert len(comments) == 2
+ assert comments[1]['text'] == '<p>Hidden comment</p>\n'
+ assert len(children) == 2
+ assert children[1]['text'] == '<p>Hidden child test comment</p>\n'
+
+ # Access the comments without being a moderator.
+ data = support.get_data(first_node.id)
+ comments = data['comments']
+ children = comments[0]['children']
+ assert len(comments) == 1
+ assert comments[0]['text'] == '<p>First test comment</p>\n'
+ assert len(children) == 1
+ assert children[0]['text'] == '<p>Child test comment</p>\n'
+
+
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+ at with_support()
+def test_voting(support):
+ session = Session()
+ nodes = session.query(Node).all()
+ node = nodes[0]
+
+ comment = support.get_data(node.id)['comments'][0]
+
+ def check_rating(val):
+ data = support.get_data(node.id)
+ comment = data['comments'][0]
+ assert comment['rating'] == val, '%s != %s' % (comment['rating'], val)
+
+ support.process_vote(comment['id'], 'user_one', '1')
+ support.process_vote(comment['id'], 'user_two', '1')
+ support.process_vote(comment['id'], 'user_three', '1')
+ check_rating(3)
+ support.process_vote(comment['id'], 'user_one', '-1')
+ check_rating(1)
+ support.process_vote(comment['id'], 'user_one', '0')
+ check_rating(2)
+
+ # Make sure a vote with value > 1 or < -1 can't be cast.
+ raises(ValueError, support.process_vote, comment['id'], 'user_one', '2')
+ raises(ValueError, support.process_vote, comment['id'], 'user_one', '-2')
+
+ # Make sure past voting data is associated with comments when they are
+ # fetched.
+ data = support.get_data(str(node.id), username='user_two')
+ comment = data['comments'][0]
+ assert comment['vote'] == 1, '%s != 1' % comment['vote']
+
+
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+ at with_support()
+def test_proposals(support):
+ session = Session()
+ node = session.query(Node).first()
+
+ data = support.get_data(node.id)
+
+ source = data['source']
+ proposal = source[:5] + source[10:15] + 'asdf' + source[15:]
+
+ comment = support.add_comment('Proposal comment',
+ node_id=node.id,
+ proposal=proposal)
+
+
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+ at with_support()
+def test_user_delete_comments(support):
+ def get_comment():
+ session = Session()
+ node = session.query(Node).first()
+ session.close()
+ return support.get_data(node.id)['comments'][0]
+
+ comment = get_comment()
+ assert comment['username'] == 'user_one'
+ # Make sure other normal users can't delete someone elses comments.
+ raises(UserNotAuthorizedError, support.delete_comment,
+ comment['id'], username='user_two')
+ # Now delete the comment using the correct username.
+ support.delete_comment(comment['id'], username='user_one')
+ comment = get_comment()
+ assert comment['username'] == '[deleted]'
+ assert comment['text'] == '[deleted]'
+
+
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+ at with_support()
+def test_moderator_delete_comments(support):
+ def get_comment():
+ session = Session()
+ node = session.query(Node).first()
+ session.close()
+ return support.get_data(node.id, moderator=True)['comments'][1]
+
+ comment = get_comment()
+ support.delete_comment(comment['id'], username='user_two',
+ moderator=True)
+ raises(IndexError, get_comment)
+
+
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+ at with_support()
+def test_update_username(support):
+ support.update_username('user_two', 'new_user_two')
+ session = Session()
+ comments = session.query(Comment).\
+ filter(Comment.username == 'user_two').all()
+ assert len(comments) == 0
+ votes = session.query(CommentVote).\
+ filter(CommentVote.username == 'user_two').all()
+ assert len(votes) == 0
+ comments = session.query(Comment).\
+ filter(Comment.username == 'new_user_two').all()
+ assert len(comments) == 1
+ votes = session.query(CommentVote).\
+ filter(CommentVote.username == 'new_user_two').all()
+ assert len(votes) == 0
+
+
+called = False
+def moderation_callback(comment):
+ global called
+ called = True
+
+
+ at skip_if(sqlalchemy_missing, 'needs sqlalchemy')
+ at with_support(moderation_callback=moderation_callback)
+def test_moderation(support):
+ session = Session()
+ nodes = session.query(Node).all()
+ node = nodes[7]
+ session.close()
+ accepted = support.add_comment('Accepted Comment', node_id=node.id,
+ displayed=False)
+ deleted = support.add_comment('Comment to delete', node_id=node.id,
+ displayed=False)
+ # Make sure the moderation_callback is called.
+ assert called == True
+ # Make sure the user must be a moderator.
+ raises(UserNotAuthorizedError, support.accept_comment, accepted['id'])
+ raises(UserNotAuthorizedError, support.delete_comment, deleted['id'])
+ support.accept_comment(accepted['id'], moderator=True)
+ support.delete_comment(deleted['id'], moderator=True)
+ comments = support.get_data(node.id)['comments']
+ assert len(comments) == 1
+ comments = support.get_data(node.id, moderator=True)['comments']
+ assert len(comments) == 1
+
+
+def test_differ():
+ source = 'Lorem ipsum dolor sit amet,\nconsectetur adipisicing elit,\n' \
+ 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
+ prop = 'Lorem dolor sit amet,\nconsectetur nihil adipisicing elit,\n' \
+ 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
+ differ = CombinedHtmlDiff(source, prop)
+ differ.make_html()
diff --git a/tests/util.py b/tests/util.py
new file mode 100644
index 0000000..61c9bd0
--- /dev/null
+++ b/tests/util.py
@@ -0,0 +1,252 @@
+# -*- coding: utf-8 -*-
+"""
+ Sphinx test suite utilities
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import StringIO
+import tempfile
+import shutil
+import re
+from codecs import open
+
+try:
+ from functools import wraps
+except ImportError:
+ # functools is new in 2.4
+ wraps = lambda f: (lambda w: w)
+
+from sphinx import application
+from sphinx.theming import Theme
+from sphinx.ext.autodoc import AutoDirective
+
+from path import path
+
+from nose import tools, SkipTest
+
+
+__all__ = [
+ 'test_root', 'test_roots', 'raises', 'raises_msg',
+ 'skip_if', 'skip_unless', 'skip_unless_importable', 'Struct',
+ 'ListOutput', 'TestApp', 'with_app', 'gen_with_app',
+ 'path', 'with_tempdir', 'write_file',
+ 'sprint', 'remove_unicode_literals',
+]
+
+
+test_root = path(__file__).parent.joinpath('root').abspath()
+test_roots = path(__file__).parent.joinpath('roots').abspath()
+
+
+def _excstr(exc):
+ if type(exc) is tuple:
+ return str(tuple(map(_excstr, exc)))
+ return exc.__name__
+
+def raises(exc, func, *args, **kwds):
+ """
+ Raise :exc:`AssertionError` if ``func(*args, **kwds)`` does not
+ raise *exc*.
+ """
+ try:
+ func(*args, **kwds)
+ except exc:
+ pass
+ else:
+ raise AssertionError('%s did not raise %s' %
+ (func.__name__, _excstr(exc)))
+
+def raises_msg(exc, msg, func, *args, **kwds):
+ """
+ Raise :exc:`AssertionError` if ``func(*args, **kwds)`` does not
+ raise *exc*, and check if the message contains *msg*.
+ """
+ try:
+ func(*args, **kwds)
+ except exc, err:
+ assert msg in str(err), "\"%s\" not in \"%s\"" % (msg, err)
+ else:
+ raise AssertionError('%s did not raise %s' %
+ (func.__name__, _excstr(exc)))
+
+def skip_if(condition, msg=None):
+ """Decorator to skip test if condition is true."""
+ def deco(test):
+ @tools.make_decorator(test)
+ def skipper(*args, **kwds):
+ if condition:
+ raise SkipTest(msg or 'conditional skip')
+ return test(*args, **kwds)
+ return skipper
+ return deco
+
+def skip_unless(condition, msg=None):
+ """Decorator to skip test if condition is false."""
+ return skip_if(not condition, msg)
+
+def skip_unless_importable(module, msg=None):
+ """Decorator to skip test if module is not importable."""
+ try:
+ __import__(module)
+ except ImportError:
+ return skip_if(True, msg)
+ else:
+ return skip_if(False, msg)
+
+
+class Struct(object):
+ def __init__(self, **kwds):
+ self.__dict__.update(kwds)
+
+
+class ListOutput(object):
+ """
+ File-like object that collects written text in a list.
+ """
+ def __init__(self, name):
+ self.name = name
+ self.content = []
+
+ def reset(self):
+ del self.content[:]
+
+ def write(self, text):
+ self.content.append(text)
+
+
+class TestApp(application.Sphinx):
+ """
+ A subclass of :class:`Sphinx` that runs on the test root, with some
+ better default values for the initialization parameters.
+ """
+
+ def __init__(self, srcdir=None, confdir=None, outdir=None, doctreedir=None,
+ buildername='html', confoverrides=None,
+ status=None, warning=None, freshenv=None,
+ warningiserror=None, tags=None,
+ confname='conf.py', cleanenv=False):
+
+ application.CONFIG_FILENAME = confname
+
+ self.cleanup_trees = [test_root / 'generated']
+
+ if srcdir is None:
+ srcdir = test_root
+ if srcdir == '(temp)':
+ tempdir = path(tempfile.mkdtemp())
+ self.cleanup_trees.append(tempdir)
+ temproot = tempdir / 'root'
+ test_root.copytree(temproot)
+ srcdir = temproot
+ elif srcdir == '(empty)':
+ tempdir = path(tempfile.mkdtemp())
+ self.cleanup_trees.append(tempdir)
+ temproot = tempdir / 'root'
+ temproot.makedirs()
+ (temproot / 'conf.py').write_text('')
+ srcdir = temproot
+ else:
+ srcdir = path(srcdir)
+ self.builddir = srcdir.joinpath('_build')
+ if confdir is None:
+ confdir = srcdir
+ if outdir is None:
+ outdir = srcdir.joinpath(self.builddir, buildername)
+ if not outdir.isdir():
+ outdir.makedirs()
+ self.cleanup_trees.insert(0, outdir)
+ if doctreedir is None:
+ doctreedir = srcdir.joinpath(srcdir, self.builddir, 'doctrees')
+ if not doctreedir.isdir():
+ doctreedir.makedirs()
+ if cleanenv:
+ self.cleanup_trees.insert(0, doctreedir)
+ if confoverrides is None:
+ confoverrides = {}
+ if status is None:
+ status = StringIO.StringIO()
+ if warning is None:
+ warning = ListOutput('stderr')
+ if freshenv is None:
+ freshenv = False
+ if warningiserror is None:
+ warningiserror = False
+
+ application.Sphinx.__init__(self, srcdir, confdir, outdir, doctreedir,
+ buildername, confoverrides, status, warning,
+ freshenv, warningiserror, tags)
+
+ def cleanup(self, doctrees=False):
+ Theme.themes.clear()
+ AutoDirective._registry.clear()
+ for tree in self.cleanup_trees:
+ shutil.rmtree(tree, True)
+
+ def __repr__(self):
+ return '<%s buildername=%r>' % (self.__class__.__name__, self.builder.name)
+
+
+def with_app(*args, **kwargs):
+ """
+ Make a TestApp with args and kwargs, pass it to the test and clean up
+ properly.
+ """
+ def generator(func):
+ @wraps(func)
+ def deco(*args2, **kwargs2):
+ app = TestApp(*args, **kwargs)
+ func(app, *args2, **kwargs2)
+ # don't execute cleanup if test failed
+ app.cleanup()
+ return deco
+ return generator
+
+
+def gen_with_app(*args, **kwargs):
+ """
+ Decorate a test generator to pass a TestApp as the first argument to the
+ test generator when it's executed.
+ """
+ def generator(func):
+ @wraps(func)
+ def deco(*args2, **kwargs2):
+ app = TestApp(*args, **kwargs)
+ for item in func(app, *args2, **kwargs2):
+ yield item
+ # don't execute cleanup if test failed
+ app.cleanup()
+ return deco
+ return generator
+
+
+def with_tempdir(func):
+ def new_func(*args, **kwds):
+ tempdir = path(tempfile.mkdtemp())
+ func(tempdir, *args, **kwds)
+ tempdir.rmtree()
+ new_func.__name__ = func.__name__
+ return new_func
+
+
+def write_file(name, contents, encoding=None):
+ if encoding is None:
+ mode = 'wb'
+ if isinstance(contents, unicode):
+ contents = contents.encode('ascii')
+ else:
+ mode = 'w'
+ f = open(str(name), mode, encoding=encoding)
+ f.write(contents)
+ f.close()
+
+
+def sprint(*args):
+ sys.stderr.write(' '.join(map(str, args)) + '\n')
+
+_unicode_literals_re = re.compile(r'u(".*?")|u(\'.*?\')')
+def remove_unicode_literals(s):
+ return _unicode_literals_re.sub(lambda x: x.group(1) or x.group(2), s)
diff --git a/utils/check_sources.py b/utils/check_sources.py
new file mode 100755
index 0000000..7bbd0a7
--- /dev/null
+++ b/utils/check_sources.py
@@ -0,0 +1,247 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ Checker for file headers
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Make sure each Python file has a correct file header
+ including copyright and license information.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys, os, re
+import cStringIO
+from optparse import OptionParser
+from os.path import join, splitext, abspath
+
+if sys.version_info >= (3, 0):
+ def b(s):
+ return s.encode('utf-8')
+else:
+ b = str
+
+
+checkers = {}
+
+def checker(*suffixes, **kwds):
+ only_pkg = kwds.pop('only_pkg', False)
+ def deco(func):
+ for suffix in suffixes:
+ checkers.setdefault(suffix, []).append(func)
+ func.only_pkg = only_pkg
+ return func
+ return deco
+
+
+name_mail_re = r'[\w ]+(<.*?>)?'
+copyright_re = re.compile(b(r'^ :copyright: Copyright 200\d(-20\d\d)? '
+ r'by %s(, %s)*[,.]$' %
+ (name_mail_re, name_mail_re)))
+license_re = re.compile(b(r" :license: (.*?).\n"))
+copyright_2_re = re.compile(b(r'^ %s(, %s)*[,.]$' %
+ (name_mail_re, name_mail_re)))
+coding_re = re.compile(b(r'coding[:=]\s*([-\w.]+)'))
+not_ix_re = re.compile(b(r'\bnot\s+\S+?\s+i[sn]\s\S+'))
+is_const_re = re.compile(b(r'if.*?==\s+(None|False|True)\b'))
+
+misspellings = [b("developement"), b("adress"), # ALLOW-MISSPELLING
+ b("verificate"), b("informations")] # ALLOW-MISSPELLING
+
+if sys.version_info < (3, 0):
+ @checker('.py')
+ def check_syntax(fn, lines):
+ try:
+ compile(b('').join(lines), fn, "exec")
+ except SyntaxError, err:
+ yield 0, "not compilable: %s" % err
+
+
+ at checker('.py')
+def check_style_and_encoding(fn, lines):
+ encoding = 'ascii'
+ for lno, line in enumerate(lines):
+ if len(line) > 90:
+ yield lno+1, "line too long"
+ if lno < 2:
+ co = coding_re.search(line)
+ if co:
+ encoding = co.group(1).decode('ascii')
+ if line.strip().startswith(b('#')):
+ continue
+ #m = not_ix_re.search(line)
+ #if m:
+ # yield lno+1, '"' + m.group() + '"'
+ if is_const_re.search(line):
+ yield lno+1, 'using == None/True/False'
+ try:
+ line.decode(encoding)
+ except UnicodeDecodeError, err:
+ yield lno+1, "not decodable: %s\n Line: %r" % (err, line)
+ except LookupError, err:
+ yield 0, "unknown encoding: %s" % encoding
+ encoding = 'latin1'
+
+
+ at checker('.py', only_pkg=True)
+def check_fileheader(fn, lines):
+ # line number correction
+ c = 1
+ if lines[0:1] == [b('#!/usr/bin/env python\n')]:
+ lines = lines[1:]
+ c = 2
+
+ llist = []
+ docopen = False
+ for lno, l in enumerate(lines):
+ llist.append(l)
+ if lno == 0:
+ if l == b('# -*- coding: rot13 -*-\n'):
+ # special-case pony package
+ return
+ elif l != b('# -*- coding: utf-8 -*-\n'):
+ yield 1, "missing coding declaration"
+ elif lno == 1:
+ if l != b('"""\n') and l != b('r"""\n'):
+ yield 2, 'missing docstring begin (""")'
+ else:
+ docopen = True
+ elif docopen:
+ if l == b('"""\n'):
+ # end of docstring
+ if lno <= 4:
+ yield lno+c, "missing module name in docstring"
+ break
+
+ if l != b("\n") and l[:4] != b(' ') and docopen:
+ yield lno+c, "missing correct docstring indentation"
+
+ if lno == 2:
+ # if not in package, don't check the module name
+ modname = fn[:-3].replace('/', '.').replace('.__init__', '')
+ while modname:
+ if l.lower()[4:-1] == b(modname):
+ break
+ modname = '.'.join(modname.split('.')[1:])
+ else:
+ yield 3, "wrong module name in docstring heading"
+ modnamelen = len(l.strip())
+ elif lno == 3:
+ if l.strip() != modnamelen * b("~"):
+ yield 4, "wrong module name underline, should be ~~~...~"
+
+ else:
+ yield 0, "missing end and/or start of docstring..."
+
+ # check for copyright and license fields
+ license = llist[-2:-1]
+ if not license or not license_re.match(license[0]):
+ yield 0, "no correct license info"
+
+ ci = -3
+ copyright = llist[ci:ci+1]
+ while copyright and copyright_2_re.match(copyright[0]):
+ ci -= 1
+ copyright = llist[ci:ci+1]
+ if not copyright or not copyright_re.match(copyright[0]):
+ yield 0, "no correct copyright info"
+
+
+ at checker('.py', '.html', '.rst')
+def check_whitespace_and_spelling(fn, lines):
+ for lno, line in enumerate(lines):
+ if b("\t") in line:
+ yield lno+1, "OMG TABS!!!1 "
+ if line[:-1].rstrip(b(' \t')) != line[:-1]:
+ yield lno+1, "trailing whitespace"
+ for word in misspellings:
+ if word in line and b('ALLOW-MISSPELLING') not in line:
+ yield lno+1, '"%s" used' % word
+
+
+bad_tags = map(b, ['<u>', '<s>', '<strike>', '<center>', '<font'])
+
+ at checker('.html')
+def check_xhtml(fn, lines):
+ for lno, line in enumerate(lines):
+ for bad_tag in bad_tags:
+ if bad_tag in line:
+ yield lno+1, "used " + bad_tag
+
+
+def main(argv):
+ parser = OptionParser(usage='Usage: %prog [-v] [-i ignorepath]* [path]')
+ parser.add_option('-v', '--verbose', dest='verbose', default=False,
+ action='store_true')
+ parser.add_option('-i', '--ignore-path', dest='ignored_paths',
+ default=[], action='append')
+ options, args = parser.parse_args(argv[1:])
+
+ if len(args) == 0:
+ path = '.'
+ elif len(args) == 1:
+ path = args[0]
+ else:
+ print args
+ parser.error('No more then one path supported')
+
+ verbose = options.verbose
+ ignored_paths = set(abspath(p) for p in options.ignored_paths)
+
+ num = 0
+ out = cStringIO.StringIO()
+
+ for root, dirs, files in os.walk(path):
+ for vcs_dir in ['.svn', '.hg', '.git']:
+ if vcs_dir in dirs:
+ dirs.remove(vcs_dir)
+ if abspath(root) in ignored_paths:
+ del dirs[:]
+ continue
+ in_check_pkg = root.startswith('./sphinx')
+ for fn in files:
+
+ fn = join(root, fn)
+ if fn[:2] == './': fn = fn[2:]
+
+ if abspath(fn) in ignored_paths:
+ continue
+
+ ext = splitext(fn)[1]
+ checkerlist = checkers.get(ext, None)
+ if not checkerlist:
+ continue
+
+ if verbose:
+ print "Checking %s..." % fn
+
+ try:
+ f = open(fn, 'rb')
+ try:
+ lines = list(f)
+ finally:
+ f.close()
+ except (IOError, OSError), err:
+ print "%s: cannot open: %s" % (fn, err)
+ num += 1
+ continue
+
+ for checker in checkerlist:
+ if not in_check_pkg and checker.only_pkg:
+ continue
+ for lno, msg in checker(fn, lines):
+ print >>out, "%s:%d: %s" % (fn, lno, msg)
+ num += 1
+ if verbose:
+ print
+ if num == 0:
+ print "No errors found."
+ else:
+ print out.getvalue().rstrip('\n')
+ print "%d error%s found." % (num, num > 1 and "s" or "")
+ return int(num > 0)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/utils/convert.py b/utils/convert.py
new file mode 100755
index 0000000..c90be8e
--- /dev/null
+++ b/utils/convert.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+# coding: utf-8
+"""
+ Converts files with 2to3
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Creates a Python 3 version of each file.
+
+ The Python3 version of a file foo.py will be called foo3.py.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import os
+import sys
+from glob import iglob
+from optparse import OptionParser
+from shutil import copy
+from distutils.util import run_2to3
+
+def main(argv):
+ parser = OptionParser(usage='%prog [path]')
+ parser.add_option('-i', '--ignorepath', dest='ignored_paths',
+ action='append', default=[])
+ options, args = parser.parse_args(argv)
+
+ ignored_paths = {os.path.abspath(p) for p in options.ignored_paths}
+
+ path = os.path.abspath(args[0]) if args else os.getcwd()
+ convertables = []
+ for filename in iglob(os.path.join(path, '*.py')):
+ if filename in ignored_paths:
+ continue
+ basename, ext = os.path.splitext(filename)
+ if basename.endswith('3'):
+ continue
+ filename3 = basename + '3' + ext
+ copy(filename, filename3)
+ convertables.append(filename3)
+ run_2to3(convertables)
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/utils/pylintrc b/utils/pylintrc
new file mode 100644
index 0000000..cf71db5
--- /dev/null
+++ b/utils/pylintrc
@@ -0,0 +1,301 @@
+# lint Python modules using external checkers.
+#
+# This is the main checker controling the other ones and the reports
+# generation. It is itself both a raw checker and an astng checker in order
+# to:
+# * handle message activation / deactivation at the module level
+# * handle some basic but necessary stats'data (number of classes, methods...)
+#
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Profiled execution.
+profile=no
+
+# Add <file or directory> to the black list. It should be a base name, not a
+# path. You may set this option multiple times.
+ignore=.svn
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Set the cache size for astng objects.
+cache-size=500
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable only checker(s) with the given id(s). This option conflict with the
+# disable-checker option
+#enable-checker=
+
+# Enable all checker(s) except those with the given id(s). This option conflict
+# with the disable-checker option
+#disable-checker=
+
+# Enable all messages in the listed categories.
+#enable-msg-cat=
+
+# Disable all messages in the listed categories.
+#disable-msg-cat=
+
+# Enable the message(s) with the given id(s).
+#enable-msg=
+
+# Disable the message(s) with the given id(s).
+disable-msg=C0323,W0142,C0301,C0103,C0111,E0213,C0302,C0203,W0703,R0201,W0613,W0612,W0622
+
+
+[REPORTS]
+
+# set the output format. Available formats are text, parseable, colorized and
+# html
+output-format=colorized
+
+# Include message's id in output
+include-ids=yes
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells wether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note).You have access to the variables errors warning, statement which
+# respectivly contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (R0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (R0004).
+comment=no
+
+# Enable the report(s) with the given id(s).
+#enable-report=
+
+# Disable the report(s) with the given id(s).
+#disable-report=
+
+
+# checks for
+# * unused variables / imports
+# * undefined variables
+# * redefinition of variable from builtins or from an outer scope
+# * use of variable before assigment
+#
+[VARIABLES]
+
+# Tells wether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching names used for dummy variables (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+# try to find bugs in the code using type inference
+#
+[TYPECHECK]
+
+# Tells wether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# When zope mode is activated, consider the acquired-members option to ignore
+# access to some undefined attributes.
+zope=no
+
+# List of members which are usually get through zope's acquisition mecanism and
+# so shouldn't trigger E0201 when accessed (need zope=yes to be considered).
+acquired-members=REQUEST,acl_users,aq_parent
+
+
+# checks for :
+# * doc strings
+# * modules / classes / functions / methods / arguments / variables name
+# * number of arguments, local variables, branchs, returns and statements in
+# functions, methods
+# * required module attributes
+# * dangerous default values as arguments
+# * redefinition of function / method / class
+# * uses of the global statement
+#
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=apply,input
+
+
+# checks for sign of poor/misdesign:
+# * number of methods, attributes, local variables...
+# * size, complexity of functions, methods
+#
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=12
+
+# Maximum number of locals for function / method body
+max-locals=30
+
+# Maximum number of return / yield for function / method body
+max-returns=12
+
+# Maximum number of branch for function / method body
+max-branchs=30
+
+# Maximum number of statements in function / method body
+max-statements=60
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=20
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=0
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+# checks for
+# * external modules dependencies
+# * relative / wildcard imports
+# * cyclic imports
+# * uses of deprecated modules
+#
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report R0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report R0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report R0402 must
+# not be disabled)
+int-import-graph=
+
+
+# checks for :
+# * methods without self as first argument
+# * overridden methods signature
+# * access only to existant members via self
+# * attributes not defined in the __init__ method
+# * supported interfaces implementation
+# * unreachable code
+#
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+
+# checks for similarities and duplicated code. This computation may be
+# memory / CPU intensive, so you should disable it if you experiments some
+# problems.
+#
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=10
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+# checks for:
+# * warning notes in the code
+# * PEP 263: source code with non ascii character but no encoding declaration
+#
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+# checks for :
+# * unauthorized constructions
+# * strict indentation
+# * line length
+# * use of <> instead of !=
+#
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=90
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
diff --git a/utils/reindent.py b/utils/reindent.py
new file mode 100755
index 0000000..59828fd
--- /dev/null
+++ b/utils/reindent.py
@@ -0,0 +1,311 @@
+#! /usr/bin/env python
+
+# Released to the public domain, by Tim Peters, 03 October 2000.
+
+"""reindent [-d][-r][-v] [ path ... ]
+
+-d (--dryrun) Dry run. Analyze, but don't make any changes to, files.
+-r (--recurse) Recurse. Search for all .py files in subdirectories too.
+-n (--nobackup) No backup. Does not make a ".bak" file before reindenting.
+-v (--verbose) Verbose. Print informative msgs; else no output.
+-h (--help) Help. Print this usage information and exit.
+
+Change Python (.py) files to use 4-space indents and no hard tab characters.
+Also trim excess spaces and tabs from ends of lines, and remove empty lines
+at the end of files. Also ensure the last line ends with a newline.
+
+If no paths are given on the command line, reindent operates as a filter,
+reading a single source file from standard input and writing the transformed
+source to standard output. In this case, the -d, -r and -v flags are
+ignored.
+
+You can pass one or more file and/or directory paths. When a directory
+path, all .py files within the directory will be examined, and, if the -r
+option is given, likewise recursively for subdirectories.
+
+If output is not to standard output, reindent overwrites files in place,
+renaming the originals with a .bak extension. If it finds nothing to
+change, the file is left alone. If reindent does change a file, the changed
+file is a fixed-point for future runs (i.e., running reindent on the
+resulting .py file won't change it again).
+
+The hard part of reindenting is figuring out what to do with comment
+lines. So long as the input files get a clean bill of health from
+tabnanny.py, reindent should do a good job.
+
+The backup file is a copy of the one that is being reindented. The ".bak"
+file is generated with shutil.copy(), but some corner cases regarding
+user/group and permissions could leave the backup file more readable that
+you'd prefer. You can always use the --nobackup option to prevent this.
+"""
+
+__version__ = "1"
+
+import tokenize
+import os, shutil
+import sys
+
+if sys.version_info >= (3, 0):
+ def tokens(readline, tokeneater):
+ for token in tokenize.tokenize(readline):
+ yield tokeneater(*token)
+else:
+ tokens = tokenize.tokenize
+
+verbose = 0
+recurse = 0
+dryrun = 0
+makebackup = True
+
+def usage(msg=None):
+ if msg is not None:
+ print >> sys.stderr, msg
+ print >> sys.stderr, __doc__
+
+def errprint(*args):
+ sep = ""
+ for arg in args:
+ sys.stderr.write(sep + str(arg))
+ sep = " "
+ sys.stderr.write("\n")
+
+def main():
+ import getopt
+ global verbose, recurse, dryrun, makebackup
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "drnvh",
+ ["dryrun", "recurse", "nobackup", "verbose", "help"])
+ except getopt.error, msg:
+ usage(msg)
+ return
+ for o, a in opts:
+ if o in ('-d', '--dryrun'):
+ dryrun += 1
+ elif o in ('-r', '--recurse'):
+ recurse += 1
+ elif o in ('-n', '--nobackup'):
+ makebackup = False
+ elif o in ('-v', '--verbose'):
+ verbose += 1
+ elif o in ('-h', '--help'):
+ usage()
+ return
+ if not args:
+ r = Reindenter(sys.stdin)
+ r.run()
+ r.write(sys.stdout)
+ return
+ for arg in args:
+ check(arg)
+
+def check(file):
+ if os.path.isdir(file) and not os.path.islink(file):
+ if verbose:
+ print "listing directory", file
+ names = os.listdir(file)
+ for name in names:
+ fullname = os.path.join(file, name)
+ if ((recurse and os.path.isdir(fullname) and
+ not os.path.islink(fullname) and
+ not os.path.split(fullname)[1].startswith("."))
+ or name.lower().endswith(".py")):
+ check(fullname)
+ return
+
+ if verbose:
+ print "checking", file, "...",
+ try:
+ f = open(file)
+ except IOError, msg:
+ errprint("%s: I/O Error: %s" % (file, str(msg)))
+ return
+
+ r = Reindenter(f)
+ f.close()
+ if r.run():
+ if verbose:
+ print "changed."
+ if dryrun:
+ print "But this is a dry run, so leaving it alone."
+ if not dryrun:
+ bak = file + ".bak"
+ if makebackup:
+ shutil.copyfile(file, bak)
+ if verbose:
+ print "backed up", file, "to", bak
+ f = open(file, "w")
+ r.write(f)
+ f.close()
+ if verbose:
+ print "wrote new", file
+ return True
+ else:
+ if verbose:
+ print "unchanged."
+ return False
+
+def _rstrip(line, JUNK='\n \t'):
+ """Return line stripped of trailing spaces, tabs, newlines.
+
+ Note that line.rstrip() instead also strips sundry control characters,
+ but at least one known Emacs user expects to keep junk like that, not
+ mentioning Barry by name or anything <wink>.
+ """
+
+ i = len(line)
+ while i > 0 and line[i-1] in JUNK:
+ i -= 1
+ return line[:i]
+
+class Reindenter:
+
+ def __init__(self, f):
+ self.find_stmt = 1 # next token begins a fresh stmt?
+ self.level = 0 # current indent level
+
+ # Raw file lines.
+ self.raw = f.readlines()
+
+ # File lines, rstripped & tab-expanded. Dummy at start is so
+ # that we can use tokenize's 1-based line numbering easily.
+ # Note that a line is all-blank iff it's "\n".
+ self.lines = [_rstrip(line).expandtabs() + "\n"
+ for line in self.raw]
+ self.lines.insert(0, None)
+ self.index = 1 # index into self.lines of next line
+
+ # List of (lineno, indentlevel) pairs, one for each stmt and
+ # comment line. indentlevel is -1 for comment lines, as a
+ # signal that tokenize doesn't know what to do about them;
+ # indeed, they're our headache!
+ self.stats = []
+
+ def run(self):
+ tokens(self.getline, self.tokeneater)
+ # Remove trailing empty lines.
+ lines = self.lines
+ while lines and lines[-1] == "\n":
+ lines.pop()
+ # Sentinel.
+ stats = self.stats
+ stats.append((len(lines), 0))
+ # Map count of leading spaces to # we want.
+ have2want = {}
+ # Program after transformation.
+ after = self.after = []
+ # Copy over initial empty lines -- there's nothing to do until
+ # we see a line with *something* on it.
+ i = stats[0][0]
+ after.extend(lines[1:i])
+ for i in range(len(stats)-1):
+ thisstmt, thislevel = stats[i]
+ nextstmt = stats[i+1][0]
+ have = getlspace(lines[thisstmt])
+ want = thislevel * 4
+ if want < 0:
+ # A comment line.
+ if have:
+ # An indented comment line. If we saw the same
+ # indentation before, reuse what it most recently
+ # mapped to.
+ want = have2want.get(have, -1)
+ if want < 0:
+ # Then it probably belongs to the next real stmt.
+ for j in xrange(i+1, len(stats)-1):
+ jline, jlevel = stats[j]
+ if jlevel >= 0:
+ if have == getlspace(lines[jline]):
+ want = jlevel * 4
+ break
+ if want < 0: # Maybe it's a hanging
+ # comment like this one,
+ # in which case we should shift it like its base
+ # line got shifted.
+ for j in xrange(i-1, -1, -1):
+ jline, jlevel = stats[j]
+ if jlevel >= 0:
+ want = have + getlspace(after[jline-1]) - \
+ getlspace(lines[jline])
+ break
+ if want < 0:
+ # Still no luck -- leave it alone.
+ want = have
+ else:
+ want = 0
+ assert want >= 0
+ have2want[have] = want
+ diff = want - have
+ if diff == 0 or have == 0:
+ after.extend(lines[thisstmt:nextstmt])
+ else:
+ for line in lines[thisstmt:nextstmt]:
+ if diff > 0:
+ if line == "\n":
+ after.append(line)
+ else:
+ after.append(" " * diff + line)
+ else:
+ remove = min(getlspace(line), -diff)
+ after.append(line[remove:])
+ return self.raw != self.after
+
+ def write(self, f):
+ f.writelines(self.after)
+
+ # Line-getter for tokenize.
+ def getline(self):
+ if self.index >= len(self.lines):
+ line = ""
+ else:
+ line = self.lines[self.index]
+ self.index += 1
+ return line
+
+ # Line-eater for tokenize.
+ def tokeneater(self, type, token, (sline, scol), end, line,
+ INDENT=tokenize.INDENT,
+ DEDENT=tokenize.DEDENT,
+ NEWLINE=tokenize.NEWLINE,
+ COMMENT=tokenize.COMMENT,
+ NL=tokenize.NL):
+
+ if type == NEWLINE:
+ # A program statement, or ENDMARKER, will eventually follow,
+ # after some (possibly empty) run of tokens of the form
+ # (NL | COMMENT)* (INDENT | DEDENT+)?
+ self.find_stmt = 1
+
+ elif type == INDENT:
+ self.find_stmt = 1
+ self.level += 1
+
+ elif type == DEDENT:
+ self.find_stmt = 1
+ self.level -= 1
+
+ elif type == COMMENT:
+ if self.find_stmt:
+ self.stats.append((sline, -1))
+ # but we're still looking for a new stmt, so leave
+ # find_stmt alone
+
+ elif type == NL:
+ pass
+
+ elif self.find_stmt:
+ # This is the first "real token" following a NEWLINE, so it
+ # must be the first token of the next program statement, or an
+ # ENDMARKER.
+ self.find_stmt = 0
+ if line: # not endmarker
+ self.stats.append((sline, self.level))
+
+# Count number of leading blanks.
+def getlspace(line):
+ i, n = 0, len(line)
+ while i < n and line[i] == " ":
+ i += 1
+ return i
+
+if __name__ == '__main__':
+ main()
diff --git a/utils/release-checklist b/utils/release-checklist
new file mode 100644
index 0000000..ab234f3
--- /dev/null
+++ b/utils/release-checklist
@@ -0,0 +1,21 @@
+Release checklist
+=================
+
+* Check hg status
+* Make check
+* Update version info in sphinx/__init__.py
+* Update release date in CHANGES
+* hg commit
+* make clean
+* python setup.py release bdist_wheel sdist upload
+* For all other versions: pythonX.Y setup.py release bdist_wheel upload
+ (remove build/ before each one)
+* Check PyPI release page for obvious errors
+* hg tag
+* Merge default into stable if final major release
+* Update homepage (release info), regenerate docs (+printable!)
+* Add new version/milestone to tracker categories
+* Write announcement and send to mailing list/python-announce
+* Update version info, add new CHANGES entry for next version
+* hg commit
+* hg push
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/sphinx.git
More information about the Reproducible-commits
mailing list