summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshimizukawa <shimizukawa@gmail.com>2014-10-09 22:05:20 +0900
committershimizukawa <shimizukawa@gmail.com>2014-10-09 22:05:20 +0900
commit6075136a5b59e5fdb1b2dafd5f890f039a380ed3 (patch)
tree0bc00da1029be105a4e609397ef1595a11e84e5c
parentaeb2cb53f39d72622813c805db52dee7b2aac3ad (diff)
parentd85167a99b5ef2e2b9e98e287b8097580b3c8b1d (diff)
downloadsphinx-6075136a5b59e5fdb1b2dafd5f890f039a380ed3.tar.gz
merge with stable
-rw-r--r--.hgignore3
-rw-r--r--AUTHORS12
-rw-r--r--CHANGES327
-rw-r--r--EXAMPLES85
-rw-r--r--LICENSE34
-rw-r--r--MANIFEST.in1
-rw-r--r--Makefile4
-rw-r--r--README.rst25
-rw-r--r--custom_fixers/fix_alt_unicode.py12
-rw-r--r--doc/_static/bookcover.pngbin31844 -> 29597 bytes
-rw-r--r--doc/_static/pocoo.pngbin2191 -> 2003 bytes
-rw-r--r--doc/_static/sphinx.pngbin42490 -> 36665 bytes
-rw-r--r--doc/_templates/index.html13
-rw-r--r--doc/_templates/indexsidebar.html4
-rw-r--r--doc/_themes/sphinx13/static/bodybg.pngbin602 -> 513 bytes
-rw-r--r--doc/_themes/sphinx13/static/footerbg.pngbin313 -> 220 bytes
-rw-r--r--doc/_themes/sphinx13/static/headerbg.pngbin344 -> 230 bytes
-rw-r--r--doc/_themes/sphinx13/static/relbg.pngbin332 -> 223 bytes
-rw-r--r--doc/_themes/sphinx13/static/sphinxheader.pngbin16255 -> 12567 bytes
-rw-r--r--doc/authors.rst9
-rw-r--r--doc/builders.rst9
-rw-r--r--doc/changes.rst2
-rw-r--r--doc/conf.py3
-rw-r--r--doc/config.rst223
-rw-r--r--doc/contents.rst1
-rw-r--r--doc/develop.rst4
-rw-r--r--doc/devguide.rst50
-rw-r--r--doc/domains.rst117
-rw-r--r--doc/ext/autodoc.rst39
-rw-r--r--doc/ext/autosummary.rst22
-rw-r--r--doc/ext/doctest.rst8
-rw-r--r--doc/ext/example_google.py223
-rw-r--r--doc/ext/example_google.rst15
-rw-r--r--doc/ext/example_numpy.py272
-rw-r--r--doc/ext/example_numpy.rst15
-rw-r--r--doc/ext/intersphinx.rst20
-rw-r--r--doc/ext/linkcode.rst3
-rw-r--r--doc/ext/math.rst6
-rw-r--r--doc/ext/napoleon.rst380
-rw-r--r--doc/ext/oldcmarkup.rst35
-rw-r--r--doc/ext/todo.rst9
-rw-r--r--doc/ext/viewcode.rst23
-rw-r--r--doc/extdev/appapi.rst87
-rw-r--r--doc/extdev/index.rst22
-rw-r--r--doc/extdev/tutorial.rst4
-rw-r--r--doc/extensions.rst2
-rw-r--r--doc/faq.rst25
-rw-r--r--doc/glossary.rst16
-rw-r--r--doc/install.rst6
-rw-r--r--doc/intl.rst13
-rw-r--r--doc/intro.rst4
-rw-r--r--doc/invocation.rst155
-rw-r--r--doc/man/sphinx-build.rst6
-rw-r--r--doc/markup/code.rst106
-rw-r--r--doc/markup/inline.rst82
-rw-r--r--doc/markup/misc.rst18
-rw-r--r--doc/markup/para.rst14
-rw-r--r--doc/more.pngbin1502 -> 1473 bytes
-rw-r--r--doc/pythonorg.pngbin187195 -> 153185 bytes
-rw-r--r--doc/rest.rst7
-rw-r--r--doc/templating.rst18
-rw-r--r--doc/themes/agogo.pngbin38724 -> 29278 bytes
-rw-r--r--doc/themes/bizstyle.pngbin0 -> 36234 bytes
-rw-r--r--doc/themes/default.pngbin57108 -> 43969 bytes
-rw-r--r--doc/themes/fullsize/agogo.pngbin75005 -> 61906 bytes
-rw-r--r--doc/themes/fullsize/bizstyle.pngbin0 -> 103961 bytes
-rw-r--r--doc/themes/fullsize/default.pngbin96831 -> 78947 bytes
-rw-r--r--doc/themes/fullsize/haiku.pngbin104662 -> 88689 bytes
-rw-r--r--doc/themes/fullsize/nature.pngbin44469 -> 36087 bytes
-rw-r--r--doc/themes/fullsize/pyramid.pngbin131965 -> 107322 bytes
-rw-r--r--doc/themes/fullsize/scrolls.pngbin121464 -> 97121 bytes
-rw-r--r--doc/themes/fullsize/sphinxdoc.pngbin99682 -> 91063 bytes
-rw-r--r--doc/themes/fullsize/traditional.pngbin108985 -> 99337 bytes
-rw-r--r--doc/themes/haiku.pngbin54252 -> 44727 bytes
-rw-r--r--doc/themes/nature.pngbin42295 -> 32041 bytes
-rw-r--r--doc/themes/pyramid.pngbin49630 -> 40085 bytes
-rw-r--r--doc/themes/scrolls.pngbin44266 -> 31717 bytes
-rw-r--r--doc/themes/sphinxdoc.pngbin42982 -> 33091 bytes
-rw-r--r--doc/themes/traditional.pngbin45762 -> 35367 bytes
-rw-r--r--doc/theming.rst42
-rw-r--r--doc/translation.pngbin40683 -> 14572 bytes
-rw-r--r--doc/tutorial.rst15
-rw-r--r--doc/web/quickstart.rst14
-rw-r--r--setup.py33
-rw-r--r--sphinx/__init__.py23
-rw-r--r--sphinx/__main__.py14
-rw-r--r--sphinx/addnodes.py37
-rw-r--r--sphinx/apidoc.py31
-rw-r--r--sphinx/application.py152
-rw-r--r--sphinx/builders/__init__.py224
-rw-r--r--sphinx/builders/changes.py11
-rw-r--r--sphinx/builders/devhelp.py2
-rw-r--r--sphinx/builders/epub.py26
-rw-r--r--sphinx/builders/gettext.py67
-rw-r--r--sphinx/builders/html.py143
-rw-r--r--sphinx/builders/htmlhelp.py9
-rw-r--r--sphinx/builders/latex.py6
-rw-r--r--sphinx/builders/linkcheck.py22
-rw-r--r--sphinx/builders/manpage.py9
-rw-r--r--sphinx/builders/qthelp.py7
-rw-r--r--sphinx/builders/texinfo.py7
-rw-r--r--sphinx/builders/text.py2
-rw-r--r--sphinx/builders/websupport.py11
-rw-r--r--sphinx/builders/xml.py2
-rw-r--r--sphinx/cmdline.py398
-rw-r--r--sphinx/config.py66
-rw-r--r--sphinx/directives/__init__.py34
-rw-r--r--sphinx/directives/code.py205
-rw-r--r--sphinx/directives/other.py3
-rw-r--r--sphinx/domains/__init__.py31
-rw-r--r--sphinx/domains/c.py74
-rw-r--r--sphinx/domains/cpp.py2299
-rw-r--r--sphinx/domains/javascript.py28
-rw-r--r--sphinx/domains/python.py118
-rw-r--r--sphinx/domains/rst.py25
-rw-r--r--sphinx/domains/std.py220
-rw-r--r--sphinx/environment.py656
-rw-r--r--sphinx/errors.py13
-rw-r--r--sphinx/ext/autodoc.py204
-rw-r--r--sphinx/ext/autosummary/__init__.py15
-rw-r--r--sphinx/ext/autosummary/generate.py18
-rw-r--r--sphinx/ext/coverage.py23
-rw-r--r--sphinx/ext/doctest.py51
-rw-r--r--sphinx/ext/extlinks.py5
-rw-r--r--sphinx/ext/graphviz.py85
-rw-r--r--sphinx/ext/ifconfig.py4
-rw-r--r--sphinx/ext/inheritance_diagram.py20
-rw-r--r--sphinx/ext/intersphinx.py94
-rw-r--r--sphinx/ext/jsmath.py2
-rw-r--r--sphinx/ext/linkcode.py5
-rw-r--r--sphinx/ext/mathjax.py6
-rw-r--r--sphinx/ext/napoleon/__init__.py391
-rw-r--r--sphinx/ext/napoleon/docstring.py860
-rw-r--r--sphinx/ext/napoleon/iterators.py239
-rw-r--r--sphinx/ext/oldcmarkup.py67
-rw-r--r--sphinx/ext/pngmath.py27
-rw-r--r--sphinx/ext/todo.py12
-rw-r--r--sphinx/ext/viewcode.py79
-rw-r--r--sphinx/highlighting.py94
-rw-r--r--sphinx/jinja2glue.py5
-rw-r--r--sphinx/locale/__init__.py20
-rw-r--r--sphinx/locale/sphinx.pot300
-rw-r--r--sphinx/make_mode.py135
-rw-r--r--sphinx/pycode/__init__.py25
-rw-r--r--sphinx/pycode/pgen2/driver.py2
-rw-r--r--sphinx/pycode/pgen2/grammar.py13
-rw-r--r--sphinx/pycode/pgen2/literals.py8
-rw-r--r--sphinx/pycode/pgen2/parse.c89
-rw-r--r--sphinx/pycode/pgen2/pgen.py45
-rwxr-xr-xsphinx/pycode/pgen2/token.py2
-rw-r--r--sphinx/pycode/pgen2/tokenize.py25
-rw-r--r--sphinx/quickstart.py399
-rw-r--r--sphinx/roles.py90
-rw-r--r--sphinx/search/__init__.py87
-rw-r--r--sphinx/search/da.py130
-rw-r--r--sphinx/search/de.py313
-rw-r--r--sphinx/search/en.py17
-rw-r--r--sphinx/search/es.py373
-rw-r--r--sphinx/search/fi.py123
-rw-r--r--sphinx/search/fr.py209
-rw-r--r--sphinx/search/hu.py237
-rw-r--r--sphinx/search/it.py326
-rw-r--r--sphinx/search/ja.py9
-rw-r--r--sphinx/search/nl.py130
-rw-r--r--sphinx/search/no.py212
-rw-r--r--sphinx/search/pt.py272
-rw-r--r--sphinx/search/ro.py32
-rw-r--r--sphinx/search/ru.py261
-rw-r--r--sphinx/search/sv.py150
-rw-r--r--sphinx/search/tr.py32
-rw-r--r--sphinx/setup_command.py16
-rw-r--r--sphinx/texinputs/Makefile28
-rw-r--r--sphinx/texinputs/sphinx.sty6
-rw-r--r--sphinx/themes/agogo/layout.html50
-rw-r--r--sphinx/themes/agogo/static/agogo.css_t16
-rw-r--r--sphinx/themes/basic/domainindex.html2
-rw-r--r--sphinx/themes/basic/layout.html10
-rw-r--r--sphinx/themes/basic/searchbox.html2
-rw-r--r--sphinx/themes/basic/sourcelink.html12
-rw-r--r--sphinx/themes/basic/static/basic.css_t30
-rw-r--r--sphinx/themes/basic/static/doctools.js25
-rw-r--r--sphinx/themes/basic/static/down-pressed.pngbin368 -> 347 bytes
-rw-r--r--sphinx/themes/basic/static/down.pngbin363 -> 347 bytes
-rw-r--r--sphinx/themes/basic/static/file.pngbin392 -> 358 bytes
-rw-r--r--sphinx/themes/basic/static/jquery-1.11.1.js10308
-rw-r--r--sphinx/themes/basic/static/jquery.js6
-rw-r--r--sphinx/themes/basic/static/minus.pngbin199 -> 173 bytes
-rw-r--r--sphinx/themes/basic/static/plus.pngbin199 -> 173 bytes
-rw-r--r--sphinx/themes/basic/static/underscore-1.3.1.js999
-rw-r--r--sphinx/themes/basic/static/up-pressed.pngbin372 -> 345 bytes
-rw-r--r--sphinx/themes/basic/static/up.pngbin363 -> 345 bytes
-rw-r--r--sphinx/themes/basic/static/websupport.js28
-rw-r--r--sphinx/themes/bizstyle/layout.html28
-rw-r--r--sphinx/themes/bizstyle/static/background_b01.pngbin0 -> 87 bytes
-rw-r--r--sphinx/themes/bizstyle/static/bizstyle.css_t487
-rw-r--r--sphinx/themes/bizstyle/static/bizstyle.js_t45
-rw-r--r--sphinx/themes/bizstyle/static/css3-mediaqueries.js1
-rw-r--r--sphinx/themes/bizstyle/static/css3-mediaqueries_src.js1104
-rw-r--r--sphinx/themes/bizstyle/theme.conf9
-rw-r--r--sphinx/themes/default/static/default.css_t11
-rw-r--r--sphinx/themes/epub/static/epub.css16
-rw-r--r--sphinx/themes/haiku/layout.html6
-rw-r--r--sphinx/themes/haiku/static/bg-page.pngbin164 -> 147 bytes
-rw-r--r--sphinx/themes/haiku/static/haiku.css_t2
-rw-r--r--sphinx/themes/nature/static/nature.css_t8
-rw-r--r--sphinx/themes/pyramid/layout.html2
-rw-r--r--sphinx/themes/pyramid/static/dialog-note.pngbin1582 -> 1461 bytes
-rw-r--r--sphinx/themes/pyramid/static/dialog-seealso.pngbin1502 -> 1473 bytes
-rw-r--r--sphinx/themes/pyramid/static/dialog-todo.pngbin1334 -> 1311 bytes
-rw-r--r--sphinx/themes/pyramid/static/dialog-warning.pngbin1391 -> 1365 bytes
-rw-r--r--sphinx/themes/pyramid/static/epub.css6
-rw-r--r--sphinx/themes/pyramid/static/middlebg.pngbin2797 -> 2763 bytes
-rw-r--r--sphinx/themes/pyramid/static/pyramid.css_t9
-rw-r--r--sphinx/themes/scrolls/layout.html4
-rw-r--r--sphinx/themes/scrolls/static/darkmetal.pngbin44361 -> 25389 bytes
-rw-r--r--sphinx/themes/scrolls/static/logo.pngbin11078 -> 8654 bytes
-rw-r--r--sphinx/themes/scrolls/static/metal.pngbin21543 -> 7939 bytes
-rw-r--r--sphinx/themes/scrolls/static/navigation.pngbin217 -> 216 bytes
-rw-r--r--sphinx/themes/scrolls/static/scrolls.css_t13
-rw-r--r--sphinx/themes/scrolls/static/watermark.pngbin107625 -> 53916 bytes
-rw-r--r--sphinx/themes/scrolls/static/watermark_blur.pngbin14470 -> 8970 bytes
-rw-r--r--sphinx/themes/sphinxdoc/static/sphinxdoc.css_t16
-rw-r--r--sphinx/themes/traditional/static/traditional.css_t20
-rw-r--r--sphinx/theming.py20
-rw-r--r--sphinx/transforms.py93
-rw-r--r--sphinx/util/__init__.py89
-rw-r--r--sphinx/util/console.py11
-rw-r--r--sphinx/util/docfields.py12
-rw-r--r--sphinx/util/docstrings.py4
-rw-r--r--sphinx/util/i18n.py89
-rw-r--r--sphinx/util/inspect.py25
-rw-r--r--sphinx/util/jsdump.py10
-rw-r--r--sphinx/util/jsonimpl.py30
-rw-r--r--sphinx/util/matching.py2
-rw-r--r--sphinx/util/nodes.py28
-rw-r--r--sphinx/util/osutil.py37
-rw-r--r--sphinx/util/parallel.py131
-rw-r--r--sphinx/util/png.py5
-rw-r--r--sphinx/util/pycompat.py238
-rw-r--r--sphinx/util/tags.py4
-rw-r--r--sphinx/util/texescape.py168
-rw-r--r--sphinx/versioning.py22
-rw-r--r--sphinx/websupport/__init__.py3
-rw-r--r--sphinx/websupport/search/__init__.py4
-rw-r--r--sphinx/websupport/search/whooshsearch.py4
-rw-r--r--sphinx/websupport/storage/sqlalchemy_db.py2
-rw-r--r--sphinx/writers/html.py143
-rw-r--r--sphinx/writers/latex.py100
-rw-r--r--sphinx/writers/manpage.py27
-rw-r--r--sphinx/writers/texinfo.py40
-rw-r--r--sphinx/writers/text.py20
-rw-r--r--sphinx/writers/xml.py2
-rwxr-xr-xtests/coverage.py88
-rw-r--r--tests/etree13/ElementPath.py12
-rw-r--r--tests/etree13/ElementTree.py27
-rw-r--r--tests/etree13/HTMLTreeBuilder.py7
-rwxr-xr-xtests/path.py23
-rw-r--r--tests/root/autodoc.txt2
-rw-r--r--tests/root/autodoc_missing_imports.py9
-rw-r--r--tests/root/conf.py57
-rw-r--r--tests/root/contents.txt16
-rw-r--r--tests/root/img.pngbin67861 -> 67765 bytes
-rw-r--r--tests/root/includes.txt20
-rw-r--r--tests/root/literal_orig.inc13
-rw-r--r--tests/root/markup.txt29
-rw-r--r--tests/root/metadata.txt4
-rw-r--r--tests/root/objects.txt13
-rw-r--r--tests/root/special/code.py4
-rw-r--r--tests/root/subdir/img.pngbin67861 -> 67765 bytes
-rw-r--r--tests/root/subdir/simg.pngbin67861 -> 67765 bytes
-rw-r--r--tests/root/undecodable.txt3
-rw-r--r--tests/roots/test-api-set-translator/conf.py80
-rw-r--r--tests/roots/test-api-set-translator/index.rst3
-rw-r--r--tests/roots/test-api-set-translator/nonext/conf.py9
-rw-r--r--tests/roots/test-api-set-translator/translator.py6
-rw-r--r--tests/roots/test-autosummary/conf.py4
-rw-r--r--tests/roots/test-autosummary/contents.rst3
-rw-r--r--tests/roots/test-autosummary/sphinx.rst (renamed from tests/root/autosummary.txt)0
-rw-r--r--tests/roots/test-build-text/conf.py2
-rw-r--r--tests/roots/test-build-text/contents.txt8
-rw-r--r--tests/roots/test-build-text/lineblock.txt6
-rw-r--r--tests/roots/test-build-text/maxwidth.txt6
-rw-r--r--tests/roots/test-build-text/nonascii_maxwidth.txt5
-rw-r--r--tests/roots/test-build-text/nonascii_table.txt7
-rw-r--r--tests/roots/test-build-text/nonascii_title.txt2
-rw-r--r--tests/roots/test-build-text/table.txt7
-rw-r--r--tests/roots/test-circular/conf.py (renamed from custom_fixers/__init__.py)0
-rw-r--r--tests/roots/test-circular/contents.rst4
-rw-r--r--tests/roots/test-circular/sub.rst3
-rw-r--r--tests/roots/test-directive-code/caption.rst21
-rw-r--r--tests/roots/test-directive-code/conf.py3
-rw-r--r--tests/roots/test-directive-code/dedent.rst35
-rw-r--r--tests/roots/test-directive-code/dedent_code.rst53
-rw-r--r--tests/roots/test-directive-code/index.rst25
-rw-r--r--tests/roots/test-directive-code/lineno_match.rst17
-rw-r--r--tests/roots/test-directive-code/lineno_start.rst6
-rw-r--r--tests/roots/test-directive-code/linenos.rst6
-rw-r--r--tests/roots/test-directive-code/literal.inc13
-rw-r--r--tests/roots/test-directive-only/conf.py2
-rw-r--r--tests/roots/test-directive-only/contents.rst (renamed from tests/roots/test-only-directive/contents.rst)2
-rw-r--r--tests/roots/test-directive-only/only.rst (renamed from tests/roots/test-only-directive/only.rst)0
-rw-r--r--tests/roots/test-doctest/conf.py5
-rw-r--r--tests/roots/test-doctest/doctest.txt (renamed from tests/root/doctest.txt)4
-rw-r--r--tests/roots/test-docutilsconf/contents.txt30
-rw-r--r--tests/roots/test-ext-viewcode/conf.py24
-rw-r--r--tests/roots/test-ext-viewcode/index.rst34
-rw-r--r--tests/roots/test-ext-viewcode/objects.rst169
-rw-r--r--tests/roots/test-ext-viewcode/spam/__init__.py7
-rw-r--r--tests/roots/test-ext-viewcode/spam/mod1.py15
-rw-r--r--tests/roots/test-ext-viewcode/spam/mod2.py15
-rw-r--r--tests/roots/test-intl/admonitions.po2
-rw-r--r--tests/roots/test-intl/conf.py1
-rw-r--r--tests/roots/test-intl/definition_terms.po2
-rw-r--r--tests/roots/test-intl/docfields.po2
-rw-r--r--tests/roots/test-intl/external_links.po2
-rw-r--r--tests/roots/test-intl/figure_caption.po2
-rw-r--r--tests/roots/test-intl/footnote.po2
-rw-r--r--tests/roots/test-intl/glossary_terms.po2
-rw-r--r--tests/roots/test-intl/glossary_terms_inconsistency.po2
-rw-r--r--tests/roots/test-intl/i18n.pngbin67861 -> 67765 bytes
-rw-r--r--tests/roots/test-intl/index_entries.po2
-rw-r--r--tests/roots/test-intl/literalblock.po2
-rw-r--r--tests/roots/test-intl/refs_inconsistency.po2
-rw-r--r--tests/roots/test-intl/refs_python_domain.txt30
-rw-r--r--tests/roots/test-intl/role_xref.po2
-rw-r--r--tests/roots/test-intl/rubric.po2
-rw-r--r--tests/roots/test-intl/seealso.po2
-rw-r--r--tests/roots/test-intl/sphinx.po2
-rw-r--r--tests/roots/test-intl/subdir/contents.txt4
-rw-r--r--tests/roots/test-intl/versionchange.po2
-rw-r--r--tests/roots/test-intl/warnings.po2
-rw-r--r--tests/roots/test-numbered-circular/conf.py0
-rw-r--r--tests/roots/test-numbered-circular/contents.rst5
-rw-r--r--tests/roots/test-numbered-circular/sub.rst3
-rw-r--r--tests/roots/test-numfig/bar.rst58
-rw-r--r--tests/roots/test-numfig/baz.rst22
-rw-r--r--tests/roots/test-numfig/conf.py3
-rw-r--r--tests/roots/test-numfig/foo.rst71
-rw-r--r--tests/roots/test-numfig/index.rst50
-rw-r--r--tests/roots/test-numfig/rimg.pngbin0 -> 218 bytes
-rw-r--r--tests/roots/test-only-directive/conf.py2
-rw-r--r--tests/roots/test-setup/doc/contents.txt10
-rw-r--r--tests/roots/test-templating/autosummary_templating.txt8
-rw-r--r--tests/roots/test-tocdepth/bar.rst27
-rw-r--r--tests/roots/test-tocdepth/baz.rst5
-rw-r--r--tests/roots/test-tocdepth/conf.py3
-rw-r--r--tests/roots/test-tocdepth/foo.rst26
-rw-r--r--tests/roots/test-tocdepth/index.rst8
-rw-r--r--tests/roots/test-versioning/added.txt (renamed from tests/root/versioning/added.txt)0
-rw-r--r--tests/roots/test-versioning/conf.py3
-rw-r--r--tests/roots/test-versioning/deleted.txt (renamed from tests/root/versioning/deleted.txt)0
-rw-r--r--tests/roots/test-versioning/deleted_end.txt (renamed from tests/root/versioning/deleted_end.txt)0
-rw-r--r--tests/roots/test-versioning/index.txt (renamed from tests/root/versioning/index.txt)0
-rw-r--r--tests/roots/test-versioning/insert.txt (renamed from tests/root/versioning/insert.txt)0
-rw-r--r--tests/roots/test-versioning/insert_beginning.txt (renamed from tests/root/versioning/insert_beginning.txt)0
-rw-r--r--tests/roots/test-versioning/insert_similar.txt (renamed from tests/root/versioning/insert_similar.txt)0
-rw-r--r--tests/roots/test-versioning/modified.txt (renamed from tests/root/versioning/modified.txt)0
-rw-r--r--tests/roots/test-versioning/original.txt (renamed from tests/root/versioning/original.txt)0
-rwxr-xr-xtests/run.py80
-rw-r--r--tests/test_api_translator.py140
-rw-r--r--tests/test_application.py91
-rw-r--r--tests/test_autodoc.py90
-rw-r--r--tests/test_build.py111
-rw-r--r--tests/test_build_gettext.py106
-rw-r--r--tests/test_build_html.py707
-rw-r--r--tests/test_build_latex.py59
-rw-r--r--tests/test_build_texinfo.py33
-rw-r--r--tests/test_build_text.py120
-rw-r--r--tests/test_catalogs.py78
-rw-r--r--tests/test_config.py36
-rw-r--r--tests/test_cpp_domain.py157
-rw-r--r--tests/test_directive_code.py191
-rw-r--r--tests/test_directive_only.py (renamed from tests/test_only_directive.py)13
-rw-r--r--tests/test_docutilsconf.py84
-rw-r--r--tests/test_domain_cpp.py127
-rw-r--r--tests/test_domain_py.py (renamed from tests/test_py_domain.py)16
-rw-r--r--tests/test_domain_rst.py (renamed from tests/test_rst_domain.py)0
-rw-r--r--tests/test_domain_std.py80
-rw-r--r--tests/test_environment.py (renamed from tests/test_env.py)71
-rw-r--r--tests/test_ext_autosummary.py (renamed from tests/test_autosummary.py)70
-rw-r--r--tests/test_ext_coverage.py (renamed from tests/test_coverage.py)4
-rw-r--r--tests/test_ext_doctest.py (renamed from tests/test_doctest.py)14
-rw-r--r--tests/test_ext_intersphinx.py (renamed from tests/test_intersphinx.py)37
-rw-r--r--tests/test_ext_napoleon.py199
-rw-r--r--tests/test_ext_napoleon_docstring.py442
-rw-r--r--tests/test_ext_napoleon_iterators.py346
-rw-r--r--tests/test_ext_viewcode.py44
-rw-r--r--tests/test_footnote.py37
-rw-r--r--tests/test_highlighting.py14
-rw-r--r--tests/test_i18n.py2
-rw-r--r--tests/test_intl.py812
-rw-r--r--tests/test_linkcode.py25
-rw-r--r--tests/test_markup.py33
-rw-r--r--tests/test_metadata.py25
-rw-r--r--tests/test_quickstart.py71
-rw-r--r--tests/test_search.py3
-rw-r--r--tests/test_searchadapters.py24
-rw-r--r--tests/test_setup_command.py9
-rw-r--r--tests/test_templating.py23
-rw-r--r--tests/test_theming.py32
-rw-r--r--tests/test_util_i18n.py163
-rw-r--r--tests/test_util_nodes.py242
-rw-r--r--tests/test_versioning.py37
-rw-r--r--tests/test_websupport.py35
-rw-r--r--tests/util.py207
-rw-r--r--tox.ini41
-rwxr-xr-xutils/check_sources.py83
-rwxr-xr-xutils/convert.py43
-rwxr-xr-xutils/reindent.py29
409 files changed, 29848 insertions, 5761 deletions
diff --git a/.hgignore b/.hgignore
index 1154332f..16d29fcf 100644
--- a/.hgignore
+++ b/.hgignore
@@ -7,6 +7,7 @@
^build/
^dist/
^tests/.coverage
+^tests/build/
^sphinx/pycode/Grammar.*pickle
^Sphinx.egg-info/
^doc/_build/
@@ -18,5 +19,3 @@
~$
^utils/.*3\.py$
^distribute-
-^tests/root/_build/*
-^tests/root/generated/*
diff --git a/AUTHORS b/AUTHORS
index 2a9dbbac..382b8c3f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,6 +3,15 @@ Sphinx is written and maintained by Georg Brandl <georg@python.org>.
Substantial parts of the templates were written by Armin Ronacher
<armin.ronacher@active-4.com>.
+Other co-maintainers:
+
+* Takayuki Shimizukawa <shimizukawa@gmail.com>
+* Daniel Neuhäuser <@DasIch>
+* Jon Waltman <@jonwaltman>
+* Rob Ruana <@RelentlessIdiot>
+* Robert Lehmann <@lehmannro>
+* Roland Meister <@rolmei>
+
Other contributors, listed alphabetically, are:
* Andi Albrecht -- agogo theme
@@ -17,6 +26,7 @@ Other contributors, listed alphabetically, are:
* Horst Gutmann -- internationalization support
* Martin Hans -- autodoc improvements
* Doug Hellmann -- graphviz improvements
+* Takeshi Komiya -- numref feature
* Dave Kuhlman -- original LaTeX writer
* Blaise Laflamme -- pyramid theme
* Thomas Lamb -- linkcheck builder
@@ -32,6 +42,8 @@ Other contributors, listed alphabetically, are:
* Christopher Perkins -- autosummary integration
* Benjamin Peterson -- unittests
* T. Powers -- HTML output improvements
+* Jeppe Pihl -- literalinclude improvements
+* Rob Ruana -- napoleon extension
* Stefan Seefeld -- toctree improvements
* Shibukawa Yoshiki -- pluggable search API and Japanese search
* Antonio Valentino -- qthelp builder
diff --git a/CHANGES b/CHANGES
index 24bef95f..66d4690a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,28 +1,183 @@
-Release 1.2.4 (in development)
-==============================
+Release 1.3 (in development)
+============================
+
+Incompatible changes
+--------------------
+
+* Dropped support for Python 2.5, 3.1 and 3.2.
+* Dropped support for docutils versions up to 0.9.
+* Removed the ``sphinx.ext.oldcmarkup`` extension.
+* The deprecated config values ``exclude_trees``, ``exclude_dirnames`` and
+ ``unused_docs`` have been removed.
+* A new node, ``sphinx.addnodes.literal_strong``, has been added, for text that
+ should appear literally (i.e. no smart quotes) in strong font. Custom writers
+ will have to be adapted to handle this node.
+* PR#269, #1476: replace ``<tt>`` tag by ``<code>``. User customized stylesheets
+ should be updated If the css contain some styles for ``tt>`` tag.
+ Thanks to Takeshi Komiya.
+* #1543: `templates_path` is automatically added to
+ `exclude_patterns` to avoid reading autosummary rst templates in the
+ templates directory.
+* Custom domains should implement the new `Domain.resolve_any_xref`
+ method to make the `any` role work properly.
+* gettext builder: gettext doesn't emit uuid information to generated pot files
+ by default. Please set ``True`` to `gettext_uuid` to emit uuid information.
+ Additionally, if the ``python-levenshtein`` 3rd-party package is installed,
+ it will improve the calculation time.
+* gettext builder: disable extracting/apply 'index' node by default. Please set
+ 'index' to :confval:`gettext_enables` to enable extracting index entries.
+* PR#307: Add frame to code-block in LaTeX. Thanks to Takeshi Komiya.
Features added
--------------
+* Add support for Python 3.4.
+* Add support for docutils 0.12
+* Added ``sphinx.ext.napoleon`` extension for NumPy and Google style docstring
+ support.
+* Added support for parallel reading (parsing) of source files with the
+ `sphinx-build -j` option. Third-party extensions will need to be checked for
+ compatibility and may need to be adapted if they store information in the
+ build environment object. See `env-merge-info`.
+* Added the `any` role that can be used to find a cross-reference of
+ *any* type in *any* domain. Custom domains should implement the new
+ `Domain.resolve_any_xref` method to make this work properly.
* Exception logs now contain the last 10 messages emitted by Sphinx.
+* Added support for extension versions (a string returned by ``setup()``, these
+ can be shown in the traceback log files). Version requirements for extensions
+ can be specified in projects using the new `needs_extensions` config
+ value.
+* Changing the default role within a document with the :dudir:`default-role`
+ directive is now supported.
+* PR#214: Added stemming support for 14 languages, so that the built-in document
+ search can now handle these. Thanks to Shibukawa Yoshiki.
+* PR#296, PR#303, #76: numfig feature: Assign numbers to figures, tables and
+ code-blocks. This feature is configured with `numfig`, `numfig_secnum_depth`
+ and `numfig_prefix`. Also `numref` role is available. Thanks to Takeshi
+ Komiya.
+* PR#202: Allow "." and "~" prefixed references in ``:param:`` doc fields
+ for Python.
+* PR#184: Add `autodoc_mock_imports`, allowing to mock imports of
+ external modules that need not be present when autodocumenting.
+* #925: Allow list-typed config values to be provided on the command line,
+ like ``-D key=val1,val2``.
+* #668: Allow line numbering of `code-block` and `literalinclude` directives
+ to start at an arbitrary line number, with a new ``lineno-start`` option.
+* PR#172, PR#266: The `code-block` and `literalinclude`
+ directives now can have a ``caption`` option that shows a filename before the
+ code in the output. Thanks to Nasimul Haque, Takeshi Komiya.
+* Prompt for the document language in sphinx-quickstart.
+* PR#217: Added config values to suppress UUID and location information in
+ generated gettext catalogs.
+* PR#236, #1456: apidoc: Add a -M option to put module documentation before
+ submodule documentation. Thanks to Wes Turner and Luc Saffre.
+* #1434: Provide non-minified JS files for jquery.js and underscore.js to
+ clarify the source of the minified files.
+* PR#252, #1291: Windows color console support. Thanks to meu31.
+* PR#255: When generating latex references, also insert latex target/anchor
+ for the ids defined on the node. Thanks to Olivier Heurtier.
+* PR#229: Allow registration of other translators. Thanks to Russell Sim.
+* Add app.set_translator() API to register or override a Docutils translator
+ class like `html_translator_class`.
+* PR#267, #1134: add 'diff' parameter to literalinclude. Thanks to Richard Wall
+ and WAKAYAMA shirou.
+* PR#272: Added 'bizstyle' theme. Thanks to Shoji KUMAGAI.
+* Automatically compile ``*.mo`` files from ``*.po`` files when
+ `gettext_auto_build` is True (default) and ``*.po`` is newer than
+ ``*.mo`` file.
+* #623: `sphinx.ext.viewcode` supports imported function/class aliases.
+* PR#275: `sphinx.ext.intersphinx` supports multiple target for the
+ inventory. Thanks to Brigitta Sipocz.
+* PR#261: Added the `env-before-read-docs` event that can be connected to modify
+ the order of documents before they are read by the environment.
+* #1284: Program options documented with :rst:dir:`option` can now start with
+ ``+``.
+* PR#291: The caption of :rst:dir:`code-block` is recognised as a title of ref
+ target. Thanks to Takeshi Komiya.
+* PR#298: Add new API: :meth:`~sphinx.application.Sphinx.add_latex_package`.
+ Thanks to Takeshi Komiya.
+* #1344: add :confval:`gettext_enables` to enable extracting 'index' to gettext
+ catalog output / applying translation catalog to generated documentation.
+* PR#301, #1583: Allow the line numbering of the directive `literalinclude` to
+ match that of the included file, using a new ``lineno-match`` option. Thanks
+ to Jeppe Pihl.
+* PR#299: add various options to sphinx-quickstart. Quiet mode option
+ ``--quiet`` will skips wizard mode. Thanks to WAKAYAMA shirou.
Bugs fixed
----------
-* Now sphinx.ext.autodoc work with python-2.5 again.
+* #1438: Updated jQuery version from 1.8.3 to 1.11.1.
+* #1568: Fix a crash when a "centered" directive contains a reference.
* #1563: :meth:`~sphinx.application.Sphinx.add_search_language` raises
AssertionError for correct type of argument. Thanks to rikoman.
-* #1568: fix a crash when a "centered" directive contains a reference.
-* PR#288, #1512: env.record_dependency crashes on non-ASCII directories that
- relates to dependency files management like :rst:dir:`include` or
- :rst:dir:`csv-table`. Thanks to Takeshi Komiya.
-* PR#285: Test for subclasses of docutils node types when screening
- searchindex. Thanks to Nathan Goldbaum.
-* #1576: Special toctree entry "self" located after another entry that also has
- a toctree was replaced with wrong title and link.
+* #1174: Fix smart quotes being applied inside roles like :rst:role:`program` or
+ `makevar`.
+* PR#235: comment db schema of websupport lacked a length of the node_id field.
+ Thanks to solos.
+* #1466,PR#241: Fix failure of the cpp domain parser to parse C+11
+ "variadic templates" declarations. Thanks to Victor Zverovich.
+* #1459,PR#244: Fix default mathjax js path point to ``http://`` that cause
+ mixed-content error on HTTPS server. Thanks to sbrandtb and robo9k.
+* PR#157: autodoc remove spurious signatures from @property decorated
+ attributes. Thanks to David Ham.
+* PR#159: Add coverage targets to quickstart generated Makefile and make.bat.
+ Thanks to Matthias Troffaes.
+* #1251: When specifying toctree :numbered: option and :tocdepth: metadata,
+ sub section number that is larger depth than ``:tocdepth:`` is shrunk.
+* PR#260: Encode underscore in citation labels for latex export. Thanks to
+ Lennart Fricke.
+* PR#264: Fix could not resolve xref for figure node with :name: option.
+ Thanks to Takeshi Komiya.
+* PR#265: Fix could not capture caption of graphviz node by xref. Thanks to
+ Takeshi Komiya.
+* PR#263, #1013, #1103: Rewrite of C++ domain. Thanks to Jakob Lykke Andersen.
+
+ * Hyperlinks to all found nested names and template arguments (#1103).
+ * Support for function types everywhere, e.g., in
+ std::function<bool(int, int)> (#1013).
+ * Support for virtual functions.
+ * Changed interpretation of function arguments to following standard
+ prototype declarations, i.e., void f(arg) means that arg is the type of the
+ argument, instead of it being the name.
+ * Updated tests.
+ * Updated documentation with elaborate description of what declarations are
+ supported and how the namespace declarations influence declaration and
+ cross-reference lookup.
+ * Index names may be different now. Elements are indexed by their fully
+ qualified name. It should be rather easy to change this behaviour and
+ potentially index by namespaces/classes as well.
+
+* PR#258, #939: Add dedent option for `code-block` and
+ `literalinclude`. Thanks to Zafar Siddiqui.
+* PR#268: Fix numbering section does not work at singlehtml mode. It still
+ ad-hoc fix because there is a issue that section IDs are conflicted.
+ Thanks to Takeshi Komiya.
+* PR#273, #1536: Fix RuntimeError with numbered circular toctree. Thanks to
+ Takeshi Komiya.
+* PR#274: Set its URL as a default title value if URL appears in toctree.
+ Thanks to Takeshi Komiya.
+* PR#276, #1381: `rfc` and `pep` roles support custom link
+ text. Thanks to Takeshi Komiya.
+* PR#277, #1513: highlights for function pointers in argument list of
+ `c:function`. Thanks to Takeshi Komiya.
+* PR#278: Fix section entries were shown twice if toctree has been put under
+ only directive. Thanks to Takeshi Komiya.
+* #1547: pgen2 tokenizer doesn't recognize ``...`` literal (Ellipsis for py3).
+* PR#294: On LaTeX builder, wrap float environment on writing literal_block
+ to avoid separation of caption and body. Thanks to Takeshi Komiya.
+* PR#295, #1520: ``make.bat latexpdf`` mechanism to ``cd`` back to the current
+ directory. Thanks to Peter Suter.
+* PR#297, #1571: Add imgpath property to all builders. It make easier to
+ develop builder extensions. Thanks to Takeshi Komiya.
* #1584: Point to master doc in HTML "top" link.
* #1585: Autosummary of modules broken in Sphinx-1.2.3.
+Documentation
+-------------
+
+* Add clarification about the syntax of tags. (:file:`doc/markup/misc.rst`)
+
Release 1.2.3 (released Sep 1, 2014)
====================================
@@ -30,7 +185,7 @@ Release 1.2.3 (released Sep 1, 2014)
Features added
--------------
-* #1518: `sphinx-apidoc` command now have a `--version` option to show version
+* #1518: ``sphinx-apidoc`` command now has a ``--version`` option to show version
information and exit
* New locales: Hebrew, European Portuguese, Vietnamese.
@@ -48,14 +203,14 @@ Bugs fixed
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.
+* #1499: With non-callable ``setup`` in a conf.py, now sphinx-build emits
+ a 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
+ 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.
+ 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
@@ -65,11 +220,11 @@ Bugs fixed
* 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.
+* #1544: ``make text`` generates 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
+ ex. ``python setup.py build_sphinx -b doctest`` return zero even if doctest
failed.
Release 1.2.2 (released Mar 2, 2014)
@@ -78,7 +233,7 @@ Release 1.2.2 (released Mar 2, 2014)
Bugs fixed
----------
-* PR#211: When checking for existence of the :confval:`html_logo` file, check
+* PR#211: When checking for existence of the `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.
@@ -96,7 +251,7 @@ Bugs fixed
* #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.
+ interface/behavior for ``item`` argument usage.
Documentation
-------------
@@ -118,7 +273,7 @@ Bugs fixed
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.
+* #1319: Do not crash if the `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).
@@ -135,7 +290,7 @@ Bugs fixed
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.
+ `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
@@ -152,14 +307,14 @@ Bugs fixed
* #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`
+* #1198: Allow "image" for the "figwidth" option of the :dudir:`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
+* #1345: Fix two bugs with `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.
@@ -182,8 +337,8 @@ Bugs fixed
* #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`.
+* #1330: Fix `exclude_patterns` behavior with subdirectories in the
+ `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.
@@ -215,7 +370,7 @@ 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
+* 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).
@@ -282,7 +437,7 @@ Features added
* 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
+* The new `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
@@ -353,10 +508,10 @@ 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
+* PR#122: the files given in `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
+* PR#124: the node generated by `versionadded`,
+ `versionchanged` and `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
@@ -410,7 +565,7 @@ Features added
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
+ - #1110: A new configuration value `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.
@@ -419,18 +574,18 @@ Features added
* LaTeX builder:
- - PR#115: Add ``'transition'`` item in :confval:`latex_elements` for
+ - PR#115: Add ``'transition'`` item in `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.
+ ``'cmappkg'`` item in `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
+ - The ``'fontpkg'`` item in `latex_elements` now defaults to ``''``
+ when the `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
+ - The `latex_documents`, `texinfo_documents`, and
+ `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
+ Previously, if these values were not set, no output would be generated by
their respective builders.
* Internationalization:
@@ -446,13 +601,13 @@ Features added
- 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
+ - PR#123, #1106: Add `epub_use_index` configuration value. If
+ provided, it will be used instead of `html_use_index` for epub
builder.
- - PR#126: Add :confval:`epub_tocscope` configuration value. The setting
+ - PR#126: Add `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.
+ - PR#112: Add `epub_show_urls` configuration value.
* Extensions:
@@ -471,7 +626,7 @@ Features added
- 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
+ greater effect. A single occurrence 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.
@@ -520,7 +675,7 @@ Bugs fixed
* #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`.
+* #1123: Allow whitespaces in filenames given to `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.
@@ -528,7 +683,7 @@ Bugs fixed
* #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.
+ `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.
@@ -593,7 +748,7 @@ Release 1.1.3 (Mar 10, 2012)
* #860: Do not crash when encountering invalid doctest examples, just
emit a warning.
-* #864: Fix crash with some settings of :confval:`modindex_common_prefix`.
+* #864: Fix crash with some settings of `modindex_common_prefix`.
* #862: Fix handling of ``-D`` and ``-A`` options on Python 3.
@@ -657,7 +812,7 @@ Release 1.1 (Oct 9, 2011)
Incompatible changes
--------------------
-* The :rst:dir:`py:module` directive doesn't output its ``platform`` option
+* The `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.)
@@ -693,7 +848,7 @@ Features added
: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.
+ - #478: Added `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
@@ -704,7 +859,7 @@ Features added
* HTML builder:
- Added ``pyramid`` theme.
- - #559: :confval:`html_add_permalinks` is now a string giving the
+ - #559: `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".
@@ -712,26 +867,26 @@ Features added
* Other builders:
- - #516: Added new value of the :confval:`latex_show_urls` option to
+ - #516: Added new value of the `latex_show_urls` option to
show the URLs in footnotes.
- - #209: Added :confval:`text_newlines` and :confval:`text_sectionchars`
+ - #209: Added `text_newlines` and `text_sectionchars`
config values.
- - Added :confval:`man_show_urls` config value.
+ - Added `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.
+ `linkcheck_timeout` and `linkcheck_workers`.
+ - #521: Added `linkcheck_ignore` config value.
- #28: Support row/colspans in tables in the LaTeX builder.
* Configuration and extensibility:
- - #537: Added :confval:`nitpick_ignore`.
+ - #537: Added `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
+ - #564: Add `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.
@@ -749,12 +904,12 @@ Features added
- 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>``
+ - #553: Added `testcleanup` blocks in the doctest extension.
+ - #594: `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`.
+ - Added `pngmath_add_tooltips`.
- The math extension displaymath directives now support ``name`` in
addition to ``label`` for giving the equation label, for compatibility
with Docutils.
@@ -827,7 +982,7 @@ Release 1.0.8 (Sep 23, 2011)
* #669: Respect the ``noindex`` flag option in py:module directives.
* #675: Fix IndexErrors when including nonexisting lines with
- :rst:dir:`literalinclude`.
+ `literalinclude`.
* #676: Respect custom function/method parameter separator strings.
@@ -910,7 +1065,7 @@ Release 1.0.6 (Jan 04, 2011)
* #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
+* #528: Observe `locale_dirs` when looking for the JS
translations file.
* #574: Add special code for better support of Japanese documents
@@ -931,7 +1086,7 @@ Release 1.0.6 (Jan 04, 2011)
* #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
+* Fix strange reports of line numbers for warnings generated from
autodoc-included docstrings, due to different behavior depending
on docutils version.
@@ -1083,51 +1238,51 @@ Features added
- 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.
+ or the `nitpicky` config value.
- Added ``latexpdf`` target in quickstart Makefile.
* Markup:
- - The :rst:role:`menuselection` and :rst:role:`guilabel` roles now
+ - The `menuselection` and `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 ``tab-width`` option to `literalinclude` directive.
- Added ``titlesonly`` option to :rst:dir:`toctree` directive.
- Added the ``prepend`` and ``append`` options to the
- :rst:dir:`literalinclude` directive.
+ `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
+ - The `ref` role can now also reference tables by caption.
+ - The :dudir:`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
+ - Added `rst_prolog` config value.
+ - Added `html_secnumber_suffix` config value to control
section numbering format.
- - Added :confval:`html_compact_lists` config value to control
+ - Added `html_compact_lists` config value to control
docutils' compact lists feature.
- - The :confval:`html_sidebars` config value can now contain patterns
+ - The `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
+ - `html_static_path` can now contain single file entries.
+ - The new universal config value `exclude_patterns` makes the
+ old ``unused_docs``, ``exclude_trees`` and
+ ``exclude_dirnames`` obsolete.
+ - Added `html_output_encoding` config value.
+ - Added the `latex_docclass` config value and made the
"twoside" documentclass option overridable by "oneside".
- - Added the :confval:`trim_doctest_flags` config value, which is true
+ - Added the `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`
+ - Added `html_show_copyright` config value.
+ - Added `latex_show_pagerefs` and `latex_show_urls`
config values.
- - The behavior of :confval:`html_file_suffix` changed slightly: the
+ - The behavior of `html_file_suffix` changed slightly: the
empty string now means "no suffix" instead of "default suffix", use
``None`` for "default suffix".
@@ -1169,7 +1324,7 @@ Features added
* Extension API:
- Added :event:`html-collect-pages`.
- - Added :confval:`needs_sphinx` config value and
+ - Added `needs_sphinx` config value and
:meth:`~sphinx.application.Sphinx.require_sphinx` application API
method.
- #200: Added :meth:`~sphinx.application.Sphinx.add_stylesheet`
@@ -1181,7 +1336,7 @@ Features added
- 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
+ - Added `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.
@@ -1191,7 +1346,7 @@ Features added
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.
+ `graphviz_output_format` config value.
- Added ``alt`` option to :rst:dir:`graphviz` extension directives.
- Added ``exclude`` argument to :func:`.autodoc.between`.
diff --git a/EXAMPLES b/EXAMPLES
index cc4c4de8..17143e92 100644
--- a/EXAMPLES
+++ b/EXAMPLES
@@ -22,18 +22,19 @@ Documentation using the default theme
* 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
+* 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
+* 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/
+* 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
+* Leo: http://leoeditor.com/
* Lino: http://lino.saffre-rumma.net/
* MeshPy: http://documen.tician.de/meshpy/
* mpmath: http://mpmath.googlecode.com/svn/trunk/doc/build/index.html
@@ -41,13 +42,13 @@ Documentation using the default theme
* OpenGDA: http://www.opengda.org/gdadoc/html/
* openWNS: http://docs.openwns.org/
* Paste: http://pythonpaste.org/script/
-* Paver: http://paver.github.com/paver/
+* Paver: http://paver.github.io/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/
+* PyMQI: http://pythonhosted.org/pymqi/
* PyPubSub: http://pubsub.sourceforge.net/
* pyrticle: http://documen.tician.de/pyrticle/
* Python: http://docs.python.org/
@@ -59,7 +60,7 @@ Documentation using the default theme
* 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/
+* z3c: http://www.ibiblio.org/paulcarduner/z3ctutorial/
Documentation using a customized version of the default theme
@@ -69,16 +70,19 @@ Documentation using a customized version of the default theme
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/
+* Chaco: http://docs.enthought.com/chaco/
* 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
+* 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
+* Kaa: http://api.freevo.org/kaa-base/
* LEPL: http://www.acooke.org/lepl/
-* Mayavi: http://code.enthought.com/projects/mayavi/docs/development/html/mayavi
+* Mayavi: http://docs.enthought.com/mayavi/mayavi/
+* NICOS: http://trac.frm2.tum.de/nicos/doc/nicos-master/index.html
* NOC: http://redmine.nocproject.org/projects/noc
* NumPy: http://docs.scipy.org/doc/numpy/reference/
* OpenCV: http://docs.opencv.org/
@@ -92,7 +96,7 @@ Documentation using a customized version of the default theme
* 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/
+* zc.async: http://pythonhosted.org/zc.async/1.5.0/
Documentation using the sphinxdoc theme
@@ -100,20 +104,16 @@ 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/
+* Matplotlib: http://matplotlib.org/
+* Music21: http://web.mit.edu/music21/doc/index.html
+* NetworkX: http://networkx.github.io/
* 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
+* Python Wild Magic: http://vmlaker.github.io/pythonwildmagic/
* 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/
@@ -125,16 +125,17 @@ 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)
+* libLAS: http://www.liblas.org/ (nature)
* MPipe: http://vmlaker.github.io/mpipe/ (sphinx13)
* pip: http://pip.openplans.org/ (nature)
+* Pyramid web framework:
+ http://docs.pylonsproject.org/projects/pyramid/en/latest/ (pyramid)
* 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)
+* Setuptools: http://pythonhosted.org/setuptools/ (nature)
+* Spring Python: http://docs.spring.io/spring-python/1.2.x/sphinx/html/ (nature)
* sqlparse: http://python-sqlparse.googlecode.com/svn/docs/api/index.html
(agogo)
* Sylli: http://sylli.sourceforge.net/ (nature)
@@ -151,35 +152,42 @@ Documentation using a custom theme/integrated in a site
* 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/
+* Elemental: http://libelemental.org/documentation/dev/index.html
+* 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/
+* Flask-OpenID: http://pythonhosted.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
+* Istihza (Turkish Python documentation project):
+ http://www.istihza.com/py2/icindekiler_python.html
+* Lasso: http://lassoguide.com/
* MathJax: http://docs.mathjax.org/en/latest/
* MirrorBrain: http://mirrorbrain.org/docs/
-* nose: http://somethingaboutorange.com/mrl/projects/nose/
+* MyHDL: http://docs.myhdl.org/en/latest/
+* nose: http://nose.readthedocs.org/en/latest/
* NoTex: https://notex.ch/overview/
-* ObjectListView: http://objectlistview.sourceforge.net/python
+* 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
+* Open Dylan: http://opendylan.org/documentation/ and also provides a
`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/
+* Pylons: http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/
+* PyMOTW: http://pymotw.com/2/
* pypol: http://pypol.altervista.org/ (celery)
-* QGIS: http://qgis.org/
-* qooxdoo: http://manual.qooxdoo.org/current
+* QGIS: http://qgis.org/en/docs/index.html
+* qooxdoo: http://manual.qooxdoo.org/current/
* Roundup: http://www.roundup-tracker.org/
-* Selenium: http://seleniumhq.org/docs/
+* Satchmo: http://docs.satchmoproject.com/en/latest/
+* Selenium: http://docs.seleniumhq.org/docs/
* Self: http://selflanguage.org/
+* Substance D: http://docs.pylonsproject.org/projects/substanced/en/latest/
* Tablib: http://tablib.org/
* SQLAlchemy: http://www.sqlalchemy.org/docs/
* tinyTiM: http://tinytim.sourceforge.net/docs/2.0/
@@ -198,7 +206,8 @@ Homepages and other non-documentation sites
* 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/
+* UC Berkeley Advanced Control Systems course:
+ http://www.me.berkeley.edu/ME233/sp14/
* VOR: http://www.vor-cycling.be/
@@ -224,6 +233,8 @@ Books produced using Sphinx
https://www.varnish-software.com/static/book/
* "Learning Sphinx" (in Japanese):
http://www.oreilly.co.jp/books/9784873116488/
+* "LassoGuide":
+ http://www.lassosoft.com/Lasso-Documentation
Thesis using Sphinx
diff --git a/LICENSE b/LICENSE
index 7aa7620b..c8a79284 100644
--- a/LICENSE
+++ b/LICENSE
@@ -244,3 +244,37 @@ 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 implementation of NumpyDocstring._parse_numpydoc_see_also_section
+was derived from code under the following license:
+
+-------------------------------------------------------------------------------
+
+Copyright (C) 2008 Stefan van der Walt <stefan@mentat.za.net>, Pauli Virtanen <pav@iki.fi>
+
+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 AUTHOR ``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 AUTHOR 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.
+
+-------------------------------------------------------------------------------
diff --git a/MANIFEST.in b/MANIFEST.in
index 5db26b81..4cafcdca 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -19,7 +19,6 @@ 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
diff --git a/Makefile b/Makefile
index 128b2c80..0e4a9ade 100644
--- a/Makefile
+++ b/Makefile
@@ -48,10 +48,10 @@ reindent:
@$(PYTHON) utils/reindent.py -r -n .
endif
-test: build
+test:
@cd tests; $(PYTHON) run.py -d -m '^[tT]est' $(TEST)
-covertest: build
+covertest:
@cd tests; $(PYTHON) run.py -d -m '^[tT]est' --with-coverage \
--cover-package=sphinx $(TEST)
diff --git a/README.rst b/README.rst
index 5963a0ae..ae92a2ce 100644
--- a/README.rst
+++ b/README.rst
@@ -2,6 +2,9 @@
README for Sphinx
=================
+This is the Sphinx documentation generator, see http://sphinx-doc.org/.
+
+
Installing
==========
@@ -17,7 +20,7 @@ Reading the docs
After installing::
cd doc
- sphinx-build . _build/html
+ make html
Then, direct your browser to ``_build/html/index.html``.
@@ -35,8 +38,26 @@ If you want to use a different interpreter, e.g. ``python3``, use::
PYTHON=python3 make test
+Continuous testing runs on drone.io:
+
+.. image:: https://drone.io/bitbucket.org/birkenfeld/sphinx/status.png
+ :target: https://drone.io/bitbucket.org/birkenfeld/sphinx/
+
Contributing
============
-Send wishes, comments, patches, etc. to sphinx-dev@googlegroups.com.
+#. Check for open issues or open a fresh issue to start a discussion around a
+ feature idea or a bug. There are Non Assigned issues:
+ https://bitbucket.org/birkenfeld/sphinx/issues?status=new&status=open&responsible=
+#. If you feel uncomfortable or uncertain about an issue or your changes, feel
+ free to email sphinx-dev@googlegroups.com.
+#. Fork the repository on Bitbucket https://bitbucket.org/birkenfeld/sphinx
+ to start making your changes to the **default** branch for next major
+ version, or **stable** branch for next minor version.
+#. Write a test which shows that the bug was fixed or that the feature works
+ as expected.
+#. Send a pull request and bug the maintainer until it gets merged and
+ published. Make sure to add yourself to AUTHORS
+ <https://bitbucket.org/birkenfeld/sphinx/src/tip/AUTHORS> and the change to
+ CHANGES <https://bitbucket.org/birkenfeld/sphinx/src/tip/CHANGES>.
diff --git a/custom_fixers/fix_alt_unicode.py b/custom_fixers/fix_alt_unicode.py
deleted file mode 100644
index 55175e90..00000000
--- a/custom_fixers/fix_alt_unicode.py
+++ /dev/null
@@ -1,12 +0,0 @@
-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/_static/bookcover.png b/doc/_static/bookcover.png
index 1c91f91f..5b521b67 100644
--- a/doc/_static/bookcover.png
+++ b/doc/_static/bookcover.png
Binary files differ
diff --git a/doc/_static/pocoo.png b/doc/_static/pocoo.png
index eeb18eaf..67663b97 100644
--- a/doc/_static/pocoo.png
+++ b/doc/_static/pocoo.png
Binary files differ
diff --git a/doc/_static/sphinx.png b/doc/_static/sphinx.png
index a4a3e1af..4bd9c753 100644
--- a/doc/_static/sphinx.png
+++ b/doc/_static/sphinx.png
Binary files differ
diff --git a/doc/_templates/index.html b/doc/_templates/index.html
index e6ef9178..2016ea9f 100644
--- a/doc/_templates/index.html
+++ b/doc/_templates/index.html
@@ -34,6 +34,9 @@
<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>
+ <li>{%trans path=pathto('develop')%}<b>Contributed extensions:</b> more than
+ 50 extensions <a href="{{ path }}#extensions">contributed by users</a>
+ in a second repository; most of them installable from PyPI{%endtrans%}</li>
</ul>
<p>{%trans%}
Sphinx uses <a href="http://docutils.sf.net/rst.html">reStructuredText</a>
@@ -97,4 +100,14 @@
powerful built-in search that exceeds the possibilities of Sphinx' JavaScript-based
offline search.{%endtrans%}</p>
+ <h2>{%trans%}Contributor Guide{%endtrans%}</h2>
+
+ <p>{%trans%}If you want to contribute to the project,
+ this part of the documentation is for you.{%endtrans%}</p>
+
+ <ul>
+ <li>{%trans path=pathto("devguide")%}<a href="{{ path }}">Sphinx Developer’s Guide</a></li>{%endtrans%}
+ <li>{%trans path=pathto("authors")%}<a href="{{ path }}">Sphinx Authors</a></li>{%endtrans%}
+ </ul>
+
{% endblock %}
diff --git a/doc/_templates/indexsidebar.html b/doc/_templates/indexsidebar.html
index 4a350ae4..db925c88 100644
--- a/doc/_templates/indexsidebar.html
+++ b/doc/_templates/indexsidebar.html
@@ -3,7 +3,7 @@
{%trans%}project{%endtrans%}</p>
<h3>Download</h3>
-{% if version.endswith('(hg)') %}
+{% if version.endswith('a0') %}
<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
@@ -14,7 +14,7 @@
<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>
+<pre>pip install -U Sphinx</pre>
<p>{%trans%}Latest <a href="http://sphinx-doc.org/latest/">development version docs</a>
are also available.{%endtrans%}</p>
{% endif %}
diff --git a/doc/_themes/sphinx13/static/bodybg.png b/doc/_themes/sphinx13/static/bodybg.png
index 506b6f90..ebe92f66 100644
--- a/doc/_themes/sphinx13/static/bodybg.png
+++ b/doc/_themes/sphinx13/static/bodybg.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/footerbg.png b/doc/_themes/sphinx13/static/footerbg.png
index d1922b44..df783e2c 100644
--- a/doc/_themes/sphinx13/static/footerbg.png
+++ b/doc/_themes/sphinx13/static/footerbg.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/headerbg.png b/doc/_themes/sphinx13/static/headerbg.png
index 6d3e1d5e..22830f99 100644
--- a/doc/_themes/sphinx13/static/headerbg.png
+++ b/doc/_themes/sphinx13/static/headerbg.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/relbg.png b/doc/_themes/sphinx13/static/relbg.png
index 47225851..2006af7d 100644
--- a/doc/_themes/sphinx13/static/relbg.png
+++ b/doc/_themes/sphinx13/static/relbg.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/sphinxheader.png b/doc/_themes/sphinx13/static/sphinxheader.png
index 2b33f09d..12988c3d 100644
--- a/doc/_themes/sphinx13/static/sphinxheader.png
+++ b/doc/_themes/sphinx13/static/sphinxheader.png
Binary files differ
diff --git a/doc/authors.rst b/doc/authors.rst
new file mode 100644
index 00000000..980b33e8
--- /dev/null
+++ b/doc/authors.rst
@@ -0,0 +1,9 @@
+:tocdepth: 2
+
+.. _authors:
+
+Sphinx authors
+==============
+
+.. include:: ../AUTHORS
+
diff --git a/doc/builders.rst b/doc/builders.rst
index 333750e0..3c6f6b98 100644
--- a/doc/builders.rst
+++ b/doc/builders.rst
@@ -153,11 +153,6 @@ for details.
.. 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
@@ -282,8 +277,8 @@ for details.
.. 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
+ :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
diff --git a/doc/changes.rst b/doc/changes.rst
index d5927a72..e4263687 100644
--- a/doc/changes.rst
+++ b/doc/changes.rst
@@ -1,5 +1,7 @@
:tocdepth: 2
+.. default-role:: any
+
.. _changes:
Changes in Sphinx
diff --git a/doc/conf.py b/doc/conf.py
index 9640e2ed..4a6f8f58 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -5,6 +5,7 @@
import re
import sphinx
+
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
'sphinx.ext.autosummary', 'sphinx.ext.extlinks']
@@ -82,7 +83,7 @@ texinfo_documents = [
# 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)}
+intersphinx_mapping = {'python': ('http://docs.python.org/2/', None)}
# Sphinx document translation with sphinx gettext feature uses these settings:
locale_dirs = ['locale/']
diff --git a/doc/config.rst b/doc/config.rst
index 26079e69..e7e2455d 100644
--- a/doc/config.rst
+++ b/doc/config.rst
@@ -45,7 +45,8 @@ Important points to note:
* 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.
+ to change. Only tags set via the ``-t`` command-line option or via
+ ``tags.add('tag')`` can be queried using ``tags.has('tag')``.
Note that the current builder tag is not available in ``conf.py``, as it is
created *after* the builder is initialized.
@@ -115,44 +116,16 @@ General configuration
.. 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.
+ .. versionchanged:: 1.3
+ As these files are not meant to be built, they are automatically added to
+ :confval:`exclude_patterns`.
+
.. confval:: template_bridge
A string with the fully-qualified name of a callable (or simply a class) that
@@ -228,6 +201,19 @@ General configuration
.. versionadded:: 1.0
+.. confval:: needs_extensions
+
+ This value can be a dictionary specifying version requirements for extensions
+ in :confval:`extensions`, e.g. ``needs_extensions =
+ {'sphinxcontrib.something': '1.5'}``. The version strings should be in the
+ form ``major.minor``. Requirements do not have to be specified for all
+ extensions, only for those you want to check.
+
+ This requires that the extension specifies its version to Sphinx (see
+ :ref:`dev-extensions` for how to do that).
+
+ .. versionadded:: 1.3
+
.. confval:: nitpicky
If true, Sphinx will warn about *all* references where the target cannot be
@@ -245,6 +231,30 @@ General configuration
.. versionadded:: 1.1
+.. confval:: numfig
+
+ If true, figures, tables and code-blocks are automatically numbered if they
+ has caption. For now, it works only with the HTML builder. Default is ``False``.
+
+ .. versionadded:: 1.3
+
+.. confval:: numfig_prefix
+
+ A dictionary mapping ``'figure'``, ``'table'`` and ``'code-block'`` to
+ strings that are used for prefix of figure numbers. Default is to use
+ ``'Fig. %s'`` for ``'figure'``, ``'Table %s'`` for ``'table'`` and
+ ``'Listing %s'`` for ``'code-block'``.
+
+ .. versionadded:: 1.3
+
+.. confval:: numfig_secnum_depth
+
+ The scope of figure numbers, that is, the numfig feature numbers figures
+ in which scope. ``0`` means "whole document". ``1`` means "in a section".
+ Sphinx numbers like x.1, x.2, x.3... ``2`` means "in a subsection". Sphinx
+ numbers like x.x.1, x.x.2, x.x.3..., and so on. Default is ``1``.
+
+ .. versionadded:: 1.3
Project information
-------------------
@@ -341,8 +351,8 @@ Project information
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.
+ ``True``. See the extension :mod:`~sphinx.ext.doctest` for more
+ possibilities of including doctests.
.. versionadded:: 1.0
.. versionchanged:: 1.1
@@ -354,7 +364,7 @@ Project information
Options for internationalization
--------------------------------
-These options influence Sphinx' *Native Language Support*. See the
+These options influence Sphinx's *Native Language Support*. See the
documentation on :ref:`intl` for details.
.. confval:: language
@@ -435,6 +445,50 @@ documentation on :ref:`intl` for details.
By default, the document ``markup/code.rst`` ends up in the ``markup`` text
domain. With this option set to ``False``, it is ``markup/code``.
+.. confval:: gettext_uuid
+
+ If true, Sphinx generates uuid information for version tracking in message
+ catalogs. It is used for:
+
+ * Add uid line for each msgids in .pot files.
+ * Calculate similarity between new msgids and previously saved old msgids.
+ This calculation takes a long time.
+
+ If you want to accelerate the calculation, you can use
+ ``python-levenshtein`` 3rd-party package written in C by using
+ :command:`pip install python-levenshtein`.
+
+ The default is ``False``.
+
+ .. versionadded:: 1.3
+
+.. confval:: gettext_location
+
+ If true, Sphinx generates location information for messages in message
+ catalogs.
+
+ The default is ``True``.
+
+ .. versionadded:: 1.3
+
+.. confval:: gettext_auto_build
+
+ If true, Sphinx builds mo file for each translation catalog files.
+
+ The default is ``True``.
+
+ .. versionadded:: 1.3
+
+.. confval:: gettext_enables
+
+ To specify names to enable gettext extracting and translation applying for
+ i18n. You can specify below names:
+
+ :index: index terms
+
+ The default is ``[]``.
+
+ .. versionadded:: 1.3
.. _html-options:
@@ -442,7 +496,7 @@ Options for HTML output
-----------------------
These options influence HTML as well as HTML Help output, and other builders
-that use Sphinx' HTMLWriter class.
+that use Sphinx's HTMLWriter class.
.. confval:: html_theme
@@ -470,14 +524,14 @@ that use Sphinx' HTMLWriter class.
.. 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
+ in Sphinx's :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.
+ The "title" for HTML documentation generated with Sphinx's 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
@@ -513,9 +567,10 @@ that use Sphinx' HTMLWriter class.
.. 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``.
+ :term:`configuration directory`) that is the favicon of the docs. Modern
+ browsers use this as the 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
@@ -557,8 +612,9 @@ that use Sphinx' HTMLWriter class.
.. confval:: html_use_smartypants
- If true, *SmartyPants* will be used to convert quotes and dashes to
- typographically correct entities. Default: ``True``.
+ If true, `SmartyPants <http://daringfireball.net/projects/smartypants/>`_
+ will be used to convert quotes and dashes to typographically correct
+ entities. Default: ``True``.
.. confval:: html_add_permalinks
@@ -600,7 +656,8 @@ that use Sphinx' HTMLWriter class.
Builtin sidebar templates that can be rendered are:
- * **localtoc.html** -- a fine-grained table of contents of the current document
+ * **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
@@ -692,7 +749,7 @@ that use Sphinx' HTMLWriter class.
.. confval:: html_use_opensearch
- If nonempty, an `OpenSearch <http://opensearch.org>` description file will be
+ 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
@@ -717,13 +774,16 @@ that use Sphinx' HTMLWriter class.
.. 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).
+ subclass of Sphinx's :class:`~sphinx.writers.html.HTMLTranslator`, that is
+ used to translate document trees to HTML. Default is ``None`` (use the
+ builtin translator).
+
+ .. seealso:: :meth:`~sphinx.application.Sphinx.set_translator`
.. confval:: html_show_copyright
- If true, "(C) Copyright ..." is shown in the HTML footer. Default is ``True``.
+ If true, "(C) Copyright ..." is shown in the HTML footer. Default is
+ ``True``.
.. versionadded:: 1.0
@@ -766,10 +826,37 @@ that use Sphinx' HTMLWriter class.
Support is present for these languages:
+ * ``da`` -- Danish
+ * ``nl`` -- Dutch
* ``en`` -- English
+ * ``fi`` -- Finnish
+ * ``fr`` -- French
+ * ``de`` -- German
+ * ``hu`` -- Hungarian
+ * ``it`` -- Italian
* ``ja`` -- Japanese
+ * ``no`` -- Norwegian
+ * ``pr`` -- Portuguese
+ * ``ro`` -- Romanian
+ * ``ru`` -- Russian
+ * ``es`` -- Spanish
+ * ``sv`` -- Swedish
+ * ``tr`` -- Turkish
+
+ .. admonition:: Accelerating build speed
+
+ Each language (except Japanese) provides its own stemming algorithm.
+ Sphinx uses a Python implementation by default. You can use a C
+ implementation to accelerate building the index file.
+
+ * `PorterStemmer <https://pypi.python.org/pypi/PorterStemmer>`_ (``en``)
+ * `PyStemmer <https://pypi.python.org/pypi/PyStemmer>`_ (all languages)
.. versionadded:: 1.1
+ With support for ``en`` and ``ja``.
+
+ .. versionchanged:: 1.3
+ Added additional languages.
.. confval:: html_search_options
@@ -791,7 +878,7 @@ that use Sphinx' HTMLWriter class.
.. confval:: html_search_scorer
- The name of a javascript file (relative to the configuration directory) that
+ 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
@@ -900,7 +987,7 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
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
+ the types can be explicitly overwritten if the default entries are not
appropriate. Example::
epub_guide = (('cover', 'cover.html', u'Cover Page'),)
@@ -940,8 +1027,8 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
.. 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
+ its nested toc listing. This allows easier navigation to the top of
+ a chapter, but can be confusing because it mixes entries of different
depth in one list. The default value is ``True``.
.. confval:: epub_tocscope
@@ -1024,11 +1111,11 @@ These options influence LaTeX output.
``'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.
+ "sphinx" package in order to define Sphinx's 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*
+ * *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.
@@ -1135,6 +1222,12 @@ These options influence LaTeX output.
"Rejne". You can also set this to ``''`` to disable fncychap.
``'preamble'``
Additional preamble content, default empty.
+ ``'figure_align'``
+ Latex figure float alignment, default 'htbp' (here, top, bottom, page).
+ Whenever an image doesn't fit into the current page, it will be
+ 'floated' into the next page but may be preceded by any other text.
+ If you don't like this behavior, use 'H' which will disable floating
+ and position figures strictly in the order they appear in the source.
``'footer'``
Additional footer content (before the indices), default empty.
@@ -1167,7 +1260,8 @@ These options influence LaTeX output.
``'\\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:
+ * Keys that are set by other options and therefore should not be overridden
+ are:
``'docclass'``
``'classoptions'``
@@ -1324,7 +1418,7 @@ These options influence Texinfo output.
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*
+ * *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
@@ -1400,7 +1494,6 @@ These options influence Texinfo output.
``'project'``
``'release'``
``'title'``
- ``'direntry'``
.. versionadded:: 1.1
@@ -1434,9 +1527,9 @@ Options for the linkcheck builder
.. 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``.
+ If true, 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
@@ -1446,7 +1539,7 @@ Options for the XML builder
.. confval:: xml_pretty
- If True, pretty-print the XML. Default is ``True``.
+ If true, pretty-print the XML. Default is ``True``.
.. versionadded:: 1.2
diff --git a/doc/contents.rst b/doc/contents.rst
index d3fd3c8e..a51910b8 100644
--- a/doc/contents.rst
+++ b/doc/contents.rst
@@ -26,6 +26,7 @@ Sphinx documentation contents
devguide
changes
examples
+ authors
Indices and tables
diff --git a/doc/develop.rst b/doc/develop.rst
index aad3ff1e..5110aa3a 100644
--- a/doc/develop.rst
+++ b/doc/develop.rst
@@ -55,6 +55,7 @@ This is the current list of contributed extensions in that repository:
- hyphenator: client-side hyphenation of HTML using hyphenator_
- inlinesyntaxhighlight_: inline syntax highlighting
- lassodomain: a domain for documenting Lasso_ source code
+- libreoffice: an extension to include any drawing supported by LibreOffice (e.g. odg, vsd...).
- lilypond: an extension inserting music scripts from Lilypond_ in PNG format.
- makedomain_: a domain for `GNU Make`_
- matlabdomain: document MATLAB_ code.
@@ -68,7 +69,8 @@ This is the current list of contributed extensions in that repository:
- 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.
+- 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
diff --git a/doc/devguide.rst b/doc/devguide.rst
index fccdd3fa..9d85ec0b 100644
--- a/doc/devguide.rst
+++ b/doc/devguide.rst
@@ -54,6 +54,23 @@ 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.
+#. Check for open issues or open a fresh issue to start a discussion around a
+ feature idea or a bug. There are `Non Assigned`_ issues.
+#. If you feel uncomfortable or uncertain about an issue or your changes, feel
+ free to email sphinx-dev@googlegroups.com.
+#. Fork `the repository`_ on Bitbucket to start making your changes to the
+ **default** branch for next major version, or **stable** branch for next
+ minor version.
+#. Write a test which shows that the bug was fixed or that the feature works
+ as expected.
+#. Send a pull request and bug the maintainer until it gets merged and
+ published. Make sure to add yourself to AUTHORS_ and the change to
+ CHANGES_.
+
+.. _`the repository`: https://bitbucket.org/birkenfeld/sphinx
+.. _AUTHORS: https://bitbucket.org/birkenfeld/sphinx/src/tip/AUTHORS
+.. _CHANGES: https://bitbucket.org/birkenfeld/sphinx/src/tip/CHANGES
+.. _Non Assigned: https://bitbucket.org/birkenfeld/sphinx/issues?status=new&status=open&responsible=
Getting Started
~~~~~~~~~~~~~~~
@@ -113,8 +130,13 @@ These are the basic steps needed to start developing on Sphinx.
* 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::
+ * Tests that need a sphinx-build run should be integrated in one of the
+ existing test modules if possible. New tests that to ``@with_app`` and
+ then ``build_all`` for a few assertions are not good since *the test suite
+ should not take more than a minute to run*.
+
+#. 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.'
@@ -191,9 +213,9 @@ 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
+<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.
@@ -235,11 +257,23 @@ Debugging Tips
* 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:`keep_warnings` to ``True`` so
+ warnings will be displayed in the generated output.
-* Set the configuration variable :confval:`nitpicky` to True so that Sphinx
+* 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>`_.
+
+* JavaScript stemming algorithms in `sphinx/search/*.py` (except `en.py`) are
+ generated by this
+ `modified snowballcode generator <https://github.com/shibukawa/snowball>`_.
+ Generated `JSX <http://jsx.github.io/>`_ files are
+ in `this repository <https://github.com/shibukawa/snowball-stemmer.jsx>`_.
+ You can get the resulting JavaScript files using the following command:
+
+ .. code-block:: bash
+
+ $ npm install
+ $ node_modules/.bin/grunt build # -> dest/*.global.js
diff --git a/doc/domains.rst b/doc/domains.rst
index 4b5a9032..4bfc91ec 100644
--- a/doc/domains.rst
+++ b/doc/domains.rst
@@ -127,7 +127,8 @@ declarations:
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).
+ 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.
@@ -157,17 +158,6 @@ declarations:
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
@@ -178,11 +168,23 @@ The following directives are provided for module and class contents:
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.
+ The description normally includes 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 (in any ``py`` directive) optionally be given in a
+ structured form, see :ref:`info-field-lists`.
+
+.. 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:class:: name
.. py:class:: name(parameters)
@@ -374,7 +376,7 @@ a matching identifier is found:
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).
+ value is ``True`` (the default).
.. rst:role:: py:data
@@ -518,23 +520,26 @@ The C++ Domain
The C++ domain (name **cpp**) supports documenting C++ projects.
-The following directives are available:
+The following directives are available. All declarations can start with a visibility statement
+(``public``, ``private`` or ``protected``).
+
+.. rst:directive:: .. cpp:class:: class speicifer
+
+ Describe a class/struct, possibly with specification of inheritance, e.g.,::
+
+ .. cpp:class:: SomeName::SomeClass : public MyBase, MyOtherBase
-.. rst:directive:: .. cpp:class:: signatures
- .. cpp:function:: signatures
- .. cpp:member:: signatures
- .. cpp:type:: signatures
+.. rst:directive:: .. cpp:function:: (member-)function prototype
- Describe a C++ object. Full signature specification is supported -- give the
- signature as you would in the declaration. Here some examples::
+ Describe a function or member function, e.g.,::
.. 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)
+ .. cpp:function:: bool namespaced::theclass::method(T1, T2)
- Describes a method without types.
+ Describes a method with unnamed parameters.
.. cpp:function:: const T &array<T>::operator[]() const
@@ -548,43 +553,41 @@ The following directives are available:
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:: MyClass::MyClass(const MyClass&) = default
- .. cpp:function:: bool namespaced::theclass::method(int arg1, std::string arg2)
+ Describe a copy constructor with default implementation.
- Describes a method with parameters and types.
+.. rst:directive:: .. cpp:member:: variable or member declaration
- .. cpp:function:: bool namespaced::theclass::method(arg1, arg2)
+ Describe a varible or member variable, e.g.,::
- Describes a method without types.
+ .. cpp:member:: std::string theclass::name
- .. cpp:function:: const T &array<T>::operator[]() const
+ .. cpp:member:: std::string theclass::name[N][M]
- Describes the constant indexing operator of a templated array.
+.. rst:directive:: .. cpp:type:: typedef-like declaration
+ .. cpp:type:: name
- .. cpp:function:: operator bool() const
+ Describe a type as in a typedef declaration, or the name of a type with unspecified type, e.g.,::
- Describe a casting operator here.
+ .. cpp:type:: std::vector<int> MyList
- .. cpp:function:: constexpr void foo(std::string &bar[2]) noexcept
+ A typedef-like declaration of a type.
- Describe a constexpr function here.
+ .. cpp:type:: theclass::const_iterator
- .. cpp:member:: std::string theclass::name
+ Declaration of a type alias with unspecified type.
- .. cpp:member:: std::string theclass::name[N][M]
+.. rst:directive:: .. cpp:namespace:: namespace
- .. cpp:type:: theclass::const_iterator
+ Select the current namespace for the following objects. Note that the namespace
+ does not need to correspond to C++ namespaces, but can end in names of classes, e.g.,::
-.. rst:directive:: .. cpp:namespace:: namespace
+ .. cpp:namespace:: Namespace1::Namespace2::SomeClass::AnInnerClass
- Select the current C++ namespace for the following objects.
+ All following objects will be defined as if their name were declared with the namespace
+ prepended. The following cross-references will be search for by both their specified name
+ and with the namespace prepended.
.. _cpp-roles:
@@ -596,12 +599,12 @@ These roles link to the given object types:
cpp:member
cpp:type
- Reference a C++ object. You can give the full signature (and need to, for
+ Reference a C++ object. You can give the full specification (and need to, for
overloaded functions.)
.. note::
- Sphinx' syntax to give references a custom title can interfere with
+ Sphinx's 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``.
@@ -617,6 +620,12 @@ These roles link to the given object types:
specific overload. Currently Sphinx will link to the first overloaded
version of the method / function.
+.. admonition:: Note on Template Delcarations
+
+ The C++ domain currently does not support template classes/functions/aliases/variables
+ (e.g., ``template<typename T> MyClass``), only template instantiations
+ (e.g., ``MyClass<T>``).
+
The Standard Domain
-------------------
@@ -654,9 +663,9 @@ There is a set of directives allowing documenting command-line programs:
.. 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*.
+ 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
diff --git a/doc/ext/autodoc.rst b/doc/ext/autodoc.rst
index 7f646985..844c6368 100644
--- a/doc/ext/autodoc.rst
+++ b/doc/ext/autodoc.rst
@@ -35,6 +35,16 @@ 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.
+If you prefer `NumPy`_ or `Google`_ style docstrings over reStructuredText,
+you can also enable the :mod:`napoleon <sphinx.ext.napoleon>` extension.
+:mod:`napoleon <sphinx.ext.napoleon>` is a preprocessor that converts your
+docstrings to correct reStructuredText before :mod:`autodoc` processes them.
+
+.. _Google:
+ http://google-styleguide.googlecode.com/svn/trunk/pyguide.html#Comments
+.. _NumPy:
+ https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
+
: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,
@@ -204,6 +214,12 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
.. versionadded:: 1.2
+ * Add a list of modules in the :confval:`autodoc_mock_imports` to prevent
+ import errors to halt the building process when some external dependencies
+ are not importable at build time.
+
+ .. versionadded:: 1.3
+
.. rst:directive:: autofunction
autodata
@@ -258,13 +274,14 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
"""Docstring for instance attribute spam."""
.. versionchanged:: 0.6
- :rst:dir:`autodata` and :rst:dir:`autoattribute` can now extract docstrings.
+ :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
+ :rst:dir:`autodata` and :rst:dir:`autoattribute` have an ``annotation``
+ option.
.. note::
@@ -344,6 +361,14 @@ There are also new config values that you can set:
.. versionadded:: 1.1
+.. confval:: autodoc_mock_imports
+
+ This value contains a list of modules to be mocked up. This is useful when
+ some external dependencies are not met at build time and break the building
+ process.
+
+ .. versionadded:: 1.3
+
Docstring preprocessing
-----------------------
@@ -389,8 +414,8 @@ autodoc provides the following additional events:
``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.
+ ``"(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
@@ -421,8 +446,8 @@ member should be included in the documentation by using the following event:
``"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 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
diff --git a/doc/ext/autosummary.rst b/doc/ext/autosummary.rst
index e3de1835..8548fbd5 100644
--- a/doc/ext/autosummary.rst
+++ b/doc/ext/autosummary.rst
@@ -15,15 +15,15 @@ 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.
+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.
+ These files by default contain only the corresponding
+ :mod:`sphinx.ext.autodoc` directive, but can be customized with templates.
.. rst:directive:: autosummary
@@ -62,8 +62,8 @@ The :mod:`sphinx.ext.autosummary` extension does this in two parts:
**Options**
- * If you want the :rst:dir:`autosummary` table to also serve as a :rst:dir:`toctree`
- entry, use the ``toctree`` option, for example::
+ * 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
@@ -78,8 +78,8 @@ The :mod:`sphinx.ext.autosummary` extension does this in two parts:
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::
+ * If you don't want the :rst:dir:`autosummary` to show function signatures in
+ the listing, include the ``nosignatures`` option::
.. autosummary::
:nosignatures:
@@ -112,8 +112,8 @@ 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
+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::
diff --git a/doc/ext/doctest.rst b/doc/ext/doctest.rst
index 554987ee..9b1b4e6d 100644
--- a/doc/ext/doctest.rst
+++ b/doc/ext/doctest.rst
@@ -142,8 +142,8 @@ names.
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. ::
+:rst:dir:`doctest` and the test via :rst:dir:`testcode` and
+:rst:dir:`testoutput` are equivalent. ::
The parrot module
=================
@@ -236,5 +236,5 @@ There are also these config values for customizing the doctest extension:
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.
+ :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/example_google.py b/doc/ext/example_google.py
new file mode 100644
index 00000000..c94dcdf1
--- /dev/null
+++ b/doc/ext/example_google.py
@@ -0,0 +1,223 @@
+# -*- coding: utf-8 -*-
+"""Example Google style docstrings.
+
+This module demonstrates documentation as specified by the `Google Python
+Style Guide`_. Docstrings may extend over multiple lines. Sections are created
+with a section header and a colon followed by a block of indented text.
+
+Example:
+ Examples can be given using either the ``Example`` or ``Examples``
+ sections. Sections support any reStructuredText formatting, including
+ literal blocks::
+
+ $ python example_google.py
+
+Section breaks are created by simply resuming unindented text. Section breaks
+are also implicitly created anytime a new section starts.
+
+Attributes:
+ module_level_variable (int): Module level variables may be documented in
+ either the ``Attributes`` section of the module docstring, or in an
+ inline docstring immediately following the variable.
+
+ Either form is acceptable, but the two should not be mixed. Choose
+ one convention to document module level variables and be consistent
+ with it.
+
+.. _Google Python Style Guide:
+ http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
+
+"""
+
+module_level_variable = 12345
+
+
+def module_level_function(param1, param2=None, *args, **kwargs):
+ """This is an example of a module level function.
+
+ Function parameters should be documented in the ``Args`` section. The name
+ of each parameter is required. The type and description of each parameter
+ is optional, but should be included if not obvious.
+
+ If the parameter itself is optional, it should be noted by adding
+ ", optional" to the type. If \*args or \*\*kwargs are accepted, they
+ should be listed as \*args and \*\*kwargs.
+
+ The format for a parameter is::
+
+ name (type): description
+ The description may span multiple lines. Following
+ lines should be indented.
+
+ Multiple paragraphs are supported in parameter
+ descriptions.
+
+ Args:
+ param1 (int): The first parameter.
+ param2 (str, optional): The second parameter. Defaults to None.
+ Second line of description should be indented.
+ *args: Variable length argument list.
+ **kwargs: Arbitrary keyword arguments.
+
+ Returns:
+ bool: True if successful, False otherwise.
+
+ The return type is optional and may be specified at the beginning of
+ the ``Returns`` section followed by a colon.
+
+ The ``Returns`` section may span multiple lines and paragraphs.
+ Following lines should be indented to match the first line.
+
+ The ``Returns`` section supports any reStructuredText formatting,
+ including literal blocks::
+
+ {
+ 'param1': param1,
+ 'param2': param2
+ }
+
+ Raises:
+ AttributeError: The ``Raises`` section is a list of all exceptions
+ that are relevant to the interface.
+ ValueError: If `param2` is equal to `param1`.
+
+ """
+ if param1 == param2:
+ raise ValueError('param1 may not be equal to param2')
+ return True
+
+
+def example_generator(n):
+ """Generators have a ``Yields`` section instead of a ``Returns`` section.
+
+ Args:
+ n (int): The upper limit of the range to generate, from 0 to `n` - 1
+
+ Yields:
+ int: The next number in the range of 0 to `n` - 1
+
+ Examples:
+ Examples should be written in doctest format, and should illustrate how
+ to use the function.
+
+ >>> print [i for i in example_generator(4)]
+ [0, 1, 2, 3]
+
+ """
+ for i in range(n):
+ yield i
+
+
+class ExampleError(Exception):
+ """Exceptions are documented in the same way as classes.
+
+ The __init__ method may be documented in either the class level
+ docstring, or as a docstring on the __init__ method itself.
+
+ Either form is acceptable, but the two should not be mixed. Choose one
+ convention to document the __init__ method and be consistent with it.
+
+ Note:
+ Do not include the `self` parameter in the ``Args`` section.
+
+ Args:
+ msg (str): Human readable string describing the exception.
+ code (int, optional): Error code, defaults to 2.
+
+ Attributes:
+ msg (str): Human readable string describing the exception.
+ code (int): Exception error code.
+
+ """
+ def __init__(self, msg, code=2):
+ self.msg = msg
+ self.code = code
+
+
+class ExampleClass(object):
+ """The summary line for a class docstring should fit on one line.
+
+ If the class has public attributes, they should be documented here
+ in an ``Attributes`` section and follow the same formatting as a
+ function's ``Args`` section.
+
+ Attributes:
+ attr1 (str): Description of `attr1`.
+ attr2 (list of str): Description of `attr2`.
+ attr3 (int): Description of `attr3`.
+
+ """
+ def __init__(self, param1, param2, param3=0):
+ """Example of docstring on the __init__ method.
+
+ The __init__ method may be documented in either the class level
+ docstring, or as a docstring on the __init__ method itself.
+
+ Either form is acceptable, but the two should not be mixed. Choose one
+ convention to document the __init__ method and be consistent with it.
+
+ Note:
+ Do not include the `self` parameter in the ``Args`` section.
+
+ Args:
+ param1 (str): Description of `param1`.
+ param2 (list of str): Description of `param2`. Multiple
+ lines are supported.
+ param3 (int, optional): Description of `param3`, defaults to 0.
+
+ """
+ self.attr1 = param1
+ self.attr2 = param2
+ self.attr3 = param3
+
+ def example_method(self, param1, param2):
+ """Class methods are similar to regular functions.
+
+ Note:
+ Do not include the `self` parameter in the ``Args`` section.
+
+ Args:
+ param1: The first parameter.
+ param2: The second parameter.
+
+ Returns:
+ True if successful, False otherwise.
+
+ """
+ return True
+
+ def __special__(self):
+ """By default special members with docstrings are included.
+
+ Special members are any methods or attributes that start with and
+ end with a double underscore. Any special member with a docstring
+ will be included in the output.
+
+ This behavior can be disabled by changing the following setting in
+ Sphinx's conf.py::
+
+ napoleon_include_special_with_doc = False
+
+ """
+ pass
+
+ def __special_without_docstring__(self):
+ pass
+
+ def _private(self):
+ """By default private members are not included.
+
+ Private members are any methods or attributes that start with an
+ underscore and are *not* special. By default they are not included
+ in the output.
+
+ This behavior can be changed such that private members *are* included
+ by changing the following setting in Sphinx's conf.py::
+
+ napoleon_include_private_with_doc = True
+
+ """
+ pass
+
+ def _private_without_docstring(self):
+ pass
diff --git a/doc/ext/example_google.rst b/doc/ext/example_google.rst
new file mode 100644
index 00000000..06508082
--- /dev/null
+++ b/doc/ext/example_google.rst
@@ -0,0 +1,15 @@
+:orphan:
+
+.. _example_google:
+
+Example Google Style Python Docstrings
+======================================
+
+.. seealso::
+
+ :ref:`example_numpy`
+
+Download: :download:`example_google.py <example_google.py>`
+
+.. literalinclude:: example_google.py
+ :language: python
diff --git a/doc/ext/example_numpy.py b/doc/ext/example_numpy.py
new file mode 100644
index 00000000..df1d20e6
--- /dev/null
+++ b/doc/ext/example_numpy.py
@@ -0,0 +1,272 @@
+# -*- coding: utf-8 -*-
+"""Example NumPy style docstrings.
+
+This module demonstrates documentation as specified by the `NumPy
+Documentation HOWTO`_. Docstrings may extend over multiple lines. Sections
+are created with a section header followed by an underline of equal length.
+
+Example
+-------
+Examples can be given using either the ``Example`` or ``Examples``
+sections. Sections support any reStructuredText formatting, including
+literal blocks::
+
+ $ python example_numpy.py
+
+
+Section breaks are created with two blank lines. Section breaks are also
+implicitly created anytime a new section starts. Section bodies *may* be
+indented:
+
+Notes
+-----
+ This is an example of an indented section. It's like any other section,
+ but the body is indented to help it stand out from surrounding text.
+
+If a section is indented, then a section break is created simply by
+resuming unindented text.
+
+Attributes
+----------
+module_level_variable : int
+ Module level variables may be documented in either the ``Attributes``
+ section of the module docstring, or in an inline docstring immediately
+ following the variable.
+
+ Either form is acceptable, but the two should not be mixed. Choose
+ one convention to document module level variables and be consistent
+ with it.
+
+.. _NumPy Documentation HOWTO:
+ https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
+
+"""
+
+module_level_variable = 12345
+
+
+def module_level_function(param1, param2=None, *args, **kwargs):
+ """This is an example of a module level function.
+
+ Function parameters should be documented in the ``Parameters`` section.
+ The name of each parameter is required. The type and description of each
+ parameter is optional, but should be included if not obvious.
+
+ If the parameter itself is optional, it should be noted by adding
+ ", optional" to the type. If \*args or \*\*kwargs are accepted, they
+ should be listed as \*args and \*\*kwargs.
+
+ The format for a parameter is::
+
+ name : type
+ description
+
+ The description may span multiple lines. Following lines
+ should be indented to match the first line of the description.
+
+ Multiple paragraphs are supported in parameter
+ descriptions.
+
+ Parameters
+ ----------
+ param1 : int
+ The first parameter.
+ param2 : str, optional
+ The second parameter, defaults to None.
+ *args
+ Variable length argument list.
+ **kwargs
+ Arbitrary keyword arguments.
+
+ Returns
+ -------
+ bool
+ True if successful, False otherwise.
+
+ The return type is not optional. The ``Returns`` section may span
+ multiple lines and paragraphs. Following lines should be indented to
+ match the first line of the description.
+
+ The ``Returns`` section supports any reStructuredText formatting,
+ including literal blocks::
+
+ {
+ 'param1': param1,
+ 'param2': param2
+ }
+
+ Raises
+ ------
+ AttributeError
+ The ``Raises`` section is a list of all exceptions
+ that are relevant to the interface.
+ ValueError
+ If `param2` is equal to `param1`.
+
+ """
+ if param1 == param2:
+ raise ValueError('param1 may not be equal to param2')
+ return True
+
+
+def example_generator(n):
+ """Generators have a ``Yields`` section instead of a ``Returns`` section.
+
+ Parameters
+ ----------
+ n : int
+ The upper limit of the range to generate, from 0 to `n` - 1
+
+ Yields
+ ------
+ int
+ The next number in the range of 0 to `n` - 1
+
+ Examples
+ --------
+ Examples should be written in doctest format, and should illustrate how
+ to use the function.
+
+ >>> print [i for i in example_generator(4)]
+ [0, 1, 2, 3]
+
+ """
+ for i in range(n):
+ yield i
+
+
+class ExampleError(Exception):
+ """Exceptions are documented in the same way as classes.
+
+ The __init__ method may be documented in either the class level
+ docstring, or as a docstring on the __init__ method itself.
+
+ Either form is acceptable, but the two should not be mixed. Choose one
+ convention to document the __init__ method and be consistent with it.
+
+ Note
+ ----
+ Do not include the `self` parameter in the ``Parameters`` section.
+
+ Parameters
+ ----------
+ msg : str
+ Human readable string describing the exception.
+ code : int, optional
+ Error code, defaults to 2.
+
+ Attributes
+ ----------
+ msg : str
+ Human readable string describing the exception.
+ code : int
+ Exception error code.
+
+ """
+ def __init__(self, msg, code=2):
+ self.msg = msg
+ self.code = code
+
+
+class ExampleClass(object):
+ """The summary line for a class docstring should fit on one line.
+
+ If the class has public attributes, they should be documented here
+ in an ``Attributes`` section and follow the same formatting as a
+ function's ``Parameters`` section.
+
+ Attributes
+ ----------
+ attr1 : str
+ Description of `attr1`.
+ attr2 : list of str
+ Description of `attr2`.
+ attr3 : int
+ Description of `attr3`.
+
+ """
+ def __init__(self, param1, param2, param3=0):
+ """Example of docstring on the __init__ method.
+
+ The __init__ method may be documented in either the class level
+ docstring, or as a docstring on the __init__ method itself.
+
+ Either form is acceptable, but the two should not be mixed. Choose one
+ convention to document the __init__ method and be consistent with it.
+
+ Note
+ ----
+ Do not include the `self` parameter in the ``Parameters`` section.
+
+ Parameters
+ ----------
+ param1 : str
+ Description of `param1`.
+ param2 : list of str
+ Description of `param2`. Multiple
+ lines are supported.
+ param3 : int, optional
+ Description of `param3`, defaults to 0.
+
+ """
+ self.attr1 = param1
+ self.attr2 = param2
+ self.attr3 = param3
+
+ def example_method(self, param1, param2):
+ """Class methods are similar to regular functions.
+
+ Note
+ ----
+ Do not include the `self` parameter in the ``Parameters`` section.
+
+ Parameters
+ ----------
+ param1
+ The first parameter.
+ param2
+ The second parameter.
+
+ Returns
+ -------
+ bool
+ True if successful, False otherwise.
+
+ """
+ return True
+
+ def __special__(self):
+ """By default special members with docstrings are included.
+
+ Special members are any methods or attributes that start with and
+ end with a double underscore. Any special member with a docstring
+ will be included in the output.
+
+ This behavior can be disabled by changing the following setting in
+ Sphinx's conf.py::
+
+ napoleon_include_special_with_doc = False
+
+ """
+ pass
+
+ def __special_without_docstring__(self):
+ pass
+
+ def _private(self):
+ """By default private members are not included.
+
+ Private members are any methods or attributes that start with an
+ underscore and are *not* special. By default they are not included
+ in the output.
+
+ This behavior can be changed such that private members *are* included
+ by changing the following setting in Sphinx's conf.py::
+
+ napoleon_include_private_with_doc = True
+
+ """
+ pass
+
+ def _private_without_docstring(self):
+ pass
diff --git a/doc/ext/example_numpy.rst b/doc/ext/example_numpy.rst
new file mode 100644
index 00000000..a3b41613
--- /dev/null
+++ b/doc/ext/example_numpy.rst
@@ -0,0 +1,15 @@
+:orphan:
+
+.. _example_numpy:
+
+Example NumPy Style Python Docstrings
+======================================
+
+.. seealso::
+
+ :ref:`example_google`
+
+Download: :download:`example_numpy.py <example_numpy.py>`
+
+.. literalinclude:: example_numpy.py
+ :language: python
diff --git a/doc/ext/intersphinx.rst b/doc/ext/intersphinx.rst
index 7997472a..94047f8e 100644
--- a/doc/ext/intersphinx.rst
+++ b/doc/ext/intersphinx.rst
@@ -88,7 +88,7 @@ linking:
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
+ inventory is cached in the Sphinx environment, so it must be re-downloaded
whenever you do a full rebuild.
A second example, showing the meaning of a non-``None`` value of the second
@@ -99,8 +99,22 @@ linking:
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.
+ ``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.
+
+ **Multiple target for the inventory**
+
+ .. versionadded:: 1.3
+
+ Alternative files can be specified for each inventory. One can give a
+ tuple for the second inventory tuple item as shown in the following
+ example. This will read the inventory iterating through the (second)
+ tuple items until the first successful fetch. The primary use case for
+ this to specify mirror sites for server downtime of the primary
+ inventory::
+
+ intersphinx_mapping = {'python': ('http://docs.python.org/3.2',
+ (None, 'python-inv.txt'))}
.. confval:: intersphinx_cache_limit
diff --git a/doc/ext/linkcode.rst b/doc/ext/linkcode.rst
index a69a5b1c..05d2cc6d 100644
--- a/doc/ext/linkcode.rst
+++ b/doc/ext/linkcode.rst
@@ -31,7 +31,8 @@ function that returns an URL based on the object.
- ``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)
+ - ``javascript``: ``object`` (name of the object), ``fullname``
+ (name of the item)
Example:
diff --git a/doc/ext/math.rst b/doc/ext/math.rst
index 8b2924c7..4c154610 100644
--- a/doc/ext/math.rst
+++ b/doc/ext/math.rst
@@ -169,8 +169,8 @@ built:
.. confval:: pngmath_add_tooltips
- Default: true. If false, do not add the LaTeX code as an "alt" attribute for
- math images.
+ Default: ``True``. If false, do not add the LaTeX code as an "alt" attribute
+ for math images.
.. versionadded:: 1.1
@@ -197,7 +197,7 @@ Sphinx.
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
+ be available offline, you have to download it and set this value to a
different path.
The path can be absolute or relative; if it is relative, it is relative to
diff --git a/doc/ext/napoleon.rst b/doc/ext/napoleon.rst
new file mode 100644
index 00000000..8d4a9311
--- /dev/null
+++ b/doc/ext/napoleon.rst
@@ -0,0 +1,380 @@
+:mod:`sphinx.ext.napoleon` -- Support for NumPy and Google style docstrings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. module:: sphinx.ext.napoleon
+ :synopsis: Support for NumPy and Google style docstrings
+
+.. moduleauthor:: Rob Ruana
+
+.. versionadded:: 1.3
+
+Napoleon - *Marching toward legible docstrings*
+===============================================
+
+Are you tired of writing docstrings that look like this::
+
+ :param path: The path of the file to wrap
+ :type path: str
+ :param field_storage: The :class:`FileStorage` instance to wrap
+ :type field_storage: FileStorage
+ :param temporary: Whether or not to delete the file when the File
+ instance is destructed
+ :type temporary: bool
+ :returns: A buffered writable file descriptor
+ :rtype: BufferedFileStorage
+
+`ReStructuredText`_ is great, but it creates visually dense, hard to read
+`docstrings`_. Compare the jumble above to the same thing rewritten
+according to the `Google Python Style Guide`_::
+
+ Args:
+ path (str): The path of the file to wrap
+ field_storage (FileStorage): The :class:`FileStorage` instance to wrap
+ temporary (bool): Whether or not to delete the file when the File
+ instance is destructed
+
+ Returns:
+ BufferedFileStorage: A buffered writable file descriptor
+
+Much more legible, no?
+
+Napoleon is a :doc:`../extensions` that enables Sphinx to parse both `NumPy`_
+and `Google`_ style docstrings - the style recommended by `Khan Academy`_.
+
+Napoleon is a pre-processor that parses `NumPy`_ and `Google`_ style
+docstrings and converts them to reStructuredText before Sphinx attempts to
+parse them. This happens in an intermediate step while Sphinx is processing
+the documentation, so it doesn't modify any of the docstrings in your actual
+source code files.
+
+.. _ReStructuredText: http://docutils.sourceforge.net/rst.html
+.. _docstrings: http://www.python.org/dev/peps/pep-0287/
+.. _Google Python Style Guide:
+ http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
+.. _Google:
+ http://google-styleguide.googlecode.com/svn/trunk/pyguide.html#Comments
+.. _NumPy:
+ https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
+.. _Khan Academy:
+ https://sites.google.com/a/khanacademy.org/forge/for-developers/styleguide/python#TOC-Docstrings
+
+Getting Started
+---------------
+
+1. After :doc:`setting up Sphinx <../tutorial>` to build your docs, enable
+ napoleon in the Sphinx `conf.py` file::
+
+ # conf.py
+
+ # Add autodoc and napoleon to the extensions list
+ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
+
+2. Use `sphinx-apidoc` to build your API documentation::
+
+ $ sphinx-apidoc -f -o docs/source projectdir
+
+
+Docstrings
+----------
+
+Napoleon interprets every docstring that :mod:`autodoc <sphinx.ext.autodoc>`
+can find, including docstrings on: ``modules``, ``classes``, ``attributes``,
+``methods``, ``functions``, and ``variables``. Inside each docstring,
+specially formatted `Sections`_ are parsed and converted to
+reStructuredText.
+
+All standard reStructuredText formatting still works as expected.
+
+
+.. _Sections:
+
+Docstring Sections
+------------------
+
+All of the following section headers are supported:
+
+ * ``Args`` *(alias of Parameters)*
+ * ``Arguments`` *(alias of Parameters)*
+ * ``Attributes``
+ * ``Example``
+ * ``Examples``
+ * ``Keyword Args`` *(alias of Keyword Arguments)*
+ * ``Keyword Arguments``
+ * ``Methods``
+ * ``Note``
+ * ``Notes``
+ * ``Other Parameters``
+ * ``Parameters``
+ * ``Return`` *(alias of Returns)*
+ * ``Returns``
+ * ``Raises``
+ * ``References``
+ * ``See Also``
+ * ``Warning``
+ * ``Warnings`` *(alias of Warning)*
+ * ``Warns``
+ * ``Yields``
+
+Google vs NumPy
+---------------
+
+Napoleon supports two styles of docstrings: `Google`_ and `NumPy`_. The
+main difference between the two styles is that Google uses indention to
+separate sections, whereas NumPy uses underlines.
+
+Google style::
+
+ def func(arg1, arg2):
+ """Summary line.
+
+ Extended description of function.
+
+ Args:
+ arg1 (int): Description of arg1
+ arg2 (str): Description of arg2
+
+ Returns:
+ bool: Description of return value
+
+ """
+ return True
+
+NumPy style::
+
+ def func(arg1, arg2):
+ """Summary line.
+
+ Extended description of function.
+
+ Parameters
+ ----------
+ arg1 : int
+ Description of arg1
+ arg2 : str
+ Description of arg2
+
+ Returns
+ -------
+ bool
+ Description of return value
+
+ """
+ return True
+
+NumPy style tends to require more vertical space, whereas Google style
+tends to use more horizontal space. Google style tends to be easier to
+read for short and simple docstrings, whereas NumPy style tends be easier
+to read for long and in-depth docstrings.
+
+The `Khan Academy`_ recommends using Google style.
+
+The choice between styles is largely aesthetic, but the two styles should
+not be mixed. Choose one style for your project and be consistent with it.
+
+.. seealso::
+
+ For complete examples:
+
+ * :ref:`example_google`
+ * :ref:`example_numpy`
+
+
+Configuration
+=============
+
+Listed below are all the settings used by napoleon and their default
+values. These settings can be changed in the Sphinx `conf.py` file. Make
+sure that both "sphinx.ext.autodoc" and "sphinx.ext.napoleon" are
+enabled in `conf.py`::
+
+ # conf.py
+
+ # Add any Sphinx extension module names here, as strings
+ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
+
+ # Napoleon settings
+ napoleon_google_docstring = True
+ napoleon_numpy_docstring = True
+ napoleon_include_private_with_doc = False
+ napoleon_include_special_with_doc = True
+ napoleon_use_admonition_for_examples = False
+ napoleon_use_admonition_for_notes = False
+ napoleon_use_admonition_for_references = False
+ napoleon_use_ivar = False
+ napoleon_use_param = True
+ napoleon_use_rtype = True
+
+.. _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
+
+
+
+.. confval:: napoleon_google_docstring
+
+ True to parse `Google style`_ docstrings. False to disable support
+ for Google style docstrings. *Defaults to True.*
+
+.. confval:: napoleon_numpy_docstring
+
+ True to parse `NumPy style`_ docstrings. False to disable support
+ for NumPy style docstrings. *Defaults to True.*
+
+.. confval:: napoleon_include_private_with_doc
+
+ True to include private members (like ``_membername``) with docstrings
+ in the documentation. False to fall back to Sphinx's default behavior.
+ *Defaults to False.*
+
+ **If True**::
+
+ def _included(self):
+ """
+ This will be included in the docs because it has a docstring
+ """
+ pass
+
+ def _skipped(self):
+ # This will NOT be included in the docs
+ pass
+
+.. confval:: napoleon_include_special_with_doc
+
+ True to include special members (like ``__membername__``) with
+ docstrings in the documentation. False to fall back to Sphinx's
+ default behavior. *Defaults to True.*
+
+ **If True**::
+
+ def __str__(self):
+ """
+ This will be included in the docs because it has a docstring
+ """
+ return unicode(self).encode('utf-8')
+
+ def __unicode__(self):
+ # This will NOT be included in the docs
+ return unicode(self.__class__.__name__)
+
+.. confval:: napoleon_use_admonition_for_examples
+
+ True to use the ``.. admonition::`` directive for the **Example** and
+ **Examples** sections. False to use the ``.. rubric::`` directive
+ instead. One may look better than the other depending on what HTML
+ theme is used. *Defaults to False.*
+
+ This `NumPy style`_ snippet will be converted as follows::
+
+ Example
+ -------
+ This is just a quick example
+
+ **If True**::
+
+ .. admonition:: Example
+
+ This is just a quick example
+
+ **If False**::
+
+ .. rubric:: Example
+
+ This is just a quick example
+
+.. confval:: napoleon_use_admonition_for_notes
+
+ True to use the ``.. admonition::`` directive for **Notes** sections.
+ False to use the ``.. rubric::`` directive instead. *Defaults to False.*
+
+ .. note:: The singular **Note** section will always be converted to a
+ ``.. note::`` directive.
+
+ .. seealso::
+
+ :attr:`napoleon_use_admonition_for_examples`
+
+.. confval:: napoleon_use_admonition_for_references
+
+ True to use the ``.. admonition::`` directive for **References**
+ sections. False to use the ``.. rubric::`` directive instead.
+ *Defaults to False.*
+
+ .. seealso::
+
+ :attr:`napoleon_use_admonition_for_examples`
+
+.. confval:: napoleon_use_ivar
+
+ True to use the ``:ivar:`` role for instance variables. False to use
+ the ``.. attribute::`` directive instead. *Defaults to False.*
+
+ This `NumPy style`_ snippet will be converted as follows::
+
+ Attributes
+ ----------
+ attr1 : int
+ Description of `attr1`
+
+ **If True**::
+
+ :ivar attr1: Description of `attr1`
+ :vartype attr1: int
+
+ **If False**::
+
+ .. attribute:: attr1
+
+ *int*
+
+ Description of `attr1`
+
+.. confval:: napoleon_use_param
+
+ True to use a ``:param:`` role for each function parameter. False to
+ use a single ``:parameters:`` role for all the parameters.
+ *Defaults to True.*
+
+ This `NumPy style`_ snippet will be converted as follows::
+
+ Parameters
+ ----------
+ arg1 : str
+ Description of `arg1`
+ arg2 : int, optional
+ Description of `arg2`, defaults to 0
+
+ **If True**::
+
+ :param arg1: Description of `arg1`
+ :type arg1: str
+ :param arg2: Description of `arg2`, defaults to 0
+ :type arg2: int, optional
+
+ **If False**::
+
+ :parameters: * **arg1** (*str*) --
+ Description of `arg1`
+ * **arg2** (*int, optional*) --
+ Description of `arg2`, defaults to 0
+
+.. confval:: napoleon_use_rtype
+
+ True to use the ``:rtype:`` role for the return type. False to output
+ the return type inline with the description. *Defaults to True.*
+
+ This `NumPy style`_ snippet will be converted as follows::
+
+ Returns
+ -------
+ bool
+ True if successful, False otherwise
+
+ **If True**::
+
+ :returns: True if successful, False otherwise
+ :rtype: bool
+
+ **If False**::
+
+ :returns: *bool* -- True if successful, False otherwise
diff --git a/doc/ext/oldcmarkup.rst b/doc/ext/oldcmarkup.rst
deleted file mode 100644
index 0fdd9fec..00000000
--- a/doc/ext/oldcmarkup.rst
+++ /dev/null
@@ -1,35 +0,0 @@
-: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
index 349d286a..c0d94ba1 100644
--- a/doc/ext/todo.rst
+++ b/doc/ext/todo.rst
@@ -13,18 +13,19 @@ There are two additional directives when using this extension:
Use this directive like, for example, :rst:dir:`note`.
- It will only show up in the output if :confval:`todo_include_todos` is true.
+ 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.
+ 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``.
+ 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
index ba6c8f86..f2b6c928 100644
--- a/doc/ext/viewcode.rst
+++ b/doc/ext/viewcode.rst
@@ -16,4 +16,25 @@ 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.
+add ``'sphinx.ext.viewcode'`` to your :confval:`extensions` value for it to
+work.
+
+There is also an additional config value:
+
+.. confval:: viewcode_import
+
+ If this is ``True``, viewcode extension will follow alias objects that
+ imported from another module such as functions, classes and attributes.
+ As side effects, this option
+ else they produce nothing. The default is ``True``.
+
+ .. warning::
+
+ :confval:`viewcode_import` **imports** the modules to be followed real
+ location. If any modules have side effects on import, these will be
+ executed by ``viewcode`` 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.
+
+ .. versionadded:: 1.3
diff --git a/doc/extdev/appapi.rst b/doc/extdev/appapi.rst
index 0321f5e5..d0d49286 100644
--- a/doc/extdev/appapi.rst
+++ b/doc/extdev/appapi.rst
@@ -82,16 +82,31 @@ package.
Register an event called *name*. This is needed to be able to emit it.
+.. method:: Sphinx.set_translator(name, translator_class)
+
+ Register or override a Docutils translator class. This is used to register
+ a custom output translator or to replace a builtin translator.
+ This allows extensions to use custom translator and define custom
+ nodes for the translator (see :meth:`add_node`).
+
+ This is a API version of :confval:`html_translator_class` for all other
+ builders. Note that if :confval:`html_translator_class` is specified and
+ this API is called for html related builders, API overriding takes
+ precedence.
+
+ .. versionadded:: 1.3
+
.. 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:
+ can be given as keyword arguments: the keyword should be one or more of
+ ``'html'``, ``'latex'``, ``'text'``, ``'man'``, ``'texinfo'`` or any other
+ supported translators, 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
@@ -131,8 +146,8 @@ package.
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:
+ For example, the (already existing) :rst:dir:`literalinclude` directive would
+ be added like this:
.. code-block:: python
@@ -212,10 +227,13 @@ package.
.. 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).
+ 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. If
+ the text should be treated as literal (e.g. no smart quote replacement), but
+ not have typewriter styling, use ``sphinx.addnodes.literal_emphasis`` or
+ ``sphinx.addnodes.literal_strong``.
For the role content, you have the same syntactical possibilities as for
standard Sphinx roles (see :ref:`xref-syntax`).
@@ -229,8 +247,8 @@ package.
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::
+ 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)
@@ -270,6 +288,18 @@ package.
.. versionadded:: 1.0
+.. method:: Sphinx.add_latex_package(packagename, options=None)
+
+ Add *packagename* to the list of packages that LaTeX source code will include.
+ If you provide *options*, it will be taken to `\usepackage` declaration.
+
+ .. code-block:: python
+
+ app.add_latex_package('mypackage') # => \usepackage{mypackage}
+ app.add_latex_package('mypackage', 'foo,bar') # => \usepackage[foo,bar]{mypackage}
+
+ .. versionadded:: 1.3
+
.. method:: Sphinx.add_lexer(alias, lexer)
Use *lexer*, which must be an instance of a Pygments lexer class, to
@@ -419,6 +449,19 @@ handlers to the events. Example:
.. versionadded:: 0.5
+.. event:: env-before-read-docs (app, env, docnames)
+
+ Emitted after the environment has determined the list of all added and
+ changed files and just before it reads them. It allows extension authors to
+ reorder the list of docnames (*inplace*) before processing, or add more
+ docnames that Sphinx did not consider changed (but never add any docnames
+ that are not in ``env.found_docs``).
+
+ You can also remove document names; do this with caution since it will make
+ Sphinx treat changed files as unchanged.
+
+ .. versionadded:: 1.3
+
.. event:: source-read (app, docname, source)
Emitted when a source file has been read. The *source* argument is a list
@@ -462,6 +505,26 @@ handlers to the events. Example:
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-merge-info (env, docnames, other)
+
+ This event is only emitted when parallel reading of documents is enabled. It
+ is emitted once for every subprocess that has read some documents.
+
+ You must handle this event in an extension that stores data in the
+ environment in a custom location. Otherwise the environment in the main
+ process will not be aware of the information stored in the subprocess.
+
+ *other* is the environment object from the subprocess, *env* is the
+ environment from the main process. *docnames* is a set of document names
+ that have been read in the subprocess.
+
+ For a sample of how to deal with this event, look at the standard
+ ``sphinx.ext.todo`` extension. The implementation is often similar to that
+ of :event:`env-purge-doc`, only that information is not removed, but added to
+ the main environment from the other environment.
+
+ .. versionadded:: 1.3
+
.. event:: env-updated (app, env)
Emitted when the :meth:`update` method of the build environment has
diff --git a/doc/extdev/index.rst b/doc/extdev/index.rst
index b76928c0..5144c5f8 100644
--- a/doc/extdev/index.rst
+++ b/doc/extdev/index.rst
@@ -22,6 +22,28 @@ 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.
+Extension metadata
+------------------
+
+.. versionadded:: 1.3
+
+The ``setup()`` function can return a dictionary. This is treated by Sphinx
+as metadata of the extension. Metadata keys currently recognized are:
+
+* ``'version'``: a string that identifies the extension version. It is used for
+ extension version requirement checking (see :confval:`needs_extensions`) and
+ informational purposes. If not given, ``"unknown version"`` is substituted.
+* ``'parallel_read_safe'``: a boolean that specifies if parallel reading of
+ source files can be used when the extension is loaded. It defaults to
+ ``False``, i.e. you have to explicitly specify your extension to be
+ parallel-read-safe after checking that it is.
+* ``'parallel_write_safe'``: a boolean that specifies if parallel writing of
+ output files can be used when the extension is loaded. Since extensions
+ usually don't negatively influence the process, this defaults to ``True``.
+
+APIs used for writing extensions
+--------------------------------
+
.. toctree::
tutorial
diff --git a/doc/extdev/tutorial.rst b/doc/extdev/tutorial.rst
index a03d6e08..e7912406 100644
--- a/doc/extdev/tutorial.rst
+++ b/doc/extdev/tutorial.rst
@@ -45,7 +45,7 @@ extension. These are:
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
+ If you have the application object, the builder is available as
``app.builder``.
**Config**
@@ -162,6 +162,8 @@ new Python module called :file:`todo.py` and add the setup function::
app.connect('doctree-resolved', process_todo_nodes)
app.connect('env-purge-doc', purge_todos)
+ return {'version': '0.1'} # identifies the version of our extension
+
The calls in this function refer to classes and functions not yet written. What
the individual calls do is the following:
diff --git a/doc/extensions.rst b/doc/extensions.rst
index b2adbc1a..b0d98e38 100644
--- a/doc/extensions.rst
+++ b/doc/extensions.rst
@@ -31,7 +31,7 @@ These extensions are built in and can be activated by respective entries in the
ext/extlinks
ext/viewcode
ext/linkcode
- ext/oldcmarkup
+ ext/napoleon
Third-party extensions
diff --git a/doc/faq.rst b/doc/faq.rst
index 7aa35d1f..7a49aed6 100644
--- a/doc/faq.rst
+++ b/doc/faq.rst
@@ -10,9 +10,9 @@ 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.
+ 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
@@ -32,9 +32,9 @@ How do I...
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.
+ 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.
@@ -50,10 +50,11 @@ 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>`_
+ 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
@@ -70,8 +71,8 @@ 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
+ <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
diff --git a/doc/glossary.rst b/doc/glossary.rst
index 8bc393eb..3ef1623d 100644
--- a/doc/glossary.rst
+++ b/doc/glossary.rst
@@ -12,7 +12,7 @@ Glossary
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.
+ See :ref:`builders` for an overview over Sphinx's built-in builders.
configuration directory
The directory containing :file:`conf.py`. By default, this is the same as
@@ -37,11 +37,11 @@ Glossary
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.
+ :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
@@ -70,8 +70,8 @@ Glossary
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.
+ 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.
diff --git a/doc/install.rst b/doc/install.rst
index bf653872..71e37e9c 100644
--- a/doc/install.rst
+++ b/doc/install.rst
@@ -4,7 +4,7 @@ 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.
+(the required version is at least 2.6) and Sphinx.
Sphinx packages are available on the `Python Package Index
<https://pypi.python.org/pypi/Sphinx>`_.
@@ -79,8 +79,8 @@ sidebar and under "Quick Links", click "Windows Installer" to download.
.. 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
+ Currently, Python offers two major versions, 2.x and 3.x. Sphinx 1.3 can run
+ under Python 2.6, 2.7, 3.2, 3.3, with the recommended version being
2.7. This chapter assumes you have installed Python 2.7.
Follow the Windows installer for Python.
diff --git a/doc/intl.rst b/doc/intl.rst
index 3363dc50..c4859d08 100644
--- a/doc/intl.rst
+++ b/doc/intl.rst
@@ -38,9 +38,9 @@ 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*.
+: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
@@ -202,10 +202,13 @@ easy to fetch and push translations.
.. code-block:: bash
- $ tx init --user=<transifex-username> --pass=<transifex-password>
+ $ tx init
Creating .tx folder...
Transifex instance [https://www.transifex.com]:
...
+ Please enter your transifex username: <transifex-username>
+ Password: <transifex-password>
+ ...
Done.
#. Upload pot files to transifex service
@@ -285,7 +288,7 @@ There is `sphinx translation page`_ for Sphinx-1.2 documentation.
.. rubric:: Footnotes
-.. [1] See the `GNU gettext utilites
+.. [1] See the `GNU gettext utilities
<http://www.gnu.org/software/gettext/manual/gettext.html#Introduction>`_
for details on that software suite.
.. [2] Because nobody expects the Spanish Inquisition!
diff --git a/doc/intro.rst b/doc/intro.rst
index 66d0c58d..a796d937 100644
--- a/doc/intro.rst
+++ b/doc/intro.rst
@@ -54,8 +54,8 @@ 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
+Sphinx needs at least **Python 2.6** or **Python 3.2** to run, as well as the
+docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.10
or some (not broken) SVN trunk snapshot. If you like to have source code
highlighting support, you must also install the Pygments_ library.
diff --git a/doc/invocation.rst b/doc/invocation.rst
index 654921be..3316522a 100644
--- a/doc/invocation.rst
+++ b/doc/invocation.rst
@@ -1,5 +1,138 @@
+.. default-role:: any
+
.. _invocation:
+Invocation of sphinx-quickstart
+===============================
+
+The :program:`sphinx-quickstart` script generates a Sphinx documentation set.
+It is called like this::
+
+ $ sphinx-quickstart [options] [projectdir]
+
+where *projectdir* is the Sphinx documentation set directory in which you want
+to place. If you omit *projectdir*, files are generated into current directory
+by default.
+
+The :program:`sphinx-quickstart` script has several options:
+
+.. program:: sphinx-quickstart
+
+.. option:: -q, --quiet
+
+ Quiet mode that will skips interactive wizard to specify options.
+ This option requires `-p`, `-a` and `-v` options.
+
+.. option:: -h, --help, --version
+
+ Display usage summary or Sphinx version.
+
+
+Structure options
+-----------------
+
+.. option:: --sep
+
+ If specified, separate source and build directories.
+
+.. option:: --dot=DOT
+
+ 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.
+
+Project basic options
+---------------------
+
+.. option:: -p PROJECT, --project=PROJECT
+
+ Project name will be set. (see :confval:`project`).
+
+.. option:: -a AUTHOR, --author=AUTHOR
+
+ Author names. (see :confval:`copyright`).
+
+.. option:: -v VERSION
+
+ Version of project. (see :confval:`version`).
+
+.. option:: -r RELEASE, --release=RELEASE
+
+ Release of project. (see :confval:`release`).
+
+.. option:: -l LANGUAGE, --language=LANGUAGE
+
+ Document language. (see :confval:`language`).
+
+.. option:: --suffix=SUFFIX
+
+ Source file suffix. (see :confval:`source_suffix`).
+
+.. option:: --master=MASTER
+
+ Master document name. (see :confval:`master_doc`).
+
+.. option:: --epub
+
+ Use epub.
+
+Extension options
+-----------------
+
+.. option:: --ext-autodoc
+
+ Enable `sphinx.ext.autodoc` extension.
+
+.. option:: --ext-doctest
+
+ Enable `sphinx.ext.doctest` extension.
+
+.. option:: --ext-intersphinx
+
+ Enable `sphinx.ext.intersphinx` extension.
+
+.. option:: --ext-todo
+
+ Enable `sphinx.ext.todo` extension.
+
+.. option:: --ext-coverage
+
+ Enable `sphinx.ext.coverage` extension.
+
+.. option:: --ext-pngmath
+
+ Enable `sphinx.ext.pngmath` extension.
+
+.. option:: --ext-mathjax
+
+ Enable `sphinx.ext.mathjax` extension.
+
+.. option:: --ext-ifconfig
+
+ Enable `sphinx.ext.ifconfig` extension.
+
+.. option:: --ext-viewcode
+
+ Enable `sphinx.ext.viewcode` extension.
+
+
+Makefile and Batchfile creation options
+---------------------------------------
+
+.. option:: --makefile, --no-makefile
+
+ Create (or not create) makefile.
+
+.. option:: --batchfile, --no-batchfile
+
+ Create (or not create) batchfile
+
+
+.. versionadded:: 1.3
+ Add various options for sphinx-quickstart invocation.
+
+
Invocation of sphinx-build
==========================
@@ -83,8 +216,8 @@ The :program:`sphinx-build` script has several options:
.. 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.
+ 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
@@ -124,13 +257,22 @@ The :program:`sphinx-build` script has several options:
.. 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.
+ must be a number, string, list or dictionary value.
+
+ For lists, you can separate elements with a comma like this: ``-D
+ html_theme_path=path1,path2``.
+
+ For dictionary values, 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.
+ .. versionchanged:: 1.3
+ The value can now also be a list value.
+
.. option:: -A name=value
Make the *name* assigned to *value* in the HTML templates.
@@ -145,8 +287,7 @@ The :program:`sphinx-build` script has several options:
.. option:: -N
- Do not emit colored output. (On Windows, colored output is disabled in any
- case.)
+ Do not emit colored output.
.. option:: -v
diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst
index aa1d71c6..13564ff4 100644
--- a/doc/man/sphinx-build.rst
+++ b/doc/man/sphinx-build.rst
@@ -102,12 +102,14 @@ Options
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).
+-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.
+-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.
diff --git a/doc/markup/code.rst b/doc/markup/code.rst
index 957774f0..9a503519 100644
--- a/doc/markup/code.rst
+++ b/doc/markup/code.rst
@@ -36,21 +36,29 @@ installed) and handled in a smart way:
highlighted as Python).
* The highlighting language can be changed using the ``highlight`` directive,
- used as follows::
+ used as follows:
- .. highlight:: c
+ .. rst:directive:: .. highlight:: language
- This language is used until the next ``highlight`` directive is encountered.
+ Example::
+
+ .. 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::
+ directly:
+
+ .. rst:directive:: .. code-block:: language
+
+ Use it like this::
- .. code-block:: ruby
+ .. code-block:: ruby
- Some Ruby code.
+ Some Ruby code.
- The directive's alias name :rst:dir:`sourcecode` works as well.
+ The directive's alias name :rst:dir:`sourcecode` works as well.
* The valid values for the highlighting language are:
@@ -79,14 +87,22 @@ option::
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::
+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.
+The first line number can be selected with the ``lineno-start`` option. If
+present, ``linenos`` is automatically activated as well.
+
+ .. code-block:: ruby
+ :lineno-start: 10
+
+ Some more Ruby code, with line numbering starting at 10.
+
Additionally, an ``emphasize-lines`` option can be given to have Pygments
emphasize particular lines::
@@ -102,16 +118,19 @@ emphasize particular lines::
.. versionchanged:: 1.1
``emphasize-lines`` has been added.
+.. versionchanged:: 1.3
+ ``lineno-start`` 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::
+ 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
@@ -122,10 +141,11 @@ Includes
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::
+ Like :rst:dir:`code-block`, the directive supports the ``linenos`` flag
+ option to switch on line numbers, the ``lineno-start`` option to select the
+ first line number, 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
@@ -164,10 +184,24 @@ Includes
string option, only lines that precede the first lines containing that string
are included.
+ When specifying particular parts of a file to display, it can be useful to
+ display exactly which lines are being presented.
+ This can be done using the ``lineno-match`` option.
+
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.
+
+ If you want to show the diff of the code, you can specify the old
+ file by giving a ``diff`` option::
+
+ .. literalinclude:: example.py
+ :diff: example.py.orig
+
+ This shows the diff between example.py and example.py.orig with unified diff
+ format.
+
.. versionadded:: 0.4.3
The ``encoding`` option.
.. versionadded:: 0.6
@@ -175,6 +209,44 @@ Includes
as well as support for absolute filenames.
.. versionadded:: 1.0
The ``prepend`` and ``append`` options, as well as ``tab-width``.
+ .. versionadded:: 1.3
+ The ``diff`` option.
+ The ``lineno-match`` option.
+
+
+Showing a file name
+^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 1.3
+
+A ``caption`` option can be given to show that name before the code block. For
+example::
+
+ .. code-block:: python
+ :caption: this.py
+
+ print 'Explicit is better than implicit.'
+
+
+:rst:dir:`literalinclude` also supports the ``caption`` option, with the
+additional feature that if you leave the value empty, the shown filename will be
+exactly the one given as an argument.
+
+
+Dedent
+^^^^^^
+
+.. versionadded:: 1.3
+
+A ``dedent`` option can be given to strip a precedence characters from the code
+block. For example::
+
+ .. literalinclude:: example.rb
+ :language: ruby
+ :dedent: 4
+ :lines: 10-15
+
+:rst:dir:`code-block` also supports the ``dedent`` option.
.. rubric:: Footnotes
diff --git a/doc/markup/inline.rst b/doc/markup/inline.rst
index 69dd832f..6f3ebe1c 100644
--- a/doc/markup/inline.rst
+++ b/doc/markup/inline.rst
@@ -12,7 +12,9 @@ They are written as ``:rolename:`content```.
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.
+ :confval:`default_role` config value to set it to a known role -- the
+ :rst:role:`any` role to find anything or the :rst:role:`py:obj` role to find
+ Python objects are very useful for this.
See :ref:`domains` for roles added by domains.
@@ -24,7 +26,7 @@ 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
+to the item named *target* of the type indicated by *role*. The link's text
will be the same as *target*.
There are some additional facilities, however, that make cross-referencing roles
@@ -38,12 +40,57 @@ more versatile:
* 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.
+ refer to ``Queue.Queue.get`` but only display ``get`` as the link text. This
+ does not work with all cross-reference roles, but is domain specific.
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.
+.. _any-role:
+
+Cross-referencing anything
+--------------------------
+
+.. rst:role:: any
+
+ .. versionadded:: 1.3
+
+ This convenience role tries to do its best to find a valid target for its
+ reference text.
+
+ * First, it tries standard cross-reference targets that would be referenced
+ by :rst:role:`doc`, :rst:role:`ref` or :rst:role:`option`.
+
+ Custom objects added to the standard domain by extensions (see
+ :meth:`.add_object_type`) are also searched.
+
+ * Then, it looks for objects (targets) in all loaded domains. It is up to
+ the domains how specific a match must be. For example, in the Python
+ domain a reference of ``:any:`Builder``` would match the
+ ``sphinx.builders.Builder`` class.
+
+ If none or multiple targets are found, a warning will be emitted. In the
+ case of multiple targets, you can change "any" to a specific role.
+
+ This role is a good candidate for setting :confval:`default_role`. If you
+ do, you can write cross-references without a lot of markup overhead. For
+ example, in this Python function documentation ::
+
+ .. function:: install()
+
+ This function installs a `handler` for every signal known by the
+ `signal` module. See the section `about-signals` for more information.
+
+ there could be references to a glossary term (usually ``:term:`handler```), a
+ Python module (usually ``:py:mod:`signal``` or ``:mod:`signal```) and a
+ section (usually ``:ref:`about-signals```).
+
+ The :rst:role:`any` role also works together with the
+ :mod:`~sphinx.ext.intersphinx` extension: when no local cross-reference is
+ found, all object types of intersphinx inventories are also searched.
+
+
Cross-referencing objects
-------------------------
@@ -102,9 +149,10 @@ Cross-referencing arbitrary locations
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.
+ 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
@@ -153,6 +201,24 @@ Referencing downloadable files
suitable link generated to it.
+Cross-referencing figures by figure number
+------------------------------------------
+
+.. versionadded:: 1.3
+
+.. rst:role:: numref
+
+ Link to the specified figures, tables and code-blocks; the standard reST
+ labels are used. When you use this role, it will insert a reference to the
+ figure with link text by its figure number like "Fig. 1.1".
+
+ If an explicit link text is given (like usual: ``:doc:`Image of Sphinx (Fig.
+ #) <my-figure>```), the link caption will be the title of the reference.
+ As a special character, `#` will be replaced to figure number.
+
+ If :confval:`numfig` is ``False``, figures are not numbered.
+ so this role inserts not a reference but labels or link text.
+
Cross-referencing other items of interest
-----------------------------------------
@@ -349,8 +415,8 @@ the standard reST markup for that purpose.
Substitutions
~~~~~~~~~~~~~
-The documentation system provides three substitutions that are defined by default.
-They are set in the build configuration file.
+The documentation system provides three substitutions that are defined by
+default. They are set in the build configuration file.
.. describe:: |release|
diff --git a/doc/markup/misc.rst b/doc/markup/misc.rst
index 5a391d02..fd31480a 100644
--- a/doc/markup/misc.rst
+++ b/doc/markup/misc.rst
@@ -52,16 +52,16 @@ Meta-information markup
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
+ :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.
+ 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
@@ -189,6 +189,14 @@ Including content based on tags
These standard tags are set *after* the configuration file is read, so they
are not available there.
+ All tags must follow the standard Python identifier syntax as set out in
+ the `Identifiers and keywords
+ <https://docs.python.org/reference/lexical_analysis.html#identifiers>`_
+ documentation. That is, a tag expression may only consist of tags that
+ conform to the syntax of Python variables. In ASCII, this consists of the
+ uppercase and lowercase letters ``A`` through ``Z``, the underscore ``_``
+ and, except for the first character, the digits ``0`` through ``9``.
+
.. versionadded:: 0.6
.. versionchanged:: 1.2
Added the name of the builder and the prefixes.
diff --git a/doc/markup/para.rst b/doc/markup/para.rst
index b532bc63..c6a49b15 100644
--- a/doc/markup/para.rst
+++ b/doc/markup/para.rst
@@ -70,12 +70,12 @@ units as well as normal text:
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 :rst:dir:`seealso` directive is typically placed in a section just before
+ any subsections. 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::
+ The content of the :rst:dir:`seealso` directive should be a reST definition
+ list. Example::
.. seealso::
@@ -206,8 +206,8 @@ the definition of the symbol. There is this directive:
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.
+ 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.
diff --git a/doc/more.png b/doc/more.png
index 3eb7b05c..a27a0fcb 100644
--- a/doc/more.png
+++ b/doc/more.png
Binary files differ
diff --git a/doc/pythonorg.png b/doc/pythonorg.png
index 83b54df0..32f0787d 100644
--- a/doc/pythonorg.png
+++ b/doc/pythonorg.png
Binary files differ
diff --git a/doc/rest.rst b/doc/rest.rst
index b5efbf98..c6a4ada0 100644
--- a/doc/rest.rst
+++ b/doc/rest.rst
@@ -312,7 +312,7 @@ Docutils supports the following directives:
- :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
+ Since these are only per-file, better use Sphinx's facilities for setting the
:confval:`default_role`.
Do *not* use the directives :dudir:`sectnum`, :dudir:`header` and
@@ -485,5 +485,6 @@ There are some problems one commonly runs into while authoring reST documents:
.. 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`.
+.. [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
index b9561b69..fde00ef8 100644
--- a/doc/templating.rst
+++ b/doc/templating.rst
@@ -11,8 +11,8 @@ 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?
----------------------------------------------------
+Do I need to use Sphinx's templates to produce HTML?
+----------------------------------------------------
No. You have several other options:
@@ -50,7 +50,7 @@ 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
+Sphinx's *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
@@ -273,7 +273,7 @@ in the future.
.. data:: has_source
True if the reST document sources are copied (if :confval:`html_copy_source`
- is true).
+ is ``True``).
.. data:: last_updated
@@ -333,7 +333,7 @@ in the future.
.. data:: show_source
- True if :confval:`html_show_sourcelink` is true.
+ True if :confval:`html_show_sourcelink` is ``True``.
.. data:: sphinx_version
@@ -372,7 +372,7 @@ are in HTML form), these variables are also available:
.. 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.
+ nonempty if the :confval:`html_copy_source` value is ``True``.
.. data:: toc
@@ -384,14 +384,14 @@ are in HTML form), these variables are also available:
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
+ * ``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_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
+ * ``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
index d29aa45c..453a1f7d 100644
--- a/doc/themes/agogo.png
+++ b/doc/themes/agogo.png
Binary files differ
diff --git a/doc/themes/bizstyle.png b/doc/themes/bizstyle.png
new file mode 100644
index 00000000..4deae9a7
--- /dev/null
+++ b/doc/themes/bizstyle.png
Binary files differ
diff --git a/doc/themes/default.png b/doc/themes/default.png
index 93d8526c..6989ebe9 100644
--- a/doc/themes/default.png
+++ b/doc/themes/default.png
Binary files differ
diff --git a/doc/themes/fullsize/agogo.png b/doc/themes/fullsize/agogo.png
index 93fadfcb..bfdba3a1 100644
--- a/doc/themes/fullsize/agogo.png
+++ b/doc/themes/fullsize/agogo.png
Binary files differ
diff --git a/doc/themes/fullsize/bizstyle.png b/doc/themes/fullsize/bizstyle.png
new file mode 100644
index 00000000..d917e2ff
--- /dev/null
+++ b/doc/themes/fullsize/bizstyle.png
Binary files differ
diff --git a/doc/themes/fullsize/default.png b/doc/themes/fullsize/default.png
index b6af8bc3..9c00f689 100644
--- a/doc/themes/fullsize/default.png
+++ b/doc/themes/fullsize/default.png
Binary files differ
diff --git a/doc/themes/fullsize/haiku.png b/doc/themes/fullsize/haiku.png
index 1590da5d..8d807f4e 100644
--- a/doc/themes/fullsize/haiku.png
+++ b/doc/themes/fullsize/haiku.png
Binary files differ
diff --git a/doc/themes/fullsize/nature.png b/doc/themes/fullsize/nature.png
index d42957e3..02d8743b 100644
--- a/doc/themes/fullsize/nature.png
+++ b/doc/themes/fullsize/nature.png
Binary files differ
diff --git a/doc/themes/fullsize/pyramid.png b/doc/themes/fullsize/pyramid.png
index 429a8b7e..961cb896 100644
--- a/doc/themes/fullsize/pyramid.png
+++ b/doc/themes/fullsize/pyramid.png
Binary files differ
diff --git a/doc/themes/fullsize/scrolls.png b/doc/themes/fullsize/scrolls.png
index 7d46f7ed..4e5c45f2 100644
--- a/doc/themes/fullsize/scrolls.png
+++ b/doc/themes/fullsize/scrolls.png
Binary files differ
diff --git a/doc/themes/fullsize/sphinxdoc.png b/doc/themes/fullsize/sphinxdoc.png
index 722fb900..b7463345 100644
--- a/doc/themes/fullsize/sphinxdoc.png
+++ b/doc/themes/fullsize/sphinxdoc.png
Binary files differ
diff --git a/doc/themes/fullsize/traditional.png b/doc/themes/fullsize/traditional.png
index 103fd3ca..da69efe1 100644
--- a/doc/themes/fullsize/traditional.png
+++ b/doc/themes/fullsize/traditional.png
Binary files differ
diff --git a/doc/themes/haiku.png b/doc/themes/haiku.png
index a8ae8557..78a2570c 100644
--- a/doc/themes/haiku.png
+++ b/doc/themes/haiku.png
Binary files differ
diff --git a/doc/themes/nature.png b/doc/themes/nature.png
index 3d4f587f..cbe773d5 100644
--- a/doc/themes/nature.png
+++ b/doc/themes/nature.png
Binary files differ
diff --git a/doc/themes/pyramid.png b/doc/themes/pyramid.png
index b16095c9..eb13cd5f 100644
--- a/doc/themes/pyramid.png
+++ b/doc/themes/pyramid.png
Binary files differ
diff --git a/doc/themes/scrolls.png b/doc/themes/scrolls.png
index 8073c10e..30ccc8d4 100644
--- a/doc/themes/scrolls.png
+++ b/doc/themes/scrolls.png
Binary files differ
diff --git a/doc/themes/sphinxdoc.png b/doc/themes/sphinxdoc.png
index f4b59ecd..31512d8d 100644
--- a/doc/themes/sphinxdoc.png
+++ b/doc/themes/sphinxdoc.png
Binary files differ
diff --git a/doc/themes/traditional.png b/doc/themes/traditional.png
index 4ad2b5ce..5ff44f86 100644
--- a/doc/themes/traditional.png
+++ b/doc/themes/traditional.png
Binary files differ
diff --git a/doc/theming.rst b/doc/theming.rst
index 73ec9f27..0a2d726d 100644
--- a/doc/theming.rst
+++ b/doc/theming.rst
@@ -102,6 +102,10 @@ Builtin themes
| | |
| *haiku* | *pyramid* |
+--------------------+--------------------+
+| |bizstyle| | |
+| | |
+| *bizstyle* | |
++--------------------+--------------------+
.. |default| image:: themes/default.png
.. |sphinxdoc| image:: themes/sphinxdoc.png
@@ -111,6 +115,7 @@ Builtin themes
.. |nature| image:: themes/nature.png
.. |haiku| image:: themes/haiku.png
.. |pyramid| image:: themes/pyramid.png
+.. |bizstyle| image:: themes/bizstyle.png
Sphinx comes with a selection of themes to choose from.
@@ -122,7 +127,7 @@ These themes are:
these options (which are inherited by the other themes):
- **nosidebar** (true or false): Don't include the sidebar. Defaults to
- false.
+ ``False``.
- **sidebarwidth** (an integer): Width of the sidebar in pixels. (Do not
include ``px`` in the value.) Defaults to 230 pixels.
@@ -132,18 +137,18 @@ These themes are:
options:
- **rightsidebar** (true or false): Put the sidebar on the right side.
- Defaults to false.
+ 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.
+ 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.
+ *Doesn't work with "stickysidebar".* Defaults to ``False``.
- **externalrefs** (true or false): Display external links differently from
- internal links. Defaults to false.
+ 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:
@@ -152,7 +157,7 @@ These themes are:
- **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).
+ 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.
@@ -218,10 +223,10 @@ These themes are:
<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.
+ - **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.
@@ -232,10 +237,20 @@ These themes are:
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** (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.
+ - **footer** (true or false, default ``True``): If this is true, the
+ `footer` block is inserted in the epub output, otherwise it is omitted.
+
+- **bizstyle** -- A simple bluish theme. The following options are supported
+ beyond *nosidebar* and *sidebarwidth*:
+
+ - **rightsidebar** (true or false): Put the sidebar on the right side.
+ Defaults to ``False``.
+
+.. versionadded:: 1.3
+ 'bizstyle' theme.
+
Creating themes
---------------
@@ -318,4 +333,3 @@ is built with the default theme, the output directory will contain a
.. [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
index aa368b67..347e287f 100644
--- a/doc/translation.png
+++ b/doc/translation.png
Binary files differ
diff --git a/doc/tutorial.rst b/doc/tutorial.rst
index cae4c8db..0a12a27a 100644
--- a/doc/tutorial.rst
+++ b/doc/tutorial.rst
@@ -10,6 +10,15 @@ The green arrows designate "more info" links leading to advanced sections about
the described task.
+Install Sphinx
+--------------
+
+Install Sphinx, either from a distribution package or from
+`PyPI <https://pypi.python.org/pypi/Sphinx>`_ with ::
+
+ $ pip install Sphinx
+
+
Setting up the documentation sources
------------------------------------
@@ -138,7 +147,7 @@ an argument to see which targets are available.
Documenting objects
-------------------
-One of Sphinx' main objectives is easy documentation of :dfn:`objects` (in a
+One of Sphinx's 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.
@@ -200,7 +209,7 @@ 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.
+importing a module to find out the version you 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
@@ -300,7 +309,7 @@ More topics to be covered
.. rubric:: Footnotes
-.. [#] This is the usual lay-out. However, :file:`conf.py` can also live in
+.. [#] This is the usual layout. However, :file:`conf.py` can also live in
another directory, the :term:`configuration directory`. See
:ref:`invocation`.
diff --git a/doc/web/quickstart.rst b/doc/web/quickstart.rst
index 1bcd217e..996942db 100644
--- a/doc/web/quickstart.rst
+++ b/doc/web/quickstart.rst
@@ -45,7 +45,7 @@ by creating a :class:`~.WebSupport` object for your application::
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
+with. You can then call its :meth:`~.WebSupport.get_document` method to access
individual documents::
contents = support.get_document('contents')
@@ -56,8 +56,8 @@ This will return a dictionary containing the following items:
* **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
+* **css**: Links to CSS files used by Sphinx
+* **script**: 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
@@ -77,9 +77,9 @@ integrate with your existing templating system. An example using `Jinja2
<link rel="stylesheet" href="/static/websupport-custom.css" type="text/css">
{% endblock %}
- {%- block js %}
+ {%- block script %}
{{ super() }}
- {{ document.js|safe }}
+ {{ document.script|safe }}
{%- endblock %}
{%- block relbar %}
@@ -109,8 +109,8 @@ 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*.
+should be a boolean representing whether the user has moderation privileges.
+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::
diff --git a/setup.py b/setup.py
index 9872226e..9e000d5c 100644
--- a/setup.py
+++ b/setup.py
@@ -41,27 +41,21 @@ Among its features are the following:
* 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.')
+ print('ERROR: Sphinx requires at least Python 2.6 or 3.3 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']
- )
+requires = [
+ 'six>=1.4',
+ 'Jinja2>=2.3',
+ 'Pygments>=1.2',
+ 'docutils>=0.10',
+ 'snowballstemmer>=1.1',
+ 'babel',
+]
+
+if sys.platform == 'win32':
+ requires.append('colorama')
# Provide a "compile_catalog" command that also creates the translated
# JavaScript files if Babel is available.
@@ -185,7 +179,7 @@ setup(
'Topic :: Utilities',
],
platforms='any',
- packages=find_packages(exclude=['custom_fixers', 'test']),
+ packages=find_packages(exclude=['test']),
include_package_data=True,
entry_points={
'console_scripts': [
@@ -200,5 +194,4 @@ setup(
},
install_requires=requires,
cmdclass=cmdclass,
- **extra
)
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
index 49bbc284..cd8baeea 100644
--- a/sphinx/__init__.py
+++ b/sphinx/__init__.py
@@ -15,12 +15,12 @@
import sys
from os import path
-__version__ = '1.2.3+'
-__released__ = '1.2.3' # used when Sphinx builds its own docs
+__version__ = '1.3a0'
+__released__ = '1.3a0' # 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)
+version_info = (1, 3, 0, 'alpha', 0)
package_dir = path.abspath(path.dirname(__file__))
@@ -49,8 +49,9 @@ def main(argv=sys.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')
+ if (sys.version_info[:3] < (2, 6, 0) or
+ (3, 0, 0) <= sys.version_info[:3] < (3, 3, 0)):
+ sys.stderr.write('Error: Sphinx requires at least Python 2.6 to run.\n')
return 1
try:
from sphinx import cmdline
@@ -78,12 +79,12 @@ def build_main(argv=sys.argv):
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
+
+ from sphinx.util.compat import docutils_version
+ if docutils_version < (0, 10):
+ sys.stderr.write('Error: Sphinx requires at least Docutils 0.10 to '
+ 'run.\n')
+ return 1
return cmdline.main(argv)
diff --git a/sphinx/__main__.py b/sphinx/__main__.py
new file mode 100644
index 00000000..270bc4eb
--- /dev/null
+++ b/sphinx/__main__.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.__main__
+ ~~~~~~~~~~~~~~~
+
+ The Sphinx documentation toolchain.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import sys
+from sphinx import main
+
+sys.exit(main(sys.argv))
diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py
index 2806a059..362abd5a 100644
--- a/sphinx/addnodes.py
+++ b/sphinx/addnodes.py
@@ -25,6 +25,7 @@ class desc(nodes.Admonition, nodes.Element):
contains one or more ``desc_signature`` and a ``desc_content``.
"""
+
class desc_signature(nodes.Part, nodes.Inline, nodes.TextElement):
"""Node for object signatures.
@@ -39,33 +40,42 @@ class desc_addname(nodes.Part, nodes.Inline, nodes.TextElement):
# 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.
@@ -82,15 +92,18 @@ class versionmodified(nodes.Admonition, nodes.TextElement):
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."""
@@ -107,26 +120,33 @@ class index(nodes.Invisible, nodes.Inline, nodes.TextElement):
*entrytype* is one of "single", "pair", "double", "triple".
"""
+
class centered(nodes.Part, nodes.TextElement):
"""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)."""
@@ -136,14 +156,17 @@ class only(nodes.Element):
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.
@@ -160,17 +183,31 @@ class pending_xref(nodes.Inline, nodes.Element):
BuildEnvironment.resolve_references.
"""
+
+class number_reference(nodes.reference):
+ """Node for number references, similar to pending_xref."""
+
+
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 literal_strong(nodes.strong):
+ """Node that behaves like `strong`, 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."""
diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py
index 755ea5ef..7b1a96d2 100644
--- a/sphinx/apidoc.py
+++ b/sphinx/apidoc.py
@@ -14,6 +14,8 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
+
import os
import sys
import optparse
@@ -53,12 +55,12 @@ 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
+ print('Would create file %s.' % fname)
return
if not opts.force and path.isfile(fname):
- print 'File %s already exists, skipping.' % fname
+ print('File %s already exists, skipping.' % fname)
else:
- print 'Creating file %s.' % fname
+ print('Creating file %s.' % fname)
f = open(fname, 'w')
try:
f.write(text)
@@ -86,7 +88,7 @@ def create_module_file(package, module, opts):
text = format_heading(1, '%s module' % module)
else:
text = ''
- #text += format_heading(2, ':mod:`%s` Module' % module)
+ # text += format_heading(2, ':mod:`%s` Module' % module)
text += format_directive(module, package)
write_file(makename(package, module), text, opts)
@@ -95,6 +97,10 @@ 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))
+ if opts.modulefirst:
+ text += format_directive(subroot, master_package)
+ text += '\n'
+
# 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
@@ -134,8 +140,9 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs):
text += '\n'
text += '\n'
- text += format_heading(2, 'Module contents')
- text += format_directive(subroot, master_package)
+ if not opts.modulefirst:
+ text += format_heading(2, 'Module contents')
+ text += format_directive(subroot, master_package)
write_file(makename(master_package, subroot), text, opts)
@@ -166,7 +173,7 @@ def shall_skip(module, opts):
# 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:
+ not opts.includeprivate:
return True
return False
@@ -211,7 +218,7 @@ def recurse_tree(rootpath, excludes, opts):
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):
+ shall_skip(path.join(root, INITPY), opts):
subpackage = root[len(rootpath):].lstrip(path.sep).\
replace(path.sep, '.')
create_package_file(root, root_package, subpackage,
@@ -287,6 +294,10 @@ Note: By default this script will not overwrite already created files.""")
help='Don\'t create headings for the module/package '
'packages (e.g. when the docstrings already contain '
'them)')
+ parser.add_option('-M', '--module-first', action='store_true',
+ dest='modulefirst',
+ help='Put module documentation before submodule '
+ 'documentation')
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',
@@ -307,7 +318,7 @@ Note: By default this script will not overwrite already created files.""")
(opts, args) = parser.parse_args(argv[1:])
if opts.show_version:
- print 'Sphinx (sphinx-apidoc) %s' % __version__
+ print('Sphinx (sphinx-apidoc) %s' % __version__)
return 0
if not args:
@@ -321,7 +332,7 @@ Note: By default this script will not overwrite already created files.""")
if opts.suffix.startswith('.'):
opts.suffix = opts.suffix[1:]
if not path.isdir(rootpath):
- print >>sys.stderr, '%s is not a directory.' % rootpath
+ print('%s is not a directory.' % rootpath, file=sys.stderr)
sys.exit(1)
if not path.isdir(opts.destdir):
if not opts.dryrun:
diff --git a/sphinx/application.py b/sphinx/application.py
index 2704df23..630bff36 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -10,14 +10,18 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
import os
import sys
import types
import posixpath
+import traceback
from os import path
-from cStringIO import StringIO
+from collections import deque
+from six import iteritems, itervalues, text_type
+from six.moves import cStringIO
from docutils import nodes
from docutils.parsers.rst import convert_directive_function, \
directives, roles
@@ -33,19 +37,23 @@ 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.pycompat import deque
from sphinx.util.tags import Tags
from sphinx.util.osutil import ENOENT
-from sphinx.util.console import bold, lightgray, darkgray
+from sphinx.util.console import bold, lightgray, darkgray, darkgreen, \
+ term_width_line
+if hasattr(sys, 'intern'):
+ intern = sys.intern
# 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',
+ 'env-before-read-docs': 'env, docnames',
'source-read': 'docname, source text',
'doctree-read': 'the doctree before being pickled',
+ 'env-merge-info': 'env, read docnames, other env instance',
'missing-reference': 'env, node, contnode',
'doctree-resolved': 'doctree, docname',
'env-updated': 'env',
@@ -67,6 +75,7 @@ class Sphinx(object):
self.verbosity = verbosity
self.next_listener_id = 0
self._extensions = {}
+ self._extension_metadata = {}
self._listeners = {}
self.domains = BUILTIN_DOMAINS.copy()
self.builderclasses = BUILTIN_BUILDERS.copy()
@@ -81,20 +90,21 @@ class Sphinx(object):
self.parallel = parallel
if status is None:
- self._status = StringIO()
+ self._status = cStringIO()
self.quiet = True
else:
self._status = status
self.quiet = False
if warning is None:
- self._warning = StringIO()
+ self._warning = cStringIO()
else:
self._warning = warning
self._warncount = 0
self.warningiserror = warningiserror
self._events = events.copy()
+ self._translators = {}
# keep last few messages for traceback
self.messagelog = deque(maxlen=10)
@@ -105,6 +115,10 @@ class Sphinx(object):
# status code for command-line application
self.statuscode = 0
+ if not path.isdir(outdir):
+ self.info('making output directory...')
+ os.makedirs(outdir)
+
# read config
self.tags = Tags(tags)
self.config = Config(confdir, CONFIG_FILENAME,
@@ -116,14 +130,12 @@ class Sphinx(object):
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
+ # py31 doesn't have 'callable' function for below check
if hasattr(self.config.setup, '__call__'):
self.config.setup(self)
else:
@@ -134,7 +146,7 @@ class Sphinx(object):
)
# now that we know all config values, collect them from conf.py
- self.config.init_values()
+ self.config.init_values(self.warn)
# check the Sphinx version if requested
if self.config.needs_sphinx and \
@@ -143,6 +155,21 @@ class Sphinx(object):
'This project needs at least Sphinx v%s and therefore cannot '
'be built with this version.' % self.config.needs_sphinx)
+ # check extension versions if requested
+ if self.config.needs_extensions:
+ for extname, needs_ver in self.config.needs_extensions.items():
+ if extname not in self._extensions:
+ self.warn('needs_extensions config value specifies a '
+ 'version requirement for extension %s, but it is '
+ 'not loaded' % extname)
+ continue
+ has_ver = self._extension_metadata[extname]['version']
+ if has_ver == 'unknown version' or needs_ver > has_ver:
+ raise VersionRequirementError(
+ 'This project needs the extension %s at least in '
+ 'version %s and therefore cannot be built with the '
+ 'loaded version (%s).' % (extname, needs_ver, has_ver))
+
# set up translation infrastructure
self._init_i18n()
# set up the build environment
@@ -180,14 +207,14 @@ class Sphinx(object):
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 = 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:
+ except Exception as err:
if type(err) is IOError and err.errno == ENOENT:
self.info('not yet created')
else:
@@ -198,7 +225,7 @@ class Sphinx(object):
def _init_builder(self, buildername):
if buildername is None:
- print >>self._status, 'No builder selected, using default: html'
+ print('No builder selected, using default: html', file=self._status)
buildername = 'html'
if buildername not in self.builderclasses:
raise SphinxError('Builder name %s not registered' % buildername)
@@ -217,12 +244,24 @@ class Sphinx(object):
def build(self, force_all=False, filenames=None):
try:
if force_all:
+ self.builder.compile_all_catalogs()
self.builder.build_all()
elif filenames:
+ self.builder.compile_specific_catalogs(filenames)
self.builder.build_specific(filenames)
else:
+ self.builder.compile_update_catalogs()
self.builder.build_update()
- except Exception, err:
+
+ status = (self.statuscode == 0
+ and 'succeeded' or 'finished with problems')
+ if self._warncount:
+ self.info(bold('build %s, %s warning%s.' %
+ (status, self._warncount,
+ self._warncount != 1 and 's' or '')))
+ else:
+ self.info(bold('build %s.' % status))
+ except Exception as err:
# delete the saved env to force a fresh build next time
envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
if path.isfile(envfile):
@@ -268,7 +307,7 @@ class Sphinx(object):
else:
location = None
warntext = location and '%s: %s%s\n' % (location, prefix, message) or \
- '%s%s\n' % (prefix, message)
+ '%s%s\n' % (prefix, message)
if self.warningiserror:
raise SphinxWarning(warntext)
self._warncount += 1
@@ -327,6 +366,48 @@ class Sphinx(object):
message = message % (args or kwargs)
self._log(lightgray(message), self._status)
+ def _display_chunk(chunk):
+ if isinstance(chunk, (list, tuple)):
+ if len(chunk) == 1:
+ return text_type(chunk[0])
+ return '%s .. %s' % (chunk[0], chunk[-1])
+ return text_type(chunk)
+
+ def old_status_iterator(self, iterable, summary, colorfunc=darkgreen,
+ stringify_func=_display_chunk):
+ 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=_display_chunk):
+ 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.verbosity:
+ s += '\n'
+ else:
+ s = term_width_line(s)
+ self.info(s, nonl=1)
+ yield item
+ if l > 0:
+ self.info()
+
# ---- general extensibility interface -------------------------------------
def setup_extension(self, extension):
@@ -336,22 +417,29 @@ class Sphinx(object):
return
try:
mod = __import__(extension, None, None, ['setup'])
- except ImportError, err:
+ except ImportError as err:
+ self.verbose('Original exception:\n' + traceback.format_exc())
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)
+ ext_meta = None
else:
try:
- mod.setup(self)
- except VersionRequirementError, err:
+ ext_meta = mod.setup(self)
+ except VersionRequirementError as 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))
+ if ext_meta is None:
+ ext_meta = {}
+ if not ext_meta.get('version'):
+ ext_meta['version'] = 'unknown version'
self._extensions[extension] = mod
+ self._extension_metadata[extension] = ext_meta
def require_sphinx(self, version):
# check the Sphinx version if requested
@@ -362,17 +450,17 @@ class Sphinx(object):
"""Import an object from a 'module.name' string."""
try:
module, name = objname.rsplit('.', 1)
- except ValueError, err:
+ except ValueError as 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:
+ except ImportError as err:
raise ExtensionError('Could not import %s' % module +
(source and ' (needed for %s)' % source or ''),
err)
- except AttributeError, err:
+ except AttributeError as err:
raise ExtensionError('Could not find %s' % objname +
(source and ' (needed for %s)' % source or ''),
err)
@@ -398,7 +486,7 @@ class Sphinx(object):
def disconnect(self, listener_id):
self.debug('[app] disconnecting event: [id=%s]', listener_id)
- for event in self._listeners.itervalues():
+ for event in itervalues(self._listeners):
event.pop(listener_id, None)
def emit(self, event, *args):
@@ -409,7 +497,7 @@ class Sphinx(object):
pass
results = []
if event in self._listeners:
- for _, callback in self._listeners[event].iteritems():
+ for _, callback in iteritems(self._listeners[event]):
results.append(callback(self, *args))
return results
@@ -433,7 +521,7 @@ class Sphinx(object):
else:
raise ExtensionError(
'Builder %r already exists (in module %s)' % (
- builder.name, self.builderclasses[builder.name].__module__))
+ builder.name, self.builderclasses[builder.name].__module__))
self.builderclasses[builder.name] = builder
def add_config_value(self, name, default, rebuild):
@@ -450,16 +538,23 @@ class Sphinx(object):
raise ExtensionError('Event %r already present' % name)
self._events[name] = ''
+ def set_translator(self, name, translator_class):
+ self.info(bold('A Translator for the %s builder is changed.' % name))
+ self._translators[name] = translator_class
+
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():
+ for key, val in iteritems(kwds):
try:
visit, depart = val
except ValueError:
raise ExtensionError('Value for key %r must be a '
'(visit, depart) function tuple' % key)
- if key == 'html':
+ translator = self._translators.get(key)
+ if translator is not None:
+ pass
+ elif key == 'html':
from sphinx.writers.html import HTMLTranslator as translator
elif key == 'latex':
from sphinx.writers.latex import LaTeXTranslator as translator
@@ -599,6 +694,11 @@ class Sphinx(object):
StandaloneHTMLBuilder.css_files.append(
posixpath.join('_static', filename))
+ def add_latex_package(self, packagename, options=None):
+ self.debug('[app] adding latex package: %r', packagename)
+ from sphinx.builders.latex import LaTeXBuilder
+ LaTeXBuilder.usepackages.append((packagename, options))
+
def add_lexer(self, alias, lexer):
self.debug('[app] adding lexer: %r', (alias, lexer))
from sphinx.highlighting import lexers
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py
index c02ecb53..64ae2a09 100644
--- a/sphinx/builders/__init__.py
+++ b/sphinx/builders/__init__.py
@@ -20,8 +20,11 @@ except ImportError:
from docutils import nodes
-from sphinx.util.osutil import SEP, relative_uri
-from sphinx.util.console import bold, purple, darkgreen, term_width_line
+from sphinx.util import i18n, path_stabilize
+from sphinx.util.osutil import SEP, relative_uri, find_catalog
+from sphinx.util.console import bold, darkgreen
+from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
+ parallel_available
# side effect: registers roles and directives
from sphinx import roles
@@ -39,12 +42,14 @@ class Builder(object):
format = ''
# doctree versioning method
versioning_method = 'none'
+ versioning_compare = False
# 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.env.set_versioning_method(self.versioning_method,
+ self.versioning_compare)
self.srcdir = app.srcdir
self.confdir = app.confdir
self.outdir = app.outdir
@@ -61,9 +66,23 @@ class Builder(object):
self.tags.add(self.name)
self.tags.add("format_%s" % self.format)
self.tags.add("builder_%s" % self.name)
+ # compatibility aliases
+ self.status_iterator = app.status_iterator
+ self.old_status_iterator = app.old_status_iterator
# images that need to be copied over (source -> dest)
self.images = {}
+ # basename of images directory
+ self.imagedir = ""
+ # relative path to image directory from current docname (used at writing docs)
+ self.imgpath = ""
+
+ # these get set later
+ self.parallel_ok = False
+ self.finish_tasks = None
+
+ # load default translator class
+ self.translator_class = app._translators.get(self.name)
self.init()
@@ -109,41 +128,6 @@ class Builder(object):
"""
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):
@@ -170,6 +154,45 @@ class Builder(object):
continue
self.images[candidate] = self.env.images[candidate][1]
+ # compile po methods
+
+ def compile_catalogs(self, catalogs, message):
+ if not self.config.gettext_auto_build:
+ return
+ self.info(bold('building [mo]: ') + message)
+ for catalog in self.app.status_iterator(
+ catalogs, 'writing output... ', darkgreen, len(catalogs),
+ lambda c: c.mo_path):
+ catalog.write_mo(self.config.language)
+
+ def compile_all_catalogs(self):
+ catalogs = i18n.get_catalogs(
+ [path.join(self.srcdir, x) for x in self.config.locale_dirs],
+ self.config.language, True)
+ message = 'all of %d po files' % len(catalogs)
+ self.compile_catalogs(catalogs, message)
+
+ def compile_specific_catalogs(self, specified_files):
+ def to_domain(fpath):
+ docname, _ = path.splitext(path_stabilize(fpath))
+ dom = find_catalog(docname, self.config.gettext_compact)
+ return dom
+
+ specified_domains = set(map(to_domain, specified_files))
+ catalogs = i18n.get_catalogs(
+ [path.join(self.srcdir, x) for x in self.config.locale_dirs],
+ self.config.language, True)
+ catalogs = [f for f in catalogs if f.domain in specified_domains]
+ message = 'targets for %d po files that are specified' % len(catalogs)
+ self.compile_catalogs(catalogs, message)
+
+ def compile_update_catalogs(self):
+ catalogs = i18n.get_catalogs(
+ [path.join(self.srcdir, x) for x in self.config.locale_dirs],
+ self.config.language)
+ message = 'targets for %d po files that are out of date' % len(catalogs)
+ self.compile_catalogs(catalogs, message)
+
# build methods
def build_all(self):
@@ -219,25 +242,17 @@ class Builder(object):
First updates the environment, and then calls :meth:`write`.
"""
if summary:
- self.info(bold('building [%s]: ' % self.name), nonl=1)
- self.info(summary)
+ self.info(bold('building [%s]' % self.name) + ': ' + 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
+ updated_docnames = self.env.update(self.config, self.srcdir,
+ self.doctreedir, self.app)
+ self.env.set_warnfunc(self.warn)
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)
@@ -271,20 +286,33 @@ class Builder(object):
if docnames and docnames != ['__all__']:
docnames = set(docnames) & self.env.found_docs
- # another indirection to support builders that don't build
- # files individually
+ # determine if we can write in parallel
+ self.parallel_ok = False
+ if parallel_available and self.app.parallel > 1 and self.allow_parallel:
+ self.parallel_ok = True
+ for extname, md in self.app._extension_metadata.items():
+ par_ok = md.get('parallel_write_safe', True)
+ if not par_ok:
+ self.app.warn('the %s extension is not safe for parallel '
+ 'writing, doing serial read' % extname)
+ self.parallel_ok = False
+ break
+
+ # create a task executor to use for misc. "finish-up" tasks
+ # if self.parallel_ok:
+ # self.finish_tasks = ParallelTasks(self.app.parallel)
+ # else:
+ # for now, just execute them serially
+ self.finish_tasks = SerialTasks()
+
+ # write all "normal" documents (or everything for some builders)
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))
+
+ # wait for all tasks
+ self.finish_tasks.join()
def write(self, build_docnames, updated_docnames, method='update'):
if build_docnames is None or build_docnames == ['__all__']:
@@ -310,23 +338,17 @@ class Builder(object):
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:
+ if self.parallel_ok:
# 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)
+ else:
+ self._write_serial(sorted(docnames), warnings)
self.env.set_warnfunc(self.warn)
def _write_serial(self, docnames, warnings):
- for docname in self.status_iterator(
+ for docname in self.app.status_iterator(
docnames, 'writing output... ', darkgreen, len(docnames)):
doctree = self.env.get_and_resolve_doctree(docname, self)
self.write_doc_serialized(docname, doctree)
@@ -336,60 +358,34 @@ class Builder(object):
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 = []
+ for docname, doctree in docs:
+ self.write_doc(docname, doctree)
+ return warnings
+
+ def add_warnings(docs, wlist):
+ warnings.extend(wlist)
# 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:
+
+ tasks = ParallelTasks(nproc)
+ chunks = make_chunks(docnames, nproc)
+
+ for chunk in self.app.status_iterator(
+ chunks, 'writing output... ', darkgreen, len(chunks)):
+ arg = []
+ for i, docname in enumerate(chunk):
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)
+ arg.append((docname, doctree))
+ tasks.add_task(write_process, arg, add_warnings)
# make sure all threads have finished
- self.info(bold('waiting for workers... '))
- for t in threads:
- t.join()
+ self.info(bold('waiting for workers...'))
+ tasks.join()
def prepare_writing(self, docnames):
"""A place where you can add logic before :meth:`write_doc` is run"""
diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py
index c9317af2..069d0ce6 100644
--- a/sphinx/builders/changes.py
+++ b/sphinx/builders/changes.py
@@ -12,6 +12,8 @@
import codecs
from os import path
+from six import iteritems
+
from sphinx import package_dir
from sphinx.util import copy_static_entry
from sphinx.locale import _
@@ -93,9 +95,9 @@ class ChangesBuilder(Builder):
'version': version,
'docstitle': self.config.html_title,
'shorttitle': self.config.html_short_title,
- 'libchanges': sorted(libchanges.iteritems()),
+ 'libchanges': sorted(iteritems(libchanges)),
'apichanges': sorted(apichanges),
- 'otherchanges': sorted(otherchanges.iteritems()),
+ 'otherchanges': sorted(iteritems(otherchanges)),
'show_copyright': self.config.html_show_copyright,
'show_sphinx': self.config.html_show_sphinx,
}
@@ -128,6 +130,9 @@ class ChangesBuilder(Builder):
self.env.config.source_encoding)
try:
lines = f.readlines()
+ except UnicodeDecodeError:
+ self.warn('could not read %r for changelog creation' % docname)
+ continue
finally:
f.close()
targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
@@ -143,7 +148,7 @@ class ChangesBuilder(Builder):
finally:
f.close()
themectx = dict(('theme_' + key, val) for (key, val) in
- self.theme.get_options({}).iteritems())
+ iteritems(self.theme.get_options({})))
copy_static_entry(path.join(package_dir, 'themes', 'default',
'static', 'default.css_t'),
self.outdir, self, themectx)
diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py
index 61482fd0..afe4b404 100644
--- a/sphinx/builders/devhelp.py
+++ b/sphinx/builders/devhelp.py
@@ -94,7 +94,7 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
def istoctree(node):
return isinstance(node, addnodes.compact_paragraph) and \
- node.has_key('toctree')
+ 'toctree' in node
for node in tocdoc.traverse(istoctree):
write_toc(node, chapters)
diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py
index a73679c0..848dfaa4 100644
--- a/sphinx/builders/epub.py
+++ b/sphinx/builders/epub.py
@@ -12,7 +12,6 @@
import os
import re
-import sys
import time
import codecs
import zipfile
@@ -219,7 +218,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""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'):
+ if isinstance(doctree, nodes.reference) and 'refuri' in doctree:
refuri = doctree['refuri']
if refuri.startswith('http://') or refuri.startswith('https://') \
or refuri.startswith('irc:') or refuri.startswith('mailto:'):
@@ -405,9 +404,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
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)):
+ ensuredir(path.join(self.outdir, self.imagedir))
+ for src in self.app.status_iterator(self.images, 'copying images... ',
+ brown, len(self.images)):
dest = self.images[src]
try:
img = Image.open(path.join(self.srcdir, src))
@@ -417,8 +416,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
(path.join(self.srcdir, src), ))
try:
copyfile(path.join(self.srcdir, src),
- path.join(self.outdir, '_images', dest))
- except (IOError, OSError), err:
+ path.join(self.outdir, self.imagedir, dest))
+ except (IOError, OSError) as err:
self.warn('cannot copy image file %r: %s' %
(path.join(self.srcdir, src), err))
continue
@@ -433,8 +432,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
nh = (height * nw) / width
img = img.resize((nw, nh), Image.BICUBIC)
try:
- img.save(path.join(self.outdir, '_images', dest))
- except (IOError, OSError), err:
+ img.save(path.join(self.outdir, self.imagedir, dest))
+ except (IOError, OSError) as err:
self.warn('cannot write image file %r: %s' %
(path.join(self.srcdir, src), err))
@@ -490,7 +489,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
fn = path.join(outdir, outname)
try:
os.mkdir(path.dirname(fn))
- except OSError, err:
+ except OSError as err:
if err.errno != EEXIST:
raise
f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
@@ -750,12 +749,5 @@ class EpubBuilder(StandaloneHTMLBuilder):
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
index 250bef8c..1962545d 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -9,7 +9,7 @@
:license: BSD, see LICENSE for details.
"""
-from __future__ import with_statement
+from __future__ import unicode_literals
from os import path, walk
from codecs import open
@@ -18,6 +18,8 @@ from datetime import datetime, tzinfo, timedelta
from collections import defaultdict
from uuid import uuid4
+from six import iteritems
+
from sphinx.builders import Builder
from sphinx.util import split_index_msg
from sphinx.util.nodes import extract_messages, traverse_translatable_index
@@ -25,7 +27,7 @@ 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"""
+POHEADER = r"""
# SOME DESCRIPTIVE TITLE.
# Copyright (C) %(copyright)s
# This file is distributed under the same license as the %(project)s package.
@@ -82,6 +84,11 @@ class I18nBuilder(Builder):
"""
name = 'i18n'
versioning_method = 'text'
+ versioning_compare = None # be set by `gettext_uuid`
+
+ def __init__(self, app):
+ self.versioning_compare = app.env.config.gettext_uuid
+ super(I18nBuilder, self).__init__(app)
def init(self):
Builder.init(self)
@@ -96,6 +103,9 @@ class I18nBuilder(Builder):
def prepare_writing(self, docnames):
return
+ def compile_catalogs(self, catalogs, message):
+ return
+
def write_doc(self, docname, doctree):
catalog = self.catalogs[find_catalog(docname,
self.config.gettext_compact)]
@@ -103,15 +113,16 @@ class I18nBuilder(Builder):
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)
+ if 'index' in self.env.config.gettext_enables:
+ # 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
@@ -164,8 +175,8 @@ class MessageCatalogBuilder(I18nBuilder):
extract_translations = self.templates.environment.extract_translations
- for template in self.status_iterator(files,
- 'reading templates... ', purple, len(files)):
+ for template in self.app.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):
@@ -185,10 +196,10 @@ class MessageCatalogBuilder(I18nBuilder):
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... ",
+ for textdomain, catalog in self.app.status_iterator(
+ iteritems(self.catalogs), "writing message catalogs... ",
darkgreen, len(self.catalogs),
- lambda (textdomain, _): textdomain):
+ lambda textdomain__: textdomain__[0]):
# noop if config.gettext_compact is set
ensuredir(path.join(self.outdir, path.dirname(textdomain)))
@@ -200,19 +211,21 @@ class MessageCatalogBuilder(I18nBuilder):
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))
+ if self.config.gettext_location:
+ # generate "#: file1:line1\n#: file2:line2 ..."
+ pofile.write("#: %s\n" % "\n#: ".join("%s:%s" %
+ (safe_relpath(source, self.outdir), line)
+ for source, line, _ in positions))
+ if self.config.gettext_uuid:
+ # generate "# uuid1\n# uuid2\n ..."
+ pofile.write("# %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)
+ message = message.replace('\\', r'\\'). \
+ replace('"', r'\"'). \
+ replace('\n', '\\n"\n"')
+ pofile.write('msgid "%s"\nmsgstr ""\n\n' % message)
finally:
pofile.close()
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 9c039e3a..d33d2eef 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -14,14 +14,11 @@ 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 hashlib import md5
+from six import iteritems, itervalues, text_type, string_types
+from six.moves import cPickle as pickle
from docutils import nodes
from docutils.io import DocTreeInput, StringOutput
from docutils.core import Publisher
@@ -32,11 +29,9 @@ 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
+ 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
@@ -45,7 +40,7 @@ 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
+ SmartyPantsHTMLTranslator
#: the filename for the inventory of objects
INVENTORY_FILENAME = 'objects.inv'
@@ -63,7 +58,7 @@ def get_stable_hash(obj):
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()
+ return md5(text_type(obj).encode('utf8')).hexdigest()
class StandaloneHTMLBuilder(Builder):
@@ -100,6 +95,8 @@ class StandaloneHTMLBuilder(Builder):
# a hash of all config values that, if changed, cause a full rebuild
self.config_hash = ''
self.tags_hash = ''
+ # basename of images directory
+ self.imagedir = '_images'
# section numbers for headings in the currently visited document
self.secnumbers = {}
# currently written docname
@@ -157,7 +154,9 @@ class StandaloneHTMLBuilder(Builder):
self.config.trim_doctest_flags)
def init_translator_class(self):
- if self.config.html_translator_class:
+ if self.translator_class is not None:
+ pass
+ elif self.config.html_translator_class:
self.translator_class = self.app.import_object(
self.config.html_translator_class,
'html_translator_class setting')
@@ -168,7 +167,7 @@ class StandaloneHTMLBuilder(Builder):
def get_outdated_docs(self):
cfgdict = dict((name, self.config[name])
- for (name, desc) in self.config.values.iteritems()
+ for (name, desc) in iteritems(self.config.values)
if desc[1] == 'html')
self.config_hash = get_stable_hash(cfgdict)
self.tags_hash = get_stable_hash(sorted(self.tags))
@@ -225,7 +224,7 @@ class StandaloneHTMLBuilder(Builder):
"""Utility: Render a lone doctree node."""
if node is None:
return {'fragment': ''}
- doc = new_document(b('<partial node>'))
+ doc = new_document(b'<partial node>')
doc.append(node)
if self._publisher is None:
@@ -269,7 +268,7 @@ class StandaloneHTMLBuilder(Builder):
# 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 domain in itervalues(self.env.domains):
for indexcls in domain.indices:
indexname = '%s-%s' % (domain.name, indexcls.name)
if isinstance(indices_config, list):
@@ -300,7 +299,7 @@ class StandaloneHTMLBuilder(Builder):
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):
+ if not isinstance(self.config.html_use_opensearch, string_types):
self.warn('html_use_opensearch config value must now be a string')
self.relations = self.env.collect_relations()
@@ -350,7 +349,7 @@ class StandaloneHTMLBuilder(Builder):
if self.theme:
self.globalcontext.update(
('theme_' + key, val) for (key, val) in
- self.theme.get_options(self.theme_options).iteritems())
+ iteritems(self.theme.get_options(self.theme_options)))
self.globalcontext.update(self.config.html_context)
def get_doc_context(self, docname, body, metatags):
@@ -427,6 +426,7 @@ class StandaloneHTMLBuilder(Builder):
doctree.settings = self.docsettings
self.secnumbers = self.env.toc_secnumbers.get(docname, {})
+ self.fignumbers = self.env.toc_fignumbers.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
@@ -439,19 +439,26 @@ class StandaloneHTMLBuilder(Builder):
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.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir)
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)
+ self.finish_tasks.add_task(self.gen_indices)
+ self.finish_tasks.add_task(self.gen_additional_pages)
+ self.finish_tasks.add_task(self.copy_image_files)
+ self.finish_tasks.add_task(self.copy_download_files)
+ self.finish_tasks.add_task(self.copy_static_files)
+ self.finish_tasks.add_task(self.copy_extra_files)
+ self.finish_tasks.add_task(self.write_buildinfo)
- # pages from extensions
- for pagelist in self.app.emit('html-collect-pages'):
- for pagename, context, template in pagelist:
- self.handle_page(pagename, context, template)
+ # dump the search index
+ self.handle_finish()
+
+ def gen_indices(self):
+ self.info(bold('generating indices...'), nonl=1)
# the global general index
if self.get_builder_config('use_index', 'html'):
@@ -460,16 +467,27 @@ class StandaloneHTMLBuilder(Builder):
# 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')
+ self.info()
+
+ def gen_additional_pages(self):
+ # pages from extensions
+ for pagelist in self.app.emit('html-collect-pages'):
+ for pagename, context, template in pagelist:
+ self.handle_page(pagename, context, template)
+
+ self.info(bold('writing additional pages...'), 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)
+ # the search page
+ if self.name != 'htmlhelp':
+ self.info(' search', nonl=1)
+ self.handle_page('search', {}, 'search.html')
+
+ # the opensearch xml file
if self.config.html_use_opensearch and self.name != 'htmlhelp':
self.info(' opensearch', nonl=1)
fn = path.join(self.outdir, '_static', 'opensearch.xml')
@@ -477,15 +495,6 @@ class StandaloneHTMLBuilder(Builder):
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
@@ -528,14 +537,14 @@ class StandaloneHTMLBuilder(Builder):
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)):
+ ensuredir(path.join(self.outdir, self.imagedir))
+ for src in self.app.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:
+ path.join(self.outdir, self.imagedir, dest))
+ except Exception as err:
self.warn('cannot copy image file %r: %s' %
(path.join(self.srcdir, src), err))
@@ -543,14 +552,14 @@ class StandaloneHTMLBuilder(Builder):
# 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)):
+ for src in self.app.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:
+ except Exception as err:
self.warn('cannot copy downloadable file %r: %s' %
(path.join(self.srcdir, src), err))
@@ -583,10 +592,7 @@ class StandaloneHTMLBuilder(Builder):
# 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]
- )
+ matchers = compile_matchers(self.config.exclude_patterns)
for entry in staticentries:
if not path.exists(entry):
self.warn('html_static_path entry %r does not exist' % entry)
@@ -704,7 +710,7 @@ class StandaloneHTMLBuilder(Builder):
sidebars = None
matched = None
customsidebar = None
- for pattern, patsidebars in self.config.html_sidebars.iteritems():
+ for pattern, patsidebars in iteritems(self.config.html_sidebars):
if patmatch(pagename, pattern):
if matched:
if has_wildcard(pattern):
@@ -721,7 +727,7 @@ class StandaloneHTMLBuilder(Builder):
if sidebars is None:
# keep defaults
pass
- elif isinstance(sidebars, basestring):
+ elif isinstance(sidebars, string_types):
# 0.x compatible mode: insert custom sidebar before searchbox
customsidebar = sidebars
sidebars = None
@@ -782,7 +788,7 @@ class StandaloneHTMLBuilder(Builder):
f.write(output)
finally:
f.close()
- except (IOError, OSError), err:
+ except (IOError, OSError) as 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
@@ -792,8 +798,8 @@ class StandaloneHTMLBuilder(Builder):
copyfile(self.env.doc2path(pagename), source_name)
def handle_finish(self):
- self.dump_search_index()
- self.dump_inventory()
+ self.finish_tasks.add_task(self.dump_search_index)
+ self.finish_tasks.add_task(self.dump_inventory)
def dump_inventory(self):
self.info(bold('dumping object inventory... '), nonl=True)
@@ -806,7 +812,7 @@ class StandaloneHTMLBuilder(Builder):
% (self.config.project, self.config.version)
).encode('utf-8'))
compressor = zlib.compressobj(9)
- for domainname, domain in self.env.domains.iteritems():
+ for domainname, domain in iteritems(self.env.domains):
for name, dispname, type, docname, anchor, prio in \
domain.get_objects():
if anchor.endswith(name):
@@ -825,7 +831,9 @@ class StandaloneHTMLBuilder(Builder):
self.info('done')
def dump_search_index(self):
- self.info(bold('dumping search index... '), nonl=True)
+ self.info(
+ bold('dumping search index in %s ... ' % self.indexer.label()),
+ 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,
@@ -919,6 +927,23 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
self.fix_refuris(tree)
return tree
+ def assemble_toc_secnumbers(self):
+ # Assemble toc_secnumbers to resolve section numbers on SingleHTML.
+ # Merge all secnumbers to single secnumber.
+ #
+ # Note: current Sphinx has refid confliction in singlehtml mode.
+ # To avoid the problem, it replaces key of secnumbers to
+ # tuple of docname and refid.
+ #
+ # There are related codes in inline_all_toctres() and
+ # HTMLTranslter#add_secnumber().
+ new_secnumbers = {}
+ for docname, secnums in iteritems(self.env.toc_secnumbers):
+ for id, secnum in iteritems(secnums):
+ new_secnumbers[(docname, id)] = secnum
+
+ return {self.config.master_doc: new_secnumbers}
+
def get_doc_context(self, docname, body, metatags):
# no relation links...
toc = self.env.get_toctree_for(self.config.master_doc, self, False)
@@ -954,6 +979,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
self.info(bold('assembling single document... '), nonl=True)
doctree = self.assemble_doctree()
+ self.env.toc_secnumbers = self.assemble_toc_secnumbers()
self.info()
self.info(bold('writing... '), nonl=True)
self.write_doc_serialized(self.config.master_doc, doctree)
@@ -1005,6 +1031,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
def init(self):
self.config_hash = ''
self.tags_hash = ''
+ self.imagedir = '_images'
self.theme = None # no theme necessary
self.templates = None # no template bridge necessary
self.init_translator_class()
@@ -1100,8 +1127,4 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
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
index 77fcd438..400fbdc1 100644
--- a/sphinx/builders/htmlhelp.py
+++ b/sphinx/builders/htmlhelp.py
@@ -9,6 +9,7 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
import os
import codecs
@@ -197,7 +198,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
f = self.open_file(outdir, outname+'.stp')
try:
for word in sorted(stopwords):
- print >>f, word
+ print(word, file=f)
finally:
f.close()
@@ -217,8 +218,8 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
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,
- '\\')
+ print(path.join(root, fn)[olen:].replace(os.sep, '\\'),
+ file=f)
finally:
f.close()
@@ -256,7 +257,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
write_toc(subnode, ullevel)
def istoctree(node):
return isinstance(node, addnodes.compact_paragraph) and \
- node.has_key('toctree')
+ 'toctree' in node
for node in tocdoc.traverse(istoctree):
write_toc(node)
f.write(contents_footer)
diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py
index f5453305..5683ade2 100644
--- a/sphinx/builders/latex.py
+++ b/sphinx/builders/latex.py
@@ -12,6 +12,7 @@
import os
from os import path
+from six import iteritems
from docutils import nodes
from docutils.io import FileOutput
from docutils.utils import new_document
@@ -36,6 +37,7 @@ class LaTeXBuilder(Builder):
format = 'latex'
supported_image_types = ['application/pdf', 'image/png',
'image/gif', 'image/jpeg']
+ usepackages = []
def init(self):
self.docnames = []
@@ -56,7 +58,7 @@ class LaTeXBuilder(Builder):
return self.get_target_uri(to, typ)
def init_document_data(self):
- preliminary_document_data = map(list, self.config.latex_documents)
+ preliminary_document_data = [list(x) for x in self.config.latex_documents]
if not preliminary_document_data:
self.warn('no "latex_documents" config value found; no documents '
'will be written')
@@ -152,7 +154,7 @@ class LaTeXBuilder(Builder):
# copy image files
if self.images:
self.info(bold('copying images...'), nonl=1)
- for src, dest in self.images.iteritems():
+ for src, dest in iteritems(self.images):
self.info(' '+src, nonl=1)
copyfile(path.join(self.srcdir, src),
path.join(self.outdir, dest))
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
index f0cb3c9a..bf50e643 100644
--- a/sphinx/builders/linkcheck.py
+++ b/sphinx/builders/linkcheck.py
@@ -10,15 +10,15 @@
"""
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 six.moves import queue
+from six.moves.urllib.request import build_opener, Request, HTTPRedirectHandler
+from six.moves.urllib.parse import unquote
+from six.moves.urllib.error import HTTPError
+from six.moves.html_parser import HTMLParser, HTMLParseError
from docutils import nodes
from sphinx.builders import Builder
@@ -90,7 +90,7 @@ class CheckExternalLinksBuilder(Builder):
name = 'linkcheck'
def init(self):
- self.to_ignore = map(re.compile, self.app.config.linkcheck_ignore)
+ self.to_ignore = [re.compile(x) for x in self.app.config.linkcheck_ignore]
self.good = set()
self.broken = {}
self.redirected = {}
@@ -100,8 +100,8 @@ class CheckExternalLinksBuilder(Builder):
open(path.join(self.outdir, 'output.txt'), 'w').close()
# create queues and worker threads
- self.wqueue = Queue.Queue()
- self.rqueue = Queue.Queue()
+ 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)
@@ -111,7 +111,7 @@ class CheckExternalLinksBuilder(Builder):
def check_thread(self):
kwargs = {}
- if sys.version_info > (2, 5) and self.app.config.linkcheck_timeout:
+ if self.app.config.linkcheck_timeout:
kwargs['timeout'] = self.app.config.linkcheck_timeout
def check():
@@ -158,7 +158,7 @@ class CheckExternalLinksBuilder(Builder):
req = HeadRequest(req_url)
f = opener.open(req, **kwargs)
f.close()
- except HTTPError, err:
+ except HTTPError as err:
if err.code != 405:
raise
# retry with GET if that fails, some servers
@@ -167,7 +167,7 @@ class CheckExternalLinksBuilder(Builder):
f = opener.open(req, **kwargs)
f.close()
- except Exception, err:
+ except Exception as err:
self.broken[uri] = str(err)
return 'broken', str(err), 0
if f.url.rstrip('/') == req_url.rstrip('/'):
diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py
index 4de82a75..dfbf8986 100644
--- a/sphinx/builders/manpage.py
+++ b/sphinx/builders/manpage.py
@@ -11,16 +11,16 @@
from os import path
+from six import string_types
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
+from sphinx.writers.manpage import ManualPageWriter
class ManualPageBuilder(Builder):
@@ -32,9 +32,6 @@ class ManualPageBuilder(Builder):
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')
@@ -58,7 +55,7 @@ class ManualPageBuilder(Builder):
for info in self.config.man_pages:
docname, name, description, authors, section = info
- if isinstance(authors, basestring):
+ if isinstance(authors, string_types):
if authors:
authors = [authors]
else:
diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py
index 1d462841..8e2558e7 100644
--- a/sphinx/builders/qthelp.py
+++ b/sphinx/builders/qthelp.py
@@ -15,6 +15,7 @@ import codecs
import posixpath
from os import path
+from six import text_type
from docutils import nodes
from sphinx import addnodes
@@ -123,7 +124,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
prune_toctrees=False)
istoctree = lambda node: (
isinstance(node, addnodes.compact_paragraph)
- and node.has_key('toctree'))
+ and 'toctree' in node)
sections = []
for node in tocdoc.traverse(istoctree):
sections.extend(self.write_toc(node))
@@ -136,7 +137,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
# they are all unicode strings before joining them
new_sections = []
for section in sections:
- if not isinstance(section, unicode):
+ if not isinstance(section, text_type):
new_sections.append(force_decode(section, None))
else:
new_sections.append(section)
@@ -156,7 +157,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
olen = len(outdir)
projectfiles = []
staticdir = path.join(outdir, '_static')
- imagesdir = path.join(outdir, '_images')
+ imagesdir = path.join(outdir, self.imagedir)
for root, dirs, files in os.walk(outdir):
resourcedir = root.startswith(staticdir) or \
root.startswith(imagesdir)
diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py
index 39499e66..53463f3c 100644
--- a/sphinx/builders/texinfo.py
+++ b/sphinx/builders/texinfo.py
@@ -11,6 +11,7 @@
from os import path
+from six import iteritems
from docutils import nodes
from docutils.io import FileOutput
from docutils.utils import new_document
@@ -107,7 +108,7 @@ class TexinfoBuilder(Builder):
return self.get_target_uri(to, typ)
def init_document_data(self):
- preliminary_document_data = map(list, self.config.texinfo_documents)
+ preliminary_document_data = [list(x) for x in self.config.texinfo_documents]
if not preliminary_document_data:
self.warn('no "texinfo_documents" config value found; no documents '
'will be written')
@@ -207,7 +208,7 @@ class TexinfoBuilder(Builder):
# copy image files
if self.images:
self.info(bold('copying images...'), nonl=1)
- for src, dest in self.images.iteritems():
+ for src, dest in iteritems(self.images):
self.info(' '+src, nonl=1)
copyfile(path.join(self.srcdir, src),
path.join(self.outdir, dest))
@@ -223,6 +224,6 @@ class TexinfoBuilder(Builder):
mkfile.write(TEXINFO_MAKEFILE)
finally:
mkfile.close()
- except (IOError, OSError), err:
+ except (IOError, OSError) as 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
index 0aeeb5f4..46b4d72c 100644
--- a/sphinx/builders/text.py
+++ b/sphinx/builders/text.py
@@ -65,7 +65,7 @@ class TextBuilder(Builder):
f.write(self.writer.output)
finally:
f.close()
- except (IOError, OSError), err:
+ except (IOError, OSError) as err:
self.warn("error writing file %s: %s" % (outfilename, err))
def finish(self):
diff --git a/sphinx/builders/websupport.py b/sphinx/builders/websupport.py
index 6cf98102..c3fbdc70 100644
--- a/sphinx/builders/websupport.py
+++ b/sphinx/builders/websupport.py
@@ -27,6 +27,7 @@ class WebSupportBuilder(PickleHTMLBuilder):
"""
name = 'websupport'
versioning_method = 'commentable'
+ versioning_compare = True # for commentable node's uuid stability.
def init(self):
PickleHTMLBuilder.init(self)
@@ -46,7 +47,8 @@ class WebSupportBuilder(PickleHTMLBuilder):
self.storage = storage
def init_translator_class(self):
- self.translator_class = WebSupportTranslator
+ if self.translator_class is None:
+ self.translator_class = WebSupportTranslator
def prepare_writing(self, docnames):
PickleHTMLBuilder.prepare_writing(self, docnames)
@@ -57,7 +59,8 @@ class WebSupportBuilder(PickleHTMLBuilder):
doctree.settings = self.docsettings
self.secnumbers = self.env.toc_secnumbers.get(docname, {})
- self.imgpath = '/' + posixpath.join(self.virtual_staticdir, '_images')
+ self.fignumbers = self.env.toc_fignumbers.get(docname, {})
+ self.imgpath = '/' + posixpath.join(self.virtual_staticdir, self.imagedir)
self.dlpath = '/' + posixpath.join(self.virtual_staticdir, '_downloads')
self.current_docname = docname
self.docwriter.write(doctree, destination)
@@ -69,7 +72,7 @@ class WebSupportBuilder(PickleHTMLBuilder):
self.handle_page(docname, ctx, event_arg=doctree)
def write_doc_serialized(self, docname, doctree):
- self.imgpath = '/' + posixpath.join(self.virtual_staticdir, '_images')
+ self.imgpath = '/' + posixpath.join(self.virtual_staticdir, self.imagedir)
self.post_process_images(doctree)
title = self.env.longtitles.get(docname)
title = title and self.render_partial(title)['title'] or ''
@@ -147,7 +150,7 @@ class WebSupportBuilder(PickleHTMLBuilder):
PickleHTMLBuilder.handle_finish(self)
# move static stuff over to separate directory
- directories = ['_images', '_static']
+ directories = [self.imagedir, '_static']
for directory in directories:
src = path.join(self.outdir, directory)
dst = path.join(self.staticdir, directory)
diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py
index 9a9aec96..b0fcd2f7 100644
--- a/sphinx/builders/xml.py
+++ b/sphinx/builders/xml.py
@@ -81,7 +81,7 @@ class XMLBuilder(Builder):
f.write(self.writer.output)
finally:
f.close()
- except (IOError, OSError), err:
+ except (IOError, OSError) as err:
self.warn("error writing file %s: %s" % (outfilename, err))
def finish(self):
diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py
index ec24d902..18a17ab3 100644
--- a/sphinx/cmdline.py
+++ b/sphinx/cmdline.py
@@ -8,13 +8,15 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
import os
import sys
-import getopt
+import optparse
import traceback
from os import path
+from six import text_type, binary_type
from docutils.utils import SystemMessage
from sphinx import __version__
@@ -23,106 +25,138 @@ 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
+from sphinx.util.pycompat import terminal_safe
def usage(argv, msg=None):
if msg:
- print >>sys.stderr, msg
- print >>sys.stderr
- print >>sys.stderr, """\
+ print(msg, file=sys.stderr)
+ print(file=sys.stderr)
+
+USAGE = """\
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])
+Usage: %%prog [options] sourcedir outdir [filenames...]
+
+Filename arguments:
+ without -a and without filenames, write new and changed files.
+ with -a, write all files.
+ with filenames, write these.
+""" % __version__
+
+EPILOG = """\
+For more information, visit <http://sphinx-doc.org/>.
+"""
+
+
+class MyFormatter(optparse.IndentedHelpFormatter):
+ def format_usage(self, usage):
+ return usage
+
+ def format_help(self, formatter):
+ result = []
+ if self.description:
+ result.append(self.format_description(formatter))
+ if self.option_list:
+ result.append(self.format_option_help(formatter))
+ return "\n".join(result)
def main(argv):
if not color_terminal():
- # Windows' poor cmd box doesn't understand ANSI sequences
nocolor()
+ parser = optparse.OptionParser(USAGE, epilog=EPILOG, formatter=MyFormatter())
+ parser.add_option('--version', action='store_true', dest='version',
+ help='show version information and exit')
+
+ group = parser.add_option_group('General options')
+ group.add_option('-b', metavar='BUILDER', dest='builder', default='html',
+ help='builder to use; default is html')
+ group.add_option('-a', action='store_true', dest='force_all',
+ help='write all files; default is to only write new and '
+ 'changed files')
+ group.add_option('-E', action='store_true', dest='freshenv',
+ help='don\'t use a saved environment, always read '
+ 'all files')
+ group.add_option('-d', metavar='PATH', default=None, dest='doctreedir',
+ help='path for the cached environment and doctree files '
+ '(default: outdir/.doctrees)')
+ group.add_option('-j', metavar='N', default=1, type='int', dest='jobs',
+ help='build in parallel with N processes where possible')
+ # this option never gets through to this point (it is intercepted earlier)
+ # group.add_option('-M', metavar='BUILDER', dest='make_mode',
+ # help='"make" mode -- as used by Makefile, like '
+ # '"sphinx-build -M html"')
+
+ group = parser.add_option_group('Build configuration options')
+ group.add_option('-c', metavar='PATH', dest='confdir',
+ help='path where configuration file (conf.py) is located '
+ '(default: same as sourcedir)')
+ group.add_option('-C', action='store_true', dest='noconfig',
+ help='use no config file at all, only -D options')
+ group.add_option('-D', metavar='setting=value', action='append',
+ dest='define', default=[],
+ help='override a setting in configuration file')
+ group.add_option('-A', metavar='name=value', action='append',
+ dest='htmldefine', default=[],
+ help='pass a value into HTML templates')
+ group.add_option('-t', metavar='TAG', action='append',
+ dest='tags', default=[],
+ help='define tag: include "only" blocks with TAG')
+ group.add_option('-n', action='store_true', dest='nitpicky',
+ help='nit-picky mode, warn about all missing references')
+
+ group = parser.add_option_group('Console output options')
+ group.add_option('-v', action='count', dest='verbosity', default=0,
+ help='increase verbosity (can be repeated)')
+ group.add_option('-q', action='store_true', dest='quiet',
+ help='no output on stdout, just warnings on stderr')
+ group.add_option('-Q', action='store_true', dest='really_quiet',
+ help='no output at all, not even warnings')
+ group.add_option('-N', action='store_true', dest='nocolor',
+ help='do not emit colored output')
+ group.add_option('-w', metavar='FILE', dest='warnfile',
+ help='write warnings (and errors) to given file')
+ group.add_option('-W', action='store_true', dest='warningiserror',
+ help='turn warnings into errors')
+ group.add_option('-T', action='store_true', dest='traceback',
+ help='show full traceback on exception')
+ group.add_option('-P', action='store_true', dest='pdb',
+ help='run Pdb on exception')
+
# 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
+ opts, args = parser.parse_args()
+ except SystemExit as err:
+ return err.code
# 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__
+ if opts.version:
+ print('Sphinx (sphinx-build) %s' % __version__)
return 0
# get paths (first and second positional argument)
try:
- srcdir = confdir = abspath(args[0])
+ srcdir = abspath(args[0])
+ confdir = abspath(opts.confdir or srcdir)
+ if opts.noconfig:
+ confdir = None
if not path.isdir(srcdir):
- print >>sys.stderr, 'Error: Cannot find source directory `%s\'.' % (
- srcdir,)
+ print('Error: Cannot find source directory `%s\'.' % srcdir,
+ file=sys.stderr)
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.')
+ if not opts.noconfig and not path.isfile(path.join(confdir, 'conf.py')):
+ print('Error: Config directory doesn\'t contain a conf.py file.',
+ file=sys.stderr)
return 1
outdir = abspath(args[1])
except IndexError:
usage(argv, 'Error: Insufficient arguments.')
return 1
except UnicodeError:
- print >>sys.stderr, (
+ print(
'Error: Multibyte filename not supported on this filesystem '
- 'encoding (%r).' % fs_encoding)
+ 'encoding (%r).' % fs_encoding, file=sys.stderr)
return 1
# handle remaining filename arguments
@@ -130,7 +164,7 @@ def main(argv):
err = 0
for filename in filenames:
if not path.isfile(filename):
- print >>sys.stderr, 'Error: Cannot find file %r.' % filename
+ print('Error: Cannot find file %r.' % filename, file=sys.stderr)
err = 1
if err:
return 1
@@ -142,155 +176,113 @@ def main(argv):
except Exception:
likely_encoding = None
- buildername = None
- force_all = freshenv = warningiserror = use_pdb = False
- show_traceback = False
- verbosity = 0
- parallel = 0
+ if opts.force_all and filenames:
+ print('Error: Cannot combine -a option and filenames.', file=sys.stderr)
+ return 1
+
+ if opts.nocolor:
+ nocolor()
+
+ doctreedir = abspath(opts.doctreedir or path.join(outdir, '.doctrees'))
+
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')
+
+ if opts.quiet:
+ status = None
+ if opts.really_quiet:
+ status = warning = None
+ if warning and opts.warnfile:
+ try:
+ warnfp = open(opts.warnfile, 'w')
+ except Exception as exc:
+ print('Error: Cannot open warning file %r: %s' %
+ (opts.warnfile, exc), file=sys.stderr)
+ sys.exit(1)
warning = Tee(warning, warnfp)
error = warning
- if not path.isdir(outdir):
- if status:
- print >>status, 'Making output directory...'
- os.makedirs(outdir)
+ confoverrides = {}
+ for val in opts.define:
+ try:
+ key, val = val.split('=')
+ except ValueError:
+ print('Error: -D option argument must be in the form name=value.',
+ file=sys.stderr)
+ return 1
+ if likely_encoding and isinstance(val, binary_type):
+ try:
+ val = val.decode(likely_encoding)
+ except UnicodeError:
+ pass
+ confoverrides[key] = val
+
+ for val in opts.htmldefine:
+ try:
+ key, val = val.split('=')
+ except ValueError:
+ print('Error: -A option argument must be in the form name=value.',
+ file=sys.stderr)
+ return 1
+ try:
+ val = int(val)
+ except ValueError:
+ if likely_encoding and isinstance(val, binary_type):
+ try:
+ val = val.decode(likely_encoding)
+ except UnicodeError:
+ pass
+ confoverrides['html_context.%s' % key] = val
+
+ if opts.nitpicky:
+ confoverrides['nitpicky'] = True
app = None
try:
- app = Sphinx(srcdir, confdir, outdir, doctreedir, buildername,
- confoverrides, status, warning, freshenv,
- warningiserror, tags, verbosity, parallel)
- app.build(force_all, filenames)
+ app = Sphinx(srcdir, confdir, outdir, doctreedir, opts.builder,
+ confoverrides, status, warning, opts.freshenv,
+ opts.warningiserror, opts.tags, opts.verbosity, opts.jobs)
+ app.build(opts.force_all, filenames)
return app.statuscode
- except (Exception, KeyboardInterrupt), err:
- if use_pdb:
+ except (Exception, KeyboardInterrupt) as err:
+ if opts.pdb:
import pdb
- print >>error, red('Exception occurred while building, '
- 'starting debugger:')
+ print(red('Exception occurred while building, starting debugger:'),
+ file=error)
traceback.print_exc()
pdb.post_mortem(sys.exc_info()[2])
else:
- print >>error
- if show_traceback:
+ print(file=error)
+ if opts.verbosity or opts.traceback:
traceback.print_exc(None, error)
- print >>error
+ print(file=error)
if isinstance(err, KeyboardInterrupt):
- print >>error, 'interrupted!'
+ print('interrupted!', file=error)
elif isinstance(err, SystemMessage):
- print >>error, red('reST markup error:')
- print >>error, terminal_safe(err.args[0])
+ print(red('reST markup error:'), file=error)
+ print(terminal_safe(err.args[0]), file=error)
elif isinstance(err, SphinxError):
- print >>error, red('%s:' % err.category)
- print >>error, terminal_safe(unicode(err))
+ print(red('%s:' % err.category), file=error)
+ print(terminal_safe(text_type(err)), file=error)
elif isinstance(err, UnicodeError):
- print >>error, red('Encoding error:')
- print >>error, terminal_safe(unicode(err))
+ print(red('Encoding error:'), file=error)
+ print(terminal_safe(text_type(err)), file=error)
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(red('The full traceback has been saved in %s, if you want '
+ 'to report the issue to the developers.' % tbpath),
+ file=error)
else:
- print >>error, red('Exception occurred:')
- print >>error, format_exception_cut_frames().rstrip()
+ print(red('Exception occurred:'), file=error)
+ print(format_exception_cut_frames().rstrip(), file=error)
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!')
+ print(red('The full traceback has been saved in %s, if you '
+ 'want to report the issue to the developers.' % tbpath),
+ file=error)
+ print('Please also report this if it was a user error, so '
+ 'that a better error message can be provided next time.',
+ file=error)
+ print('A bug report can be filed in the tracker at '
+ '<https://bitbucket.org/birkenfeld/sphinx/issues/>. Thanks!',
+ file=error)
return 1
diff --git a/sphinx/config.py b/sphinx/config.py
index 69ba7cfe..77d6779d 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -8,21 +8,21 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-from __future__ import with_statement
import re
-import sys
from os import path
+from six import PY3, iteritems, string_types, binary_type, integer_types
+
from sphinx.errors import ConfigError
from sphinx.locale import l_
from sphinx.util.osutil import make_filename, cd
-from sphinx.util.pycompat import bytes, b, execfile_
+from sphinx.util.pycompat import execfile_
-nonascii_re = re.compile(b(r'[\x80-\xff]'))
+nonascii_re = re.compile(br'[\x80-\xff]')
CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s"
-if sys.version_info >= (3, 0):
+if PY3:
CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
class Config(object):
@@ -51,10 +51,6 @@ class Config(object):
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'),
@@ -71,8 +67,15 @@ class Config(object):
trim_doctest_flags = (True, 'env'),
primary_domain = ('py', 'env'),
needs_sphinx = (None, None),
+ needs_extensions = ({}, None),
nitpicky = (False, 'env'),
nitpick_ignore = ([], 'html'),
+ numfig = (False, 'env'),
+ numfig_secnum_depth = (1, 'env'),
+ numfig_prefix = ({'figure': l_('Fig. %s'),
+ 'table': l_('Table %s'),
+ 'code-block': l_('Listing %s')},
+ 'env'),
# HTML options
html_theme = ('default', 'html'),
@@ -205,6 +208,10 @@ class Config(object):
# gettext options
gettext_compact = (True, 'gettext'),
+ gettext_location = (True, 'gettext'),
+ gettext_uuid = (False, 'gettext'),
+ gettext_auto_build = (True, 'env'),
+ gettext_enables = ([], 'env'),
# XML options
xml_pretty = (True, 'env'),
@@ -214,8 +221,11 @@ class Config(object):
self.overrides = overrides
self.values = Config.config_values.copy()
config = {}
- if "extensions" in overrides:
- config["extensions"] = overrides["extensions"]
+ if 'extensions' in overrides:
+ if isinstance(overrides['extensions'], string_types):
+ config['extensions'] = overrides.pop('extensions').split(',')
+ else:
+ config['extensions'] = overrides.pop('extensions')
if dirname is not None:
config_file = path.join(dirname, filename)
config['__file__'] = config_file
@@ -225,7 +235,7 @@ class Config(object):
# config file is executed
try:
execfile_(filename, config)
- except SyntaxError, err:
+ except SyntaxError as err:
raise ConfigError(CONFIG_SYNTAX_ERROR % err)
self._raw_config = config
@@ -237,19 +247,43 @@ class Config(object):
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):
+ for name, value in iteritems(self._raw_config):
+ if isinstance(value, binary_type) 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):
+ def init_values(self, warn):
config = self._raw_config
- for valname, value in self.overrides.iteritems():
+ for valname, value in iteritems(self.overrides):
if '.' in valname:
realvalname, key = valname.split('.', 1)
config.setdefault(realvalname, {})[key] = value
+ continue
+ elif valname not in self.values:
+ warn('unknown config value %r in override, ignoring' % valname)
+ continue
+ defvalue = self.values[valname][0]
+ if isinstance(value, string_types):
+ if isinstance(defvalue, dict):
+ warn('cannot override dictionary config setting %r, '
+ 'ignoring (use %r to set individual elements)' %
+ (valname, valname + '.key=value'))
+ continue
+ elif isinstance(defvalue, list):
+ config[valname] = value.split(',')
+ elif isinstance(defvalue, integer_types):
+ try:
+ config[valname] = int(value)
+ except ValueError:
+ warn('invalid number %r for config value %r, ignoring'
+ % (value, valname))
+ elif defvalue is not None and not isinstance(defvalue, string_types):
+ warn('cannot override config setting %r with unsupported type, '
+ 'ignoring' % valname)
+ else:
+ config[valname] = value
else:
config[valname] = value
for name in config:
diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py
index 250a013e..969426bc 100644
--- a/sphinx/directives/__init__.py
+++ b/sphinx/directives/__init__.py
@@ -11,7 +11,8 @@
import re
-from docutils.parsers.rst import Directive, directives
+from docutils import nodes
+from docutils.parsers.rst import Directive, directives, roles
from sphinx import addnodes
from sphinx.util.docfields import DocFieldTransformer
@@ -162,6 +163,34 @@ class ObjectDescription(Directive):
DescDirective = ObjectDescription
+class DefaultRole(Directive):
+ """
+ Set the default interpreted text role. Overridden from docutils.
+ """
+
+ optional_arguments = 1
+ final_argument_whitespace = False
+
+ def run(self):
+ if not self.arguments:
+ if '' in roles._roles:
+ # restore the "default" default role
+ del roles._roles['']
+ return []
+ role_name = self.arguments[0]
+ role, messages = roles.role(role_name, self.state_machine.language,
+ self.lineno, self.state.reporter)
+ if role is None:
+ error = self.state.reporter.error(
+ 'Unknown interpreted text role "%s".' % role_name,
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ return messages + [error]
+ roles._roles[''] = role
+ self.state.document.settings.env.temp_data['default_role'] = role_name
+ return messages
+
+
class DefaultDomain(Directive):
"""
Directive to (re-)set the default domain for this source file.
@@ -178,7 +207,7 @@ class DefaultDomain(Directive):
domain_name = self.arguments[0].lower()
# if domain_name not in env.domains:
# # try searching by label
- # for domain in env.domains.itervalues():
+ # for domain in itervalues(env.domains):
# if domain.label.lower() == domain_name:
# domain_name = domain.name
# break
@@ -186,6 +215,7 @@ class DefaultDomain(Directive):
return []
+directives.register_directive('default-role', DefaultRole)
directives.register_directive('default-domain', DefaultDomain)
directives.register_directive('describe', ObjectDescription)
# new, more consistent, name
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index 9bfac5a6..aee32fe3 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -9,9 +9,13 @@
import sys
import codecs
+from difflib import unified_diff
from docutils import nodes
from docutils.parsers.rst import Directive, directives
+from docutils.statemachine import ViewList
+
+from six import string_types
from sphinx import addnodes
from sphinx.util import parselinenos
@@ -39,11 +43,39 @@ class Highlight(Directive):
except Exception:
linenothreshold = 10
else:
- linenothreshold = sys.maxint
+ linenothreshold = sys.maxsize
return [addnodes.highlightlang(lang=self.arguments[0].strip(),
linenothreshold=linenothreshold)]
+def dedent_lines(lines, dedent):
+ if not dedent:
+ return lines
+
+ new_lines = []
+ for line in lines:
+ new_line = line[dedent:]
+ if line.endswith('\n') and not new_line:
+ new_line = '\n' # keep CRLF
+ new_lines.append(new_line)
+
+ return new_lines
+
+
+def container_wrapper(directive, literal_node, caption):
+ container_node = nodes.container('', literal_block=True)
+ parsed = nodes.Element()
+ directive.state.nested_parse(ViewList([caption], source=''),
+ directive.content_offset, parsed)
+ caption_node = nodes.caption(parsed[0].rawsource, '',
+ *parsed[0].children)
+ caption_node.source = parsed[0].source
+ caption_node.line = parsed[0].line
+ container_node += caption_node
+ container_node += literal_node
+ return container_node
+
+
class CodeBlock(Directive):
"""
Directive for a code block with special highlighting or line numbering
@@ -56,7 +88,10 @@ class CodeBlock(Directive):
final_argument_whitespace = False
option_spec = {
'linenos': directives.flag,
+ 'dedent': int,
+ 'lineno-start': int,
'emphasize-lines': directives.unchanged_required,
+ 'caption': directives.unchanged_required,
}
def run(self):
@@ -67,18 +102,32 @@ class CodeBlock(Directive):
try:
nlines = len(self.content)
hl_lines = [x+1 for x in parselinenos(linespec, nlines)]
- except ValueError, err:
+ except ValueError as err:
document = self.state.document
return [document.reporter.warning(str(err), line=self.lineno)]
else:
hl_lines = None
+ if 'dedent' in self.options:
+ lines = code.split('\n')
+ lines = dedent_lines(lines, self.options['dedent'])
+ code = '\n'.join(lines)
+
literal = nodes.literal_block(code, code)
literal['language'] = self.arguments[0]
- literal['linenos'] = 'linenos' in self.options
+ literal['linenos'] = 'linenos' in self.options or \
+ 'lineno-start' in self.options
+ extra_args = literal['highlight_args'] = {}
if hl_lines is not None:
- literal['highlight_args'] = {'hl_lines': hl_lines}
+ extra_args['hl_lines'] = hl_lines
+ if 'lineno-start' in self.options:
+ extra_args['linenostart'] = self.options['lineno-start']
set_source_info(self, literal)
+
+ caption = self.options.get('caption')
+ if caption:
+ literal = container_wrapper(self, literal, caption)
+
return [literal]
@@ -94,7 +143,10 @@ class LiteralInclude(Directive):
optional_arguments = 0
final_argument_whitespace = True
option_spec = {
+ 'dedent': int,
'linenos': directives.flag,
+ 'lineno-start': int,
+ 'lineno-match': directives.flag,
'tab-width': int,
'language': directives.unchanged_required,
'encoding': directives.encoding,
@@ -105,8 +157,31 @@ class LiteralInclude(Directive):
'prepend': directives.unchanged_required,
'append': directives.unchanged_required,
'emphasize-lines': directives.unchanged_required,
+ 'caption': directives.unchanged,
+ 'diff': directives.unchanged_required,
}
+ def read_with_encoding(self, filename, document, codec_info, encoding):
+ f = None
+ try:
+ f = codecs.StreamReaderWriter(open(filename, 'rb'), codec_info[2],
+ codec_info[3], 'strict')
+ lines = f.readlines()
+ lines = dedent_lines(lines, self.options.get('dedent'))
+ return lines
+ 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()
+
def run(self):
document = self.state.document
if not document.settings.file_insertion_enabled:
@@ -120,26 +195,41 @@ class LiteralInclude(Directive):
'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):
+ if 'lineno-match' in self.options and 'lineno-start' in self.options:
return [document.reporter.warning(
- 'Include file %r not found or reading it failed' % filename,
+ 'Cannot use both "lineno-match" and "lineno-start"',
line=self.lineno)]
- except UnicodeError:
+
+ if 'lineno-match' in self.options and \
+ (set(['append', 'prepend']) & set(self.options.keys())):
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()
+ 'Cannot use "lineno-match" and "append" or "prepend"',
+ line=self.lineno)]
+ encoding = self.options.get('encoding', env.config.source_encoding)
+ codec_info = codecs.lookup(encoding)
+
+ lines = self.read_with_encoding(filename, document,
+ codec_info, encoding)
+ if not isinstance(lines[0], string_types):
+ return lines
+
+ diffsource = self.options.get('diff')
+ if diffsource is not None:
+ tmp, fulldiffsource = env.relfn2path(diffsource)
+
+ difflines = self.read_with_encoding(fulldiffsource, document,
+ codec_info, encoding)
+ if not isinstance(difflines[0], string_types):
+ return difflines
+ diff = unified_diff(
+ difflines,
+ lines,
+ diffsource,
+ self.arguments[0])
+ lines = list(diff)
+
+ linenostart = self.options.get('lineno-start', 1)
objectname = self.options.get('pyobject')
if objectname is not None:
from sphinx.pycode import ModuleAnalyzer
@@ -150,17 +240,30 @@ class LiteralInclude(Directive):
'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]
+ lines = lines[tags[objectname][1]-1: tags[objectname][2]-1]
+ if 'lineno-match' in self.options:
+ linenostart = tags[objectname][1]
linespec = self.options.get('lines')
- if linespec is not None:
+ if linespec:
try:
linelist = parselinenos(linespec, len(lines))
- except ValueError, err:
+ except ValueError as 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 'lineno-match' in self.options:
+ # make sure the line list is not "disjoint".
+ previous = linelist[0]
+ for line_number in linelist[1:]:
+ if line_number == previous + 1:
+ previous = line_number
+ continue
+ return [document.reporter.warning(
+ 'Cannot use "lineno-match" with a disjoint set of '
+ '"lines"', line=self.lineno)]
+ linenostart = linelist[0] + 1
+ # just ignore non-existing lines
+ lines = [lines[i] for i in linelist if i < len(lines)]
if not lines:
return [document.reporter.warning(
'Line spec %r: no lines pulled from include file %r' %
@@ -170,50 +273,74 @@ class LiteralInclude(Directive):
if linespec:
try:
hl_lines = [x+1 for x in parselinenos(linespec, len(lines))]
- except ValueError, err:
+ except ValueError as 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')
+ endbefore = self.options.get('end-before')
if startafter is not None or endbefore is not None:
use = not startafter
res = []
- for line in lines:
+ for line_number, line in enumerate(lines):
if not use and startafter and startafter in line:
+ if 'lineno-match' in self.options:
+ linenostart += line_number + 1
use = True
elif use and endbefore and endbefore in line:
- use = False
break
elif use:
res.append(line)
lines = res
+ if 'lineno-match' in self.options:
+ # handle that docutils remove preceding lines which only contains
+ # line separation.
+ for line in lines:
+ # check if line contains anything else than line separation.
+ if line and line.splitlines()[0]:
+ break
+ linenostart += 1
+
+ prepend = self.options.get('prepend')
if prepend:
- lines.insert(0, prepend + '\n')
+ lines.insert(0, prepend + '\n')
+
+ append = self.options.get('append')
if append:
- lines.append(append + '\n')
+ 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', ''):
+ if diffsource: # if diff is set, set udiff
+ retnode['language'] = 'udiff'
+ if 'language' in self.options:
retnode['language'] = self.options['language']
- if 'linenos' in self.options:
- retnode['linenos'] = True
+ retnode['linenos'] = 'linenos' in self.options or \
+ 'lineno-start' in self.options or \
+ 'lineno-match' in self.options
+ extra_args = retnode['highlight_args'] = {}
if hl_lines is not None:
- retnode['highlight_args'] = {'hl_lines': hl_lines}
+ extra_args['hl_lines'] = hl_lines
+ extra_args['linenostart'] = linenostart
env.note_dependency(rel_filename)
+
+ caption = self.options.get('caption')
+ if caption is not None:
+ if caption:
+ retnode = container_wrapper(self, retnode, caption)
+ else:
+ retnode = container_wrapper(self, retnode, self.arguments[0])
+
return [retnode]
directives.register_directive('highlight', Highlight)
-directives.register_directive('highlightlang', Highlight) # old
+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
index d28c00fb..01c8c012 100644
--- a/sphinx/directives/other.py
+++ b/sphinx/directives/other.py
@@ -7,6 +7,7 @@
:license: BSD, see LICENSE for details.
"""
+from six.moves import range
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
@@ -368,7 +369,7 @@ class Only(Directive):
# 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):
+ for i in range(n_sects_to_raise):
if parent.parent:
parent = parent.parent
parent.append(node)
diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py
index 200fd515..66d4c677 100644
--- a/sphinx/domains/__init__.py
+++ b/sphinx/domains/__init__.py
@@ -10,6 +10,8 @@
:license: BSD, see LICENSE for details.
"""
+from six import iteritems
+
from sphinx.errors import SphinxError
from sphinx.locale import _
@@ -153,10 +155,13 @@ class Domain(object):
self._role_cache = {}
self._directive_cache = {}
self._role2type = {}
- for name, obj in self.object_types.iteritems():
+ self._type2role = {}
+ for name, obj in iteritems(self.object_types):
for rolename in obj.roles:
self._role2type.setdefault(rolename, []).append(name)
+ self._type2role[name] = obj.roles[0] if obj.roles else ''
self.objtypes_for_role = self._role2type.get
+ self.role_for_objtype = self._type2role.get
def role(self, name):
"""Return a role adapter function that always gives the registered
@@ -197,6 +202,14 @@ class Domain(object):
"""Remove traces of a document in the domain-specific inventories."""
pass
+ def merge_domaindata(self, docnames, otherdata):
+ """Merge in data regarding *docnames* from a different domaindata
+ inventory (coming from a subprocess in parallel builds).
+ """
+ raise NotImplementedError('merge_domaindata must be implemented in %s '
+ 'to be able to do parallel builds!' %
+ self.__class__)
+
def process_doc(self, env, docname, document):
"""Process a document after it is read by the environment."""
pass
@@ -218,6 +231,22 @@ class Domain(object):
"""
pass
+ def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode):
+ """Resolve the pending_xref *node* with the given *target*.
+
+ The reference comes from an "any" or similar role, which means that we
+ don't know the type. Otherwise, the arguments are the same as for
+ :meth:`resolve_xref`.
+
+ The method must return a list (potentially empty) of tuples
+ ``('domain:role', newnode)``, where ``'domain:role'`` is the name of a
+ role that could have created the same reference, e.g. ``'py:func'``.
+ ``newnode`` is what :meth:`resolve_xref` would return.
+
+ .. versionadded:: 1.3
+ """
+ raise NotImplementedError
+
def get_objects(self):
"""Return an iterable of "object descriptions", which are tuples with
five items:
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index fb38cfe8..0754e317 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -39,6 +39,13 @@ c_funcptr_sig_re = re.compile(
\( (.*) \) # arguments
(\s+const)? $ # const specifier
''', re.VERBOSE)
+c_funcptr_arg_sig_re = re.compile(
+ r'''^\s*([^(,]+?) # return type
+ \( ([^()]+) \) \s* # name in parentheses
+ \( (.*) \) # arguments
+ (\s+const)? # const specifier
+ \s*(?=$|,) # end with comma or end of string
+ ''', re.VERBOSE)
c_funcptr_name_re = re.compile(r'^\(\s*\*\s*(.*?)\s*\)$')
@@ -68,7 +75,7 @@ class CObject(ObjectDescription):
def _parse_type(self, node, ctype):
# add cross-ref nodes for all words
- for part in filter(None, wsplit_re.split(ctype)):
+ for part in [_f for _f in wsplit_re.split(ctype) if _f]:
tnode = nodes.Text(part, part)
if part[0] in string.ascii_letters+'_' and \
part not in self.stopwords:
@@ -80,6 +87,24 @@ class CObject(ObjectDescription):
else:
node += tnode
+ def _parse_arglist(self, arglist):
+ while True:
+ m = c_funcptr_arg_sig_re.match(arglist)
+ if m:
+ yield m.group()
+ arglist = c_funcptr_arg_sig_re.sub('', arglist)
+ if ',' in arglist:
+ _, arglist = arglist.split(',', 1)
+ else:
+ break
+ else:
+ if ',' in arglist:
+ arg, arglist = arglist.split(',', 1)
+ yield arg
+ else:
+ yield arglist
+ break
+
def handle_signature(self, sig, signode):
"""Transform a C signature into RST nodes."""
# first try the function pointer signature regex, it's more specific
@@ -105,7 +130,7 @@ class CObject(ObjectDescription):
if m:
name = m.group(1)
- typename = self.env.temp_data.get('c:type')
+ typename = self.env.ref_context.get('c:type')
if self.name == 'c:member' and typename:
fullname = typename + '.' + name
else:
@@ -122,19 +147,25 @@ class CObject(ObjectDescription):
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:
+ for arg in self._parse_arglist(arglist):
arg = arg.strip()
param = addnodes.desc_parameter('', '', noemph=True)
try:
- ctype, argname = arg.rsplit(' ', 1)
+ m = c_funcptr_arg_sig_re.match(arg)
+ if m:
+ self._parse_type(param, m.group(1) + '(')
+ param += nodes.emphasis(m.group(2), m.group(2))
+ self._parse_type(param, ')(' + m.group(3) + ')')
+ if m.group(4):
+ param += addnodes.desc_addname(m.group(4), m.group(4))
+ else:
+ ctype, argname = arg.rsplit(' ', 1)
+ self._parse_type(param, ctype)
+ # separate by non-breaking space in the output
+ param += nodes.emphasis(' '+argname, u'\xa0'+argname)
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:
@@ -181,12 +212,12 @@ class CObject(ObjectDescription):
self.typename_set = False
if self.name == 'c:type':
if self.names:
- self.env.temp_data['c:type'] = self.names[0]
+ self.env.ref_context['c:type'] = self.names[0]
self.typename_set = True
def after_content(self):
if self.typename_set:
- self.env.temp_data['c:type'] = None
+ self.env.ref_context.pop('c:type', None)
class CXRefRole(XRefRole):
@@ -234,10 +265,16 @@ class CDomain(Domain):
}
def clear_doc(self, docname):
- for fullname, (fn, _) in self.data['objects'].items():
+ for fullname, (fn, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
+ def merge_domaindata(self, docnames, otherdata):
+ # XXX check duplicates
+ for fullname, (fn, objtype) in otherdata['objects'].items():
+ if fn in docnames:
+ self.data['objects'][fullname] = (fn, objtype)
+
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
# strip pointer asterisk
@@ -248,6 +285,17 @@ class CDomain(Domain):
return make_refnode(builder, fromdocname, obj[0], 'c.' + target,
contnode, target)
+ def resolve_any_xref(self, env, fromdocname, builder, target,
+ node, contnode):
+ # strip pointer asterisk
+ target = target.rstrip(' *')
+ if target not in self.data['objects']:
+ return []
+ obj = self.data['objects'][target]
+ return [('c:' + self.role_for_objtype(obj[1]),
+ make_refnode(builder, fromdocname, obj[0], 'c.' + target,
+ contnode, target))]
+
def get_objects(self):
- for refname, (docname, type) in self.data['objects'].iteritems():
+ for refname, (docname, type) in list(self.data['objects'].items()):
yield (refname, refname, type, docname, 'c.' + refname, 1)
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index cb64a60d..d4455a22 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -7,11 +7,143 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
+
+ See http://www.nongnu.org/hcb/ for the grammar.
+ See http://mentorembedded.github.io/cxx-abi/abi.html#mangling for the
+ inspiration for the id generation.
+
+ common grammar things:
+ simple-declaration
+ -> attribute-specifier-seq[opt] decl-specifier-seq[opt]
+ init-declarator-list[opt] ;
+ # Drop the semi-colon. For now: drop the attributes (TODO).
+ # Use at most 1 init-declerator.
+ -> decl-specifier-seq init-declerator
+ -> decl-specifier-seq declerator initializer
+
+ decl-specifier ->
+ storage-class-specifier -> "static" (only for member_object and
+ function_object)
+ | type-specifier -> trailing-type-specifier
+ | function-specifier -> "inline" | "virtual" | "explicit" (only
+ for function_object)
+ | "friend" (only for function_object)
+ | "constexpr" (only for member_object and function_object)
+ trailing-type-specifier ->
+ simple-type-specifier
+ | elaborated-type-specifier
+ | typename-specifier
+ | cv-qualifier -> "const" | "volatile"
+ stricter grammar for decl-specifier-seq (with everything, each object
+ uses a subset):
+ visibility storage-class-specifier function-specifier "friend"
+ "constexpr" "volatile" "const" trailing-type-specifier
+ # where trailing-type-specifier can no be cv-qualifier
+ # Inside e.g., template paramters a strict subset is used
+ # (see type-specifier-seq)
+ trailing-type-specifier ->
+ simple-type-specifier ->
+ ::[opt] nested-name-specifier[opt] type-name
+ | ::[opt] nested-name-specifier "template" simple-template-id
+ | "char" | "bool" | ect.
+ | decltype-specifier
+ | elaborated-type-specifier ->
+ class-key attribute-specifier-seq[opt] ::[opt]
+ nested-name-specifier[opt] identifier
+ | class-key ::[opt] nested-name-specifier[opt] template[opt]
+ simple-template-id
+ | "enum" ::[opt] nested-name-specifier[opt] identifier
+ | typename-specifier ->
+ "typename" ::[opt] nested-name-specifier identifier
+ | "typename" ::[opt] nested-name-specifier template[opt]
+ simple-template-id
+ class-key -> "class" | "struct" | "union"
+ type-name ->* identifier | simple-template-id
+ # ignoring attributes and decltype, and then some left-factoring
+ trailing-type-specifier ->
+ rest-of-trailing
+ ("class" | "struct" | "union" | "typename") rest-of-trailing
+ build-in -> "char" | "bool" | ect.
+ decltype-specifier
+ rest-of-trailing -> (with some simplification)
+ "::"[opt] list-of-elements-separated-by-::
+ element ->
+ "template"[opt] identifier ("<" template-argument-list ">")[opt]
+ template-argument-list ->
+ template-argument "..."[opt]
+ | template-argument-list "," template-argument "..."[opt]
+ template-argument ->
+ constant-expression
+ | type-specifier-seq abstract-declerator
+ | id-expression
+
+
+ declerator ->
+ ptr-declerator
+ | noptr-declarator parameters-and-qualifiers trailing-return-type
+ (TODO: for now we don't support it)
+ ptr-declerator ->
+ noptr-declerator
+ | ptr-operator ptr-declarator
+ noptr-declerator ->
+ declarator-id attribute-specifier-seq[opt] ->
+ "..."[opt] id-expression
+ | rest-of-trailing
+ | noptr-declerator parameters-and-qualifiers
+ | noptr-declarator "[" constant-expression[opt] "]"
+ attribute-specifier-seq[opt]
+ | "(" ptr-declarator ")" # TODO: not implemented yet
+ # function_object must use a parameters-and-qualifiers, the others may
+ # use it (e.g., function poitners)
+ parameters-and-qualifiers ->
+ "(" parameter-clause ")" attribute-specifier-seq[opt]
+ cv-qualifier-seq[opt] ref-qualifier[opt]
+ exception-specification[opt]
+ ref-qualifier -> "&" | "&&"
+ exception-specification ->
+ "noexcept" ("(" constant-expression ")")[opt]
+ "throw" ("(" type-id-list ")")[opt]
+ # TODO: we don't implement attributes
+ # member functions can have initializers, but we fold them into here
+ memberFunctionInit -> "=" "0"
+ # (note: only "0" is allowed as the value, according to the standard,
+ # right?)
+
+
+ We additionally add the possibility for specifying the visibility as the
+ first thing.
+
+ type_object:
+ goal:
+ either a single type (e.g., "MyClass:Something_T" or a typedef-like
+ thing (e.g. "Something Something_T" or "int I_arr[]"
+ grammar, single type: based on a type in a function parameter, but
+ without a name:
+ parameter-declaration
+ -> attribute-specifier-seq[opt] decl-specifier-seq
+ abstract-declarator[opt]
+ # Drop the attributes
+ -> decl-specifier-seq abstract-declarator[opt]
+ grammar, typedef-like: no initilizer
+ decl-specifier-seq declerator
+
+
+ member_object:
+ goal: as a type_object which must have a declerator, and optionally
+ with a initializer
+ grammar:
+ decl-specifier-seq declerator initializer
+
+ function_object:
+ goal: a function declaration, TODO: what about templates? for now: skip
+ grammar: no initializer
+ decl-specifier-seq declerator
"""
import re
from copy import deepcopy
+from six import iteritems, text_type
from docutils import nodes
from sphinx import addnodes
@@ -21,6 +153,7 @@ 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.pycompat import UnicodeMixin
from sphinx.util.docfields import Field, GroupedField
@@ -40,88 +173,112 @@ _operator_re = re.compile(r'''(?x)
| [!<>=/*%+|&^~-]=?
''')
-_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'
+_id_prefix = '_CPP'
+_id_fundamental = {
+ # not all of these are actually parsed as fundamental types, TODO: do that
+ 'void': 'v',
+ 'bool': 'b',
+ 'char': 'c',
+ 'signed char': 'a',
+ 'unsigned char': 'h',
+ 'wchar_t': 'w',
+ 'char32_t': 'Di',
+ 'char16_t': 'Ds',
+ 'short': 's',
+ 'short int': 's',
+ 'signed short': 's',
+ 'signed short int': 's',
+ 'unsigned short': 't',
+ 'unsigned short int': 't',
+ 'int': 'i',
+ 'signed': 'i',
+ 'signed int': 'i',
+ 'unsigned': 'j',
+ 'unsigned int': 'j',
+ 'long': 'l',
+ 'long int': 'l',
+ 'signed long': 'l',
+ 'signed long int': 'l',
+ 'unsigned long': 'm',
+ 'unsigned long int': 'm',
+ 'long long': 'x',
+ 'long long int': 'x',
+ 'signed long long': 'x',
+ 'signed long long int': 'x',
+ 'unsigned long long': 'y',
+ 'unsigned long long int': 'y',
+ 'float': 'f',
+ 'double': 'd',
+ 'long double': 'e',
+ 'auto': 'Da',
+ 'decltype(auto)': 'Dc',
+ 'std::nullptr_t': 'Dn'
+}
+_id_operator = {
+ 'new': 'nw',
+ 'new[]': 'na',
+ 'delete': 'dl',
+ 'delete[]': 'da',
+ # the arguments will make the difference between unary and binary
+ # '+(unary)' : 'ps',
+ # '-(unary)' : 'ng',
+ # '&(unary)' : 'ad',
+ # '*(unary)' : 'de',
+ '~': 'co',
+ '+': 'pl',
+ '-': 'mi',
+ '*': 'ml',
+ '/': 'dv',
+ '%': 'rm',
+ '&': 'an',
+ '|': 'or',
+ '^': 'eo',
+ '=': 'aS',
+ '+=': 'pL',
+ '-=': 'mI',
+ '*=': 'mL',
+ '/=': 'dV',
+ '%=': 'rM',
+ '&=': 'aN',
+ '|=': 'oR',
+ '^=': 'eO',
+ '<<': 'ls',
+ '>>': 'rs',
+ '<<=': 'lS',
+ '>>=': 'rS',
+ '==': 'eq',
+ '!=': 'ne',
+ '<': 'lt',
+ '>': 'gt',
+ '<=': 'le',
+ '>=': 'ge',
+ '!': 'nt',
+ '&&': 'aa',
+ '||': 'oo',
+ '++': 'pp',
+ '--': 'mm',
+ ',': 'cm',
+ '->*': 'pm',
+ '->': 'pt',
+ '()': 'cl',
+ '[]': 'ix'
}
-class DefinitionError(Exception):
-
+class DefinitionError(UnicodeMixin, 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):
-
+class ASTBase(UnicodeMixin):
def __eq__(self, other):
if type(self) is not type(other):
return False
try:
- for key, value in self.__dict__.iteritems():
+ for key, value in iteritems(self.__dict__):
if value != getattr(other, key):
return False
except AttributeError:
@@ -139,7 +296,7 @@ class DefExpr(object):
def get_id(self):
"""Return the id for the node."""
- return u''
+ raise NotImplementedError(repr(self))
def get_name(self):
"""Return the name.
@@ -147,402 +304,748 @@ class DefExpr(object):
Returns either `None` or a node with a name you might call
:meth:`split_owner` on.
"""
- return None
+ raise NotImplementedError(repr(self))
- 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):
+ def prefix_nested_name(self, prefix):
"""Prefix a name node (a node returned by :meth:`get_name`)."""
- raise NotImplementedError()
-
- def __str__(self):
- return unicode(self).encode('utf-8')
+ raise NotImplementedError(repr(self))
def __unicode__(self):
- raise NotImplementedError()
+ raise NotImplementedError(repr(self))
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])
+def _verify_description_mode(mode):
+ if mode not in ('lastIsName', 'noneIsName', 'markType', 'param'):
+ raise Exception("Description mode '%s' is invalid." % mode)
-class NameDefExpr(PrimaryDefExpr):
-
- def __init__(self, name):
- self.name = name
+class ASTOperatorBuildIn(ASTBase):
+ def __init__(self, op):
+ self.op = op
def get_id(self):
- name = _id_shortwords.get(self.name)
- if name is not None:
- return name
- return self.name.replace(u' ', u'-')
+ if self.op not in _id_operator:
+ raise Exception('Internal error: Build-in operator "%s" can not '
+ 'be mapped to an id.' % self.op)
+ return _id_operator[self.op]
def __unicode__(self):
- return unicode(self.name)
-
-
-class PathDefExpr(PrimaryDefExpr):
+ if self.op in ('new', 'new[]', 'delete', 'delete[]'):
+ return u'operator ' + self.op
+ else:
+ return u'operator' + self.op
- def __init__(self, parts):
- self.path = parts
+ def get_name_no_template(self):
+ return text_type(self)
- def get_id(self):
- rv = u'::'.join(x.get_id() for x in self.path)
- return _id_shortwords.get(rv, rv)
+ def describe_signature(self, signode, mode, env, prefix):
+ _verify_description_mode(mode)
+ identifier = text_type(self)
+ if mode == 'lastIsName':
+ signode += addnodes.desc_name(identifier, identifier)
+ else:
+ signode += addnodes.desc_addname(identifier, identifier)
- 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)
+class ASTOperatorType(ASTBase):
+ def __init__(self, type):
+ self.type = type
def __unicode__(self):
- return u'::'.join(map(unicode, self.path))
+ return u''.join(['operator ', text_type(self.type)])
+ def get_id(self):
+ return u'cv' + self.type.get_id()
-class ArrayTypeSuffixDefExpr(object):
+ def get_name_no_template(self):
+ return text_type(self)
+
+ def describe_signature(self, signode, mode, env, prefix):
+ _verify_description_mode(mode)
+ identifier = text_type(self)
+ if mode == 'lastIsName':
+ signode += addnodes.desc_name(identifier, identifier)
+ else:
+ signode += addnodes.desc_addname(identifier, identifier)
- def __init__(self, size_hint=None):
- self.size_hint = size_hint
- def get_id_suffix(self):
- return 'A'
+class ASTTemplateArgConstant(ASTBase):
+ def __init__(self, value):
+ self.value = value
def __unicode__(self):
- return u'[%s]' % (
- self.size_hint is not None and unicode(self.size_hint) or u'',
- )
+ return text_type(self.value)
+ def get_id(self):
+ # TODO: doing this properly needs parsing of expressions, let's just
+ # juse it verbatim for now
+ return u'X' + text_type(self) + u'E'
-class TemplateDefExpr(PrimaryDefExpr):
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ signode += nodes.Text(text_type(self))
- 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)
+class ASTNestedNameElement(ASTBase):
+ def __init__(self, identifier, templateArgs):
+ self.identifier = identifier
+ self.templateArgs = templateArgs
def get_id(self):
- return u'%s:%s:' % (self.typename.get_id(),
- u'.'.join(x.get_id() for x in self.args))
+ res = []
+ if self.identifier == "std":
+ res.append(u'St')
+ else:
+ res.append(text_type(len(self.identifier)))
+ res.append(self.identifier)
+ if self.templateArgs:
+ res.append('I')
+ for a in self.templateArgs:
+ res.append(a.get_id())
+ res.append('E')
+ return u''.join(res)
def __unicode__(self):
- return u'%s<%s>' % (self.typename, u', '.join(map(unicode, self.args)))
-
-
-class ConstantTemplateArgExpr(PrimaryDefExpr):
+ res = []
+ res.append(self.identifier)
+ if self.templateArgs:
+ res.append('<')
+ first = True
+ for a in self.templateArgs:
+ if not first:
+ res.append(', ')
+ first = False
+ res.append(text_type(a))
+ res.append('>')
+ return u''.join(res)
+
+ def get_name_no_template(self):
+ return text_type(self.identifier)
+
+ def describe_signature(self, signode, mode, env, prefix):
+ _verify_description_mode(mode)
+ if mode == 'markType':
+ targetText = prefix + text_type(self)
+ pnode = addnodes.pending_xref(
+ '', refdomain='cpp', reftype='type',
+ reftarget=targetText, modname=None, classname=None)
+ if env: # during testing we don't have an env, do we?
+ pnode['cpp:parent'] = env.ref_context.get('cpp:parent')
+ pnode += nodes.Text(text_type(self.identifier))
+ signode += pnode
+ elif mode == 'lastIsName':
+ name = text_type(self.identifier)
+ signode += addnodes.desc_name(name, name)
+ else:
+ raise Exception('Unknown description mode: %s' % mode)
+ if self.templateArgs:
+ signode += nodes.Text('<')
+ first = True
+ for a in self.templateArgs:
+ if not first:
+ signode += nodes.Text(', ')
+ first = False
+ a.describe_signature(signode, 'markType', env)
+ signode += nodes.Text('>')
+
+
+class ASTNestedName(ASTBase):
+ def __init__(self, names):
+ """Use an empty string as the first name if it should start with '::'
+ """
+ self.names = names
- def __init__(self, arg):
- self.arg = arg
+ @property
+ def name(self):
+ return self
def get_id(self):
- return self.arg.replace(u' ', u'-')
+ res = []
+ if len(self.names) > 1:
+ res.append('N')
+ for n in self.names:
+ res.append(n.get_id())
+ if len(self.names) > 1:
+ res.append('E')
+ return u''.join(res)
+
+ def get_name_no_last_template(self):
+ res = u'::'.join([text_type(n) for n in self.names[:-1]])
+ if len(self.names) > 1:
+ res += '::'
+ res += self.names[-1].get_name_no_template()
+ return res
+
+ def prefix_nested_name(self, prefix):
+ if self.names[0] == '':
+ return self # it's defined at global namespace, don't tuch it
+ assert isinstance(prefix, ASTNestedName)
+ names = prefix.names[:]
+ names.extend(self.names)
+ return ASTNestedName(names)
def __unicode__(self):
- return unicode(self.arg)
+ return u'::'.join([text_type(n) for n in self.names])
+
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ if mode == 'lastIsName':
+ addname = u'::'.join([text_type(n) for n in self.names[:-1]])
+ if len(self.names) > 1:
+ addname += u'::'
+ name = text_type(self.names[-1])
+ signode += addnodes.desc_addname(addname, addname)
+ self.names[-1].describe_signature(signode, mode, env, '')
+ elif mode == 'noneIsName':
+ name = text_type(self)
+ signode += nodes.Text(name)
+ elif mode == 'param':
+ name = text_type(self)
+ signode += nodes.emphasis(name, name)
+ elif mode == 'markType':
+ # each element should be a pending xref targeting the complete
+ # prefix. however, only the identifier part should be a link, such
+ # that template args can be a link as well.
+ prefix = ''
+ first = True
+ for name in self.names:
+ if not first:
+ signode += nodes.Text('::')
+ prefix += '::'
+ first = False
+ if name != '':
+ name.describe_signature(signode, mode, env, prefix)
+ prefix += text_type(name)
+ else:
+ raise Exception('Unknown description mode: %s' % mode)
+
+class ASTTrailingTypeSpecFundamental(ASTBase):
+ def __init__(self, name):
+ self.name = name
-class WrappingDefExpr(DefExpr):
+ def __unicode__(self):
+ return self.name
- def __init__(self, typename):
- self.typename = typename
+ def get_id(self):
+ if self.name not in _id_fundamental:
+ raise Exception(
+ 'Semi-internal error: Fundamental type "%s" can not be mapped '
+ 'to an id. Is it a true fundamental type? If not so, the '
+ 'parser should have rejected it.' % self.name)
+ return _id_fundamental[self.name]
- def get_name(self):
- return self.typename.get_name()
+ def describe_signature(self, signode, mode, env):
+ signode += nodes.Text(text_type(self.name))
-class ModifierDefExpr(WrappingDefExpr):
+class ASTTrailingTypeSpecName(ASTBase):
+ def __init__(self, prefix, nestedName):
+ self.prefix = prefix
+ self.nestedName = nestedName
- def __init__(self, typename, modifiers):
- WrappingDefExpr.__init__(self, typename)
- self.modifiers = modifiers
+ @property
+ def name(self):
+ return self.nestedName
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)
+ return self.nestedName.get_id()
def __unicode__(self):
- return u' '.join(map(unicode, list(self.modifiers) + [self.typename]))
+ res = []
+ if self.prefix:
+ res.append(self.prefix)
+ res.append(' ')
+ res.append(text_type(self.nestedName))
+ return u''.join(res)
+
+ def describe_signature(self, signode, mode, env):
+ if self.prefix:
+ signode += addnodes.desc_annotation(self.prefix, self.prefix)
+ signode += nodes.Text(' ')
+ self.nestedName.describe_signature(signode, mode, env)
-class PtrDefExpr(WrappingDefExpr):
+class ASTFunctinoParameter(ASTBase):
+ def __init__(self, arg, ellipsis=False):
+ self.arg = arg
+ self.ellipsis = ellipsis
def get_id(self):
- return self.typename.get_id() + u'P'
+ if self.ellipsis:
+ return 'z'
+ else:
+ return self.arg.get_id()
def __unicode__(self):
- return u'%s*' % self.typename
+ if self.ellipsis:
+ return '...'
+ else:
+ return text_type(self.arg)
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ if self.ellipsis:
+ signode += nodes.Text('...')
+ else:
+ self.arg.describe_signature(signode, mode, env)
-class LValRefDefExpr(WrappingDefExpr):
- def get_id(self):
- return self.typename.get_id() + u'R'
+class ASTParametersQualifiers(ASTBase):
+ def __init__(self, args, volatile, const, refQual, exceptionSpec, override,
+ final, initializer):
+ self.args = args
+ self.volatile = volatile
+ self.const = const
+ self.refQual = refQual
+ self.exceptionSpec = exceptionSpec
+ self.override = override
+ self.final = final
+ self.initializer = initializer
+
+ def get_modifiers_id(self):
+ res = []
+ if self.volatile:
+ res.append('V')
+ if self.const:
+ res.append('K')
+ if self.refQual == '&&':
+ res.append('O')
+ elif self.refQual == '&':
+ res.append('R')
+ return u''.join(res)
+
+ def get_param_id(self):
+ if len(self.args) == 0:
+ return 'v'
+ else:
+ return u''.join(a.get_id() for a in self.args)
def __unicode__(self):
- return u'%s&' % self.typename
+ res = []
+ res.append('(')
+ first = True
+ for a in self.args:
+ if not first:
+ res.append(', ')
+ first = False
+ res.append(text_type(a))
+ res.append(')')
+ if self.volatile:
+ res.append(' volatile')
+ if self.const:
+ res.append(' const')
+ if self.refQual:
+ res.append(' ')
+ res.append(self.refQual)
+ if self.exceptionSpec:
+ res.append(' ')
+ res.append(text_type(self.exceptionSpec))
+ if self.final:
+ res.append(' final')
+ if self.override:
+ res.append(' override')
+ if self.initializer:
+ res.append(' = ')
+ res.append(self.initializer)
+ return u''.join(res)
+
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ paramlist = addnodes.desc_parameterlist()
+ for arg in self.args:
+ param = addnodes.desc_parameter('', '', noemph=True)
+ if mode == 'lastIsName': # i.e., outer-function params
+ arg.describe_signature(param, 'param', env)
+ else:
+ arg.describe_signature(param, 'markType', env)
+ paramlist += param
+ signode += paramlist
+
+ def _add_anno(signode, text):
+ signode += nodes.Text(' ')
+ signode += addnodes.desc_annotation(text, text)
+
+ def _add_text(signode, text):
+ signode += nodes.Text(' ' + text)
+
+ if self.volatile:
+ _add_anno(signode, 'volatile')
+ if self.const:
+ _add_anno(signode, 'const')
+ if self.refQual:
+ _add_text(signode, self.refQual)
+ if self.exceptionSpec:
+ _add_anno(signode, text_type(self.exceptionSpec))
+ if self.final:
+ _add_anno(signode, 'final')
+ if self.override:
+ _add_anno(signode, 'override')
+ if self.initializer:
+ _add_text(signode, '= ' + text_type(self.initializer))
-class RValRefDefExpr(WrappingDefExpr):
+class ASTDeclSpecs(ASTBase):
+ def __init__(self, outer, visibility, storage, inline, virtual, explicit,
+ constexpr, volatile, const, trailing):
+ self.outer = outer
+ self.visibility = visibility
+ self.storage = storage
+ self.inline = inline
+ self.virtual = virtual
+ self.explicit = explicit
+ self.constexpr = constexpr
+ self.volatile = volatile
+ self.const = const
+ self.trailingTypeSpec = trailing
+
+ @property
+ def name(self):
+ return self.trailingTypeSpec.name
def get_id(self):
- return self.typename.get_id() + u'RR'
+ res = []
+ if self.volatile:
+ res.append('V')
+ if self.const:
+ res.append('K')
+ res.append(self.trailingTypeSpec.get_id())
+ return u''.join(res)
+
+ def _print_visibility(self):
+ return (self.visibility and
+ not (
+ self.outer in ('type', 'member', 'function') and
+ self.visibility == 'public'))
def __unicode__(self):
- return u'%s&&' % self.typename
+ res = []
+ if self._print_visibility():
+ res.append(self.visibility)
+ if self.storage:
+ res.append(self.storage)
+ if self.inline:
+ res.append('inline')
+ if self.virtual:
+ res.append('virtual')
+ if self.explicit:
+ res.append('explicit')
+ if self.constexpr:
+ res.append('constexpr')
+ if self.volatile:
+ res.append('volatile')
+ if self.const:
+ res.append('const')
+ if self.trailingTypeSpec:
+ res.append(text_type(self.trailingTypeSpec))
+ return u' '.join(res)
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ modifiers = []
-class ConstDefExpr(WrappingDefExpr):
+ def _add(modifiers, text):
+ if len(modifiers) > 0:
+ modifiers.append(nodes.Text(' '))
+ modifiers.append(addnodes.desc_annotation(text, text))
+
+ if self._print_visibility():
+ _add(modifiers, self.visibility)
+ if self.storage:
+ _add(modifiers, self.storage)
+ if self.inline:
+ _add(modifiers, 'inline')
+ if self.virtual:
+ _add(modifiers, 'virtual')
+ if self.explicit:
+ _add(modifiers, 'explicit')
+ if self.constexpr:
+ _add(modifiers, 'constexpr')
+ if self.volatile:
+ _add(modifiers, 'volatile')
+ if self.const:
+ _add(modifiers, 'const')
+ for m in modifiers:
+ signode += m
+ if self.trailingTypeSpec:
+ if len(modifiers) > 0:
+ signode += nodes.Text(' ')
+ self.trailingTypeSpec.describe_signature(signode, mode, env)
- def __init__(self, typename, prefix=False):
- WrappingDefExpr.__init__(self, typename)
- self.prefix = prefix
- def get_id(self):
- return self.typename.get_id() + u'C'
+class ASTPtrOpPtr(ASTBase):
+ def __init__(self, volatile, const):
+ self.volatile = volatile
+ self.const = const
def __unicode__(self):
- return (self.prefix and u'const %s' or u'%s const') % self.typename
+ res = ['*']
+ if self.volatile:
+ res.append('volatile ')
+ if self.const:
+ res.append('const ')
+ return u''.join(res)
+ def get_id(self):
+ res = ['P']
+ if self.volatile:
+ res.append('V')
+ if self.const:
+ res.append('C')
+ return u''.join(res)
-class CastOpDefExpr(PrimaryDefExpr):
- def __init__(self, typename):
- self.typename = typename
+class ASTPtrOpRef(ASTBase):
+ def __unicode__(self):
+ return '&'
def get_id(self):
- return u'castto-%s-operator' % self.typename.get_id()
+ return 'R'
+
+class ASTPtrOpParamPack(ASTBase):
def __unicode__(self):
- return u'operator %s' % self.typename
+ return '...'
+ def get_id(self):
+ return 'Dp'
-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
+class ASTArray(ASTBase):
+ def __init__(self, size):
+ self.size = size
- def get_name(self):
- return self.name.get_name()
+ def __unicode__(self):
+ return u''.join(['[', text_type(self.size), ']'])
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)
+ # TODO: this should maybe be done differently
+ return u'A' + text_type(self.size) + u'_'
- 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)
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ signode += nodes.Text(text_type(self))
-class NamedDefExpr(DefExpr):
+class ASTDeclerator(ASTBase):
+ def __init__(self, ptrOps, declId, suffixOps):
+ self.ptrOps = ptrOps
+ self.declId = declId
+ self.suffixOps = suffixOps
- def __init__(self, name, visibility, static):
- self.name = name
- self.visibility = visibility
- self.static = static
+ @property
+ def name(self):
+ return self.declId
+
+ def get_modifiers_id(self): # only the modifiers for a function, e.g.,
+ # cv-qualifiers
+ for op in self.suffixOps:
+ if isinstance(op, ASTParametersQualifiers):
+ return op.get_modifiers_id()
+ raise Exception(
+ "This should only be called on a function: %s" % text_type(self))
+
+ def get_param_id(self): # only the parameters (if any)
+ for op in self.suffixOps:
+ if isinstance(op, ASTParametersQualifiers):
+ return op.get_param_id()
+ return ''
- 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
+ def get_ptr_suffix_id(self): # only the ptr ops and array specifiers
+ return u''.join(
+ a.get_id()
+ for a in self.ptrOps + self.suffixOps
+ if not isinstance(a, ASTParametersQualifiers))
+
+ def require_start_space(self):
+ if (len(self.ptrOps) > 0 and
+ isinstance(self.ptrOps[-1], ASTPtrOpParamPack)):
+ return False
+ else:
+ return self.declId is not None
+
+ def __unicode__(self):
+ res = []
+ for op in self.ptrOps:
+ res.append(text_type(op))
+ if isinstance(op, ASTPtrOpParamPack) and self.declId:
+ res.append(' ')
+ if self.declId:
+ res.append(text_type(self.declId))
+ for op in self.suffixOps:
+ res.append(text_type(op))
+ return u''.join(res)
+
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ for op in self.ptrOps:
+ signode += nodes.Text(text_type(op))
+ if isinstance(op, ASTPtrOpParamPack) and self.declId:
+ signode += nodes.Text(' ')
+ if self.declId:
+ self.declId.describe_signature(signode, mode, env)
+ for op in self.suffixOps:
+ op.describe_signature(signode, mode, env)
+
+
+class ASTInitializer(ASTBase):
+ def __init__(self, value):
+ self.value = value
+
+ def __unicode__(self):
+ return u''.join([' = ', text_type(self.value)])
+ def describe_signature(self, signode, mode):
+ _verify_description_mode(mode)
+ signode += nodes.Text(text_type(self))
-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
+class ASTType(ASTBase):
+ def __init__(self, declSpecs, decl):
+ self.declSpecs = declSpecs
+ self.decl = decl
+ self.objectType = None
+
+ @property
+ def name(self):
+ name = self.decl.name
+ if not name:
+ name = self.declSpecs.name
+ return name
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)
+ res = []
+ if self.objectType: # needs the name
+ res.append(_id_prefix)
+ if self.objectType == 'function': # also modifiers
+ res.append(self.decl.get_modifiers_id())
+ res.append(self.prefixedName.get_id())
+ res.append(self.decl.get_param_id())
+ elif self.objectType == 'type': # just the name
+ res.append(self.prefixedName.get_id())
+ else:
+ print(self.objectType)
+ assert False
+ else: # only type encoding
+ res.append(self.decl.get_ptr_suffix_id())
+ res.append(self.declSpecs.get_id())
+ res.append(self.decl.get_param_id())
+ return u''.join(res)
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)
+ res = []
+ declSpecs = text_type(self.declSpecs)
+ res.append(declSpecs)
+ if self.decl.require_start_space() and len(declSpecs) > 0:
+ res.append(u' ')
+ res.append(text_type(self.decl))
+ return u''.join(res)
+
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ self.declSpecs.describe_signature(signode, 'markType', env)
+ if (self.decl.require_start_space() and
+ len(text_type(self.declSpecs)) > 0):
+ signode += nodes.Text(' ')
+ self.decl.describe_signature(signode, mode, env)
-class MemberObjDefExpr(NamedDefExpr):
+class ASTTypeWithInit(ASTBase):
+ def __init__(self, type, init):
+ self.objectType = None
+ self.type = type
+ self.init = init
- 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
+ @property
+ def name(self):
+ return self.type.name
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)
+ if self.objectType == 'member':
+ return _id_prefix + self.prefixedName.get_id()
+ else:
+ return self.type.get_id()
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)
+ res = []
+ res.append(text_type(self.type))
+ if self.init:
+ res.append(text_type(self.init))
+ return u''.join(res)
- 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 describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ self.type.describe_signature(signode, mode, env)
+ if self.init:
+ self.init.describe_signature(signode, mode)
- 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 ASTBaseClass(ASTBase):
+ def __init__(self, name, visibility):
+ self.name = name
+ self.visibility = visibility
+
+ def __unicode__(self):
+ res = []
+ if self.visibility != 'private':
+ res.append(self.visibility)
+ res.append(' ')
+ res.append(text_type(self.name))
+ return u''.join(res)
+
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ if self.visibility != 'private':
+ signode += addnodes.desc_annotation(
+ self.visibility, self.visibility)
+ signode += nodes.Text(' ')
+ self.name.describe_signature(signode, mode, env)
-class ClassDefExpr(NamedDefExpr):
- def __init__(self, name, visibility, static, bases):
- NamedDefExpr.__init__(self, name, visibility, static)
+class ASTClass(ASTBase):
+ def __init__(self, name, bases):
+ self.name = name
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)
+ return _id_prefix + self.prefixedName.get_id()
def __unicode__(self):
- return self._tostring('public')
+ res = []
+ res.append(text_type(self.name))
+ if len(self.bases) > 0:
+ res.append(' : ')
+ first = True
+ for b in self.bases:
+ if not first:
+ res.append(', ')
+ first = False
+ res.append(text_type(b))
+ return u''.join(res)
+
+ def describe_signature(self, signode, mode, env):
+ _verify_description_mode(mode)
+ self.name.describe_signature(signode, mode, env)
+ if len(self.bases) > 0:
+ signode += nodes.Text(' : ')
+ for b in self.bases:
+ b.describe_signature(signode, mode, env)
+ signode += nodes.Text(', ')
+ signode.pop()
+
class DefinitionParser(object):
+ # those without signedness and size modifiers
+ # see http://en.cppreference.com/w/cpp/language/types
+ _simple_fundemental_types = (
+ 'void', 'bool', 'char', 'wchar_t', 'char16_t', 'char32_t', 'int',
+ 'float', 'double', 'auto'
+ )
- # 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'))
- }
+ _prefix_keys = ('class', 'struct', 'union', 'typename')
def __init__(self, definition):
self.definition = definition.strip()
@@ -552,8 +1055,10 @@ class DefinitionParser(object):
self._previous_state = (0, None)
def fail(self, msg):
- raise DefinitionError('Invalid definition: %s [error at %d]\n %s' %
- (msg, self.pos, self.definition))
+ indicator = '-' * self.pos + '^'
+ raise DefinitionError(
+ 'Invalid definition: %s [error at %d]\n %s\n %s' %
+ (msg, self.pos, self.definition, indicator))
def match(self, regex):
match = regex.match(self.definition, self.pos)
@@ -602,379 +1107,527 @@ class DefinitionParser(object):
if self.last_match is not None:
return self.last_match.group()
+ 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:])
+
def _parse_operator(self):
self.skip_ws()
+ # adapted from the old code
# thank god, a regular operator definition
if self.match(_operator_re):
- return NameDefExpr('operator' +
- _whitespace_re.sub('', self.matched_text))
+ return ASTOperatorBuildIn(self.matched_text)
# new/delete operator?
- for allocop in 'new', 'delete':
- if not self.skip_word(allocop):
+ for op in 'new', 'delete':
+ if not self.skip_word(op):
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)
+ self.fail('Expected "]" after "operator ' + op + '["')
+ op += '[]'
+ return ASTOperatorBuildIn(op)
# 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
+ return ASTOperatorType(type)
- def _peek_const(self, path):
- try:
- path.remove('const')
- return True
- except ValueError:
- return False
+ def _parse_nested_name(self):
+ names = []
- def _parse_builtin(self, modifiers):
- modifier = modifiers[-1]
- path = modifiers
- following = self._modifiers[modifier]
+ self.skip_ws()
+ if self.skip_string('::'):
+ names.append(u'')
while 1:
self.skip_ws()
+ # TODO: parse the "template" keyword
if not self.match(_identifier_re):
- break
+ self.fail("expected identifier")
identifier = self.matched_text
- if identifier in following:
- path.append(identifier)
- following = self._modifiers[modifier]
- assert following
+ if identifier == 'operator':
+ op = self._parse_operator()
+ names.append(op)
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
+ templateArgs = None
+ self.skip_ws()
+ if self.skip_string('<'):
+ templateArgs = []
+ while 1:
+ pos = self.pos
+ try:
+ type = self._parse_type(allowParams=True)
+ templateArgs.append(type)
+ except DefinitionError:
+ self.pos = pos
+ symbols = []
+ startPos = self.pos
+ self.skip_ws()
+ if self.match(_string_re):
+ value = self.matched_text
+ else:
+ while not self.eof:
+ if (len(symbols) == 0 and
+ self.current_char in (
+ ',', '>')):
+ break
+ # TODO: actually implement nice handling
+ # of quotes, braces, brackets, parens, and
+ # whatever
+ self.pos += 1
+ if self.eof:
+ self.pos = startPos
+ self.fail(
+ 'Could not find end of constant '
+ 'template argument.')
+ value = self.definition[startPos:self.pos].strip()
+ templateArgs.append(ASTTemplateArgConstant(value))
+ self.skip_ws()
+ if self.skip_string('>'):
+ break
+ elif self.skip_string(','):
+ continue
+ else:
+ self.fail('Expected ">" or "," in template '
+ 'argument list.')
+ names.append(ASTNestedNameElement(identifier, templateArgs))
- args = []
- while 1:
self.skip_ws()
- if self.skip_string('>'):
+ if not 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)
+ return ASTNestedName(names)
- def _parse_type(self, in_template=False):
+ def _parse_trailing_type_spec(self):
+ # fundemental types
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
+ for t in self._simple_fundemental_types:
+ if self.skip_word(t):
+ return ASTTrailingTypeSpecFundamental(t)
+ # TODO: this could/should be more strict
+ elements = []
+ self.skip_ws()
+ if self.skip_word_and_ws('signed'):
+ elements.append('signed')
+ elif self.skip_word_and_ws('unsigned'):
+ elements.append('unsigned')
while 1:
- self.skip_ws()
- if (in_template and self.current_char in ',>') or \
- (result and not self.skip_string('::')) or \
- self.eof:
+ if self.skip_word_and_ws('short'):
+ elements.append('short')
+ elif self.skip_word_and_ws('long'):
+ elements.append('long')
+ else:
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)
+ if self.skip_word_and_ws('int'):
+ elements.append('int')
+ elif self.skip_word_and_ws('double'):
+ elements.append('double')
+ if len(elements) > 0:
+ return ASTTrailingTypeSpecFundamental(u' '.join(elements))
+
+ # decltype
+ self.skip_ws()
+ if self.skip_word_and_ws('decltype'):
+ self.fail('"decltype(.)" in trailing_type_spec not implemented')
- def _parse_default_expr(self):
+ # prefixed
+ prefix = None
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:
+ for k in self._prefix_keys:
+ if self.skip_word_and_ws(k):
+ prefix = k
break
- self.pos = idx+1
- rv = self.definition[rv_start:idx]
- self.pos = idx
- return rv
+ nestedName = self._parse_nested_name()
+ return ASTTrailingTypeSpecName(prefix, nestedName)
- def _parse_signature(self):
+ def _parse_parameters_and_qualifiers(self, paramMode):
self.skip_ws()
if not self.skip_string('('):
- self.fail('expected parentheses for function')
-
+ if paramMode == 'function':
+ self.fail('Expecting "(" in parameters_and_qualifiers.')
+ else:
+ return None
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 not self.skip_string(')'):
+ while 1:
self.skip_ws()
-
- if self.skip_string('...'):
- args.append(ArgumentDefExpr(None, '...', [], None))
- if self.skip_string(')'):
+ if self.skip_string('...'):
+ args.append(ASTFunctinoParameter(None, True))
+ self.skip_ws()
+ if not self.skip_string(')'):
+ self.fail('Expected ")" after "..." in '
+ 'parameters_and_qualifiers.')
break
+ if paramMode == 'function':
+ arg = self._parse_type_with_init(named='maybe')
else:
- self.fail('expected closing parenthesis after ellipses')
+ arg = self._parse_type()
+ # TODO: parse default parameters
+ args.append(ASTFunctinoParameter(arg))
- 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))
+ if self.skip_string(','):
+ continue
+ elif self.skip_string(')'):
+ break
+ else:
+ self.fail(
+ 'Expecting "," or ")" in parameters_and_qualifiers, '
+ 'got "%s".' % self.current_char)
+
+ if paramMode != 'function':
+ return ASTParametersQualifiers(
+ args, None, None, None, None, None, None, None)
+
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)
+ const = self.skip_word_and_ws('const')
+ volatile = self.skip_word_and_ws('volatile')
+ if not const: # the can be permuted
+ const = self.skip_word_and_ws('const')
+ refQual = None
if self.skip_string('&&'):
- attributes['rvalue_this'] = True
- if self.skip_string('&'):
- attributes['lvalue_this'] = True
+ refQual = '&&'
+ if not refQual and self.skip_string('&'):
+ refQual = '&'
+
+ exceptionSpec = None
+ override = None
+ final = None
+ initializer = None
+ self.skip_ws()
+ if self.skip_string('noexcept'):
+ exceptionSpec = 'noexcept'
+ self.skip_ws()
+ if self.skip_string('('):
+ self.fail('Parameterised "noexcept" not implemented.')
- if attributes['lvalue_this'] and attributes['rvalue_this']:
- self.fail('rvalue reference for *this specifier must be one of'
- '"&&" or "&"')
+ self.skip_ws()
+ override = self.skip_word_and_ws('override')
+ final = self.skip_word_and_ws('final')
+ if not override:
+ override = self.skip_word_and_ws(
+ 'override') # they can be permuted
+ self.skip_ws()
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()
+ valid = ('0', 'delete', 'default')
+ for w in valid:
+ if self.skip_word_and_ws(w):
+ initializer = w
+ break
+ if not initializer:
+ self.fail(
+ 'Expected "%s" in initializer-specifier.'
+ % u'" or "'.join(valid))
- 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()
+ return ASTParametersQualifiers(
+ args, volatile, const, refQual, exceptionSpec, override, final,
+ initializer)
+
+ def _parse_decl_specs(self, outer, typed=True):
+ """
+ visibility storage-class-specifier function-specifier "constexpr"
+ "volatile" "const" trailing-type-specifier
+
+ storage-class-specifier -> "static" (only for member_object and
+ function_object)
+
+ function-specifier -> "inline" | "virtual" | "explicit" (only for
+ function_object)
+
+ "constexpr" (only for member_object and function_object)
+ """
+ visibility = None
+ storage = None
+ inline = None
+ virtual = None
+ explicit = None
+ constexpr = None
+ volatile = None
+ const = None
+
+ if outer:
+ self.skip_ws()
+ if self.match(_visibility_re):
+ visibility = self.matched_text
+
+ while 1: # accept any permutation of a subset of some decl-specs
+ self.skip_ws()
+ if not storage:
+ if outer in ('member', 'function'):
+ if self.skip_word('static'):
+ storage = 'static'
+ continue
+ if outer == 'member':
+ if self.skip_word('mutable'):
+ storage = 'mutable'
+ continue
+ if outer == 'fuction':
+ # TODO: maybe in more contexts, missing test cases
+ if self.skip_word('register'):
+ storage = 'register'
+ continue
+
+ if outer == 'function':
+ # function-specifiers
+ if not inline:
+ inline = self.skip_word('inline')
+ if inline:
+ continue
+ if not virtual:
+ virtual = self.skip_word('virtual')
+ if virtual:
+ continue
+ if not explicit:
+ explicit = self.skip_word('explicit')
+ if explicit:
+ continue
+
+ if not constexpr and outer in ('member', 'function'):
+ constexpr = self.skip_word("constexpr")
+ if constexpr:
+ continue
+ if not volatile and typed:
+ volatile = self.skip_word('volatile')
+ if volatile:
+ continue
+ if not const and typed:
+ const = self.skip_word('const')
+ if const:
+ continue
+ break
+
+ if typed:
+ trailing = self._parse_trailing_type_spec()
else:
- name = typename
- typename = None
- type_suffixes = []
- return TypeObjDefExpr(name, visibility, static, typename, type_suffixes)
+ trailing = None
+ return ASTDeclSpecs(
+ outer, visibility, storage, inline, virtual, explicit, constexpr,
+ volatile, const, trailing)
+
+ def _parse_declerator(self, named, paramMode=None, typed=True):
+ if paramMode:
+ if paramMode not in ('type', 'function'):
+ raise Exception(
+ "Internal error, unknown paramMode '%s'." % paramMode)
+ ptrOps = []
+ while 1:
+ if not typed:
+ break
+ self.skip_ws()
+ if self.skip_string('*'):
+ self.skip_ws()
+ volatile = self.skip_word_and_ws('volatile')
+ const = self.skip_word_and_ws('const')
+ ptrOps.append(ASTPtrOpPtr(volatile=volatile, const=const))
+ elif self.skip_string('&'):
+ ptrOps.append(ASTPtrOpRef())
+ elif self.skip_string('...'):
+ ptrOps.append(ASTPtrOpParamPack())
+ break
+ else:
+ break
- 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()
+ if named == 'maybe':
+ try:
+ declId = self._parse_nested_name()
+ except DefinitionError:
+ declId = None
+ elif named:
+ declId = self._parse_nested_name()
else:
- value = None
- return MemberObjDefExpr(name, visibility, static, typename,
- type_suffixes, value)
+ declId = None
+
+ suffixOpts = []
+ while 1:
+ self.skip_ws()
+ if typed and self.skip_string('['):
+ startPos = self.pos - 1
+ openCount = 1
+ while not self.eof:
+ c = self.current_char
+ if c == '[':
+ openCount += 1
+ elif c == ']':
+ openCount -= 1
+ if openCount == 0:
+ break
+ self.pos += 1
+ if self.eof:
+ self.pos = startPos
+ self.fail(
+ "Could not find closing square bracket for array.")
+ self.pos += 1
+ suffixOpts.append(ASTArray(
+ self.definition[startPos + 1:self.pos - 1].strip()))
+ continue
+ if paramMode:
+ paramQual = self._parse_parameters_and_qualifiers(paramMode)
+ if paramQual:
+ suffixOpts.append(paramQual)
+ break
- def parse_function(self):
- visibility, static = self._parse_visibility_static()
- explicit = self.skip_word_and_ws('explicit')
- constexpr = self.skip_word_and_ws('constexpr')
+ return ASTDeclerator(ptrOps, declId, suffixOpts)
- rv = self._parse_type()
+ def _parse_initializer(self, outer=None):
self.skip_ws()
- # some things just don't have return values
- if self.current_char == '(':
- name = rv
- rv = None
+ # TODO: support paren and brace initialization for memberObject
+ if not self.skip_string('='):
+ return None
else:
- name = self._parse_type()
- return FuncDefExpr(name, visibility, static, explicit, constexpr, rv,
- **self._parse_signature())
+ if outer == 'member':
+ value = self.read_rest().strip()
+ return ASTInitializer(value)
+ elif outer is None: # function parameter
+ symbols = []
+ startPos = self.pos
+ self.skip_ws()
+ if self.match(_string_re):
+ value = self.matched_text
+ return ASTInitializer(value)
+ while not self.eof:
+ if len(symbols) == 0 and self.current_char in (',', ')'):
+ break
+ elif len(symbols) > 0 and self.current_char == symbols[-1]:
+ symbols.pop()
+ elif self.current_char == '(':
+ symbols.append(')')
+ # TODO: actually implement nice handling of quotes, braces,
+ # brackets, parens, and whatever
+ self.pos += 1
+ if self.eof:
+ self.pos = startPos
+ self.fail(
+ 'Could not find end of default value for function '
+ 'parameter.')
+ value = self.definition[startPos:self.pos].strip()
+ return ASTInitializer(value)
+ else:
+ self.fail(
+ "Internal error, initializer for outer '%s' not "
+ "implemented." % outer)
- def parse_class(self):
- visibility, static = self._parse_visibility_static()
- name = self._parse_type()
+ def _parse_type(self, outer=None, named=False, allowParams=False):
+ """
+ named=False|'maybe'|True: 'maybe' is e.g., for function objects which
+ doesn't need to name the arguments
+ """
+ if outer: # always named
+ if outer not in ('type', 'member', 'function'):
+ raise Exception('Internal error, unknown outer "%s".' % outer)
+ assert not named
+
+ if outer in ('type', 'function'):
+ # We allow type objects to just be a name.
+ # Some functions don't have normal return types: constructors,
+ # destrutors, cast operators
+ startPos = self.pos
+ # first try without the type
+ try:
+ declSpecs = self._parse_decl_specs(outer=outer, typed=False)
+ decl = self._parse_declerator(named=True, paramMode=outer,
+ typed=False)
+ self.assert_end()
+ except DefinitionError as exUntyped:
+ self.pos = startPos
+ try:
+ declSpecs = self._parse_decl_specs(outer=outer)
+ decl = self._parse_declerator(named=True, paramMode=outer)
+ except DefinitionError as exTyped:
+ if outer == 'type':
+ raise DefinitionError(
+ 'Type must be either just a name or a '
+ 'typedef-like declaration.\nJust a name error: '
+ '%s\nTypedef-like expression error: %s'
+ % (exUntyped.description, exTyped.description))
+ else:
+ # do it again to get the proper traceback (how do you
+ # relieable save a traceback when an exception is
+ # constructed?)
+ self.pos = startPos
+ declSpecs = self._parse_decl_specs(outer=outer)
+ decl = self._parse_declerator(named=True,
+ paramMode=outer)
+ else:
+ if outer:
+ named = True
+ allowParams = True
+ if allowParams:
+ paramMode = 'type'
+ else:
+ paramMode = None
+ declSpecs = self._parse_decl_specs(outer=outer)
+ decl = self._parse_declerator(named=named, paramMode=paramMode)
+ return ASTType(declSpecs, decl)
+
+ def _parse_type_with_init(self, outer=None, named=False):
+ if outer:
+ assert outer in ('type', 'member', 'function')
+ type = self._parse_type(outer=outer, named=named)
+ init = self._parse_initializer(outer=outer)
+ return ASTTypeWithInit(type, init)
+
+ def _parse_class(self):
+ name = self._parse_nested_name()
bases = []
+ self.skip_ws()
if self.skip_string(':'):
- self.skip_ws()
while 1:
- access = 'private'
+ self.skip_ws()
+ visibility = 'private'
if self.match(_visibility_re):
- access = self.matched_text
- base = self._parse_type()
- bases.append(ClassDefExpr(base, access, False, []))
+ visibility = self.matched_text
+ baseName = self._parse_nested_name()
+ bases.append(ASTBaseClass(baseName, visibility))
+ self.skip_ws()
if self.skip_string(','):
- self.skip_ws()
+ continue
else:
break
- return ClassDefExpr(name, visibility, static, bases)
+ return ASTClass(name, bases)
- def read_rest(self):
- rv = self.definition[self.pos:]
- self.pos = self.end
- return rv
+ def parse_type_object(self):
+ res = self._parse_type(outer='type')
+ res.objectType = 'type'
+ return res
- def assert_end(self):
- self.skip_ws()
- if not self.eof:
- self.fail('expected end of definition, got %r' %
- self.definition[self.pos:])
+ def parse_member_object(self):
+ res = self._parse_type_with_init(outer='member')
+ res.objectType = 'member'
+ return res
+
+ def parse_function_object(self):
+ res = self._parse_type(outer='function')
+ res.objectType = 'function'
+ return res
+
+ def parse_class_object(self):
+ res = self._parse_class()
+ res.objectType = 'class'
+ return res
+
+ def parse_namespace_object(self):
+ res = self._parse_nested_name()
+ res.objectType = 'namespace'
+ return res
+
+ def parse_xref_object(self):
+ res = self._parse_nested_name()
+ res.objectType = 'xref'
+ return res
class CPPObject(ObjectDescription):
@@ -991,214 +1644,120 @@ class CPPObject(ObjectDescription):
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)
+ def add_target_and_index(self, ast, sig, signode):
+ theid = ast.get_id()
+ name = text_type(ast.prefixedName)
if theid not in self.state.document.ids:
- signode['names'].append(theid)
+ # the name is not unique, the first one will win
+ objects = self.env.domaindata['cpp']['objects']
+ if name not in objects:
+ signode['names'].append(name)
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))
+ if name not in objects:
+ objects.setdefault(name,
+ (self.env.docname, ast.objectType, theid))
+ # add the uninstantiated template if it doesn't exist
+ uninstantiated = ast.prefixedName.get_name_no_last_template()
+ if uninstantiated != name and uninstantiated not in objects:
+ signode['names'].append(uninstantiated)
+ objects.setdefault(uninstantiated, (
+ self.env.docname, ast.objectType, theid))
+ self.env.ref_context['cpp:lastname'] = ast.prefixedName
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
+ if not re.compile(r'^[a-zA-Z0-9_]*$').match(theid):
+ self.state_machine.reporter.warning(
+ 'Index id generation for C++ object "%s" failed, please '
+ 'report as bug (id=%s).' % (text_type(ast), theid),
+ line=self.lineno)
+ self.indexnode['entries'].append(('single', indextext, theid, ''))
def parse_definition(self, parser):
raise NotImplementedError()
- def describe_signature(self, signode, arg):
+ def describe_signature(self, signode, ast):
raise NotImplementedError()
def handle_signature(self, sig, signode):
parser = DefinitionParser(sig)
try:
- rv = self.parse_definition(parser)
+ ast = self.parse_definition(parser)
parser.assert_end()
- except DefinitionError, e:
- self.state_machine.reporter.warning(e.description, line=self.lineno)
+ except DefinitionError as 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()
+ self.describe_signature(signode, ast)
- 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
+ parent = self.env.ref_context.get('cpp:parent')
+ if parent and len(parent) > 0:
+ ast = ast.clone()
+ ast.prefixedName = ast.name.prefix_nested_name(parent[-1])
+ else:
+ ast.prefixedName = ast.name
+ return ast
class CPPTypeObject(CPPObject):
-
def get_index_text(self, name):
- if self.objtype == 'type':
- return _('%s (C++ type)') % name
- return ''
+ return _('%s (C++ type)') % name
def parse_definition(self, parser):
return parser.parse_type_object()
- def describe_signature(self, signode, obj):
- self.attach_modifiers(signode, obj)
+ def describe_signature(self, signode, ast):
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)
+ ast.describe_signature(signode, 'lastIsName', self.env)
class CPPMemberObject(CPPObject):
-
def get_index_text(self, name):
- if self.objtype == 'member':
- return _('%s (C++ member)') % name
- return ''
+ return _('%s (C++ member)') % name
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)
+ def describe_signature(self, signode, ast):
+ ast.describe_signature(signode, 'lastIsName', self.env)
class CPPFunctionObject(CPPObject):
+ def get_index_text(self, name):
+ return _('%s (C++ function)') % name
- 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)
+ def parse_definition(self, parser):
+ return parser.parse_function_object()
- 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
+ def describe_signature(self, signode, ast):
+ ast.describe_signature(signode, 'lastIsName', self.env)
- 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')
+class CPPClassObject(CPPObject):
def get_index_text(self, name):
- return _('%s (C++ function)') % name
+ return _('%s (C++ class)') % name
+
+ def before_content(self):
+ lastname = self.env.ref_context['cpp:lastname']
+ assert lastname
+ if 'cpp:parent' in self.env.ref_context:
+ self.env.ref_context['cpp:parent'].append(lastname)
+ else:
+ self.env.ref_context['cpp:parent'] = [lastname]
+
+ def after_content(self):
+ self.env.ref_context['cpp:parent'].pop()
def parse_definition(self, parser):
- return parser.parse_function()
+ return parser.parse_class_object()
- 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)
+ def describe_signature(self, signode, ast):
+ signode += addnodes.desc_annotation('class ', 'class ')
+ ast.describe_signature(signode, 'lastIsName', self.env)
-class CPPCurrentNamespace(Directive):
+class CPPNamespaceObject(Directive):
"""
This directive is just to tell Sphinx that we're documenting stuff in
namespace foo.
@@ -1213,26 +1772,27 @@ class CPPCurrentNamespace(Directive):
def run(self):
env = self.state.document.settings.env
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
- env.temp_data['cpp:prefix'] = None
+ env.ref_context['cpp:parent'] = []
else:
parser = DefinitionParser(self.arguments[0])
try:
- prefix = parser.parse_type()
+ prefix = parser.parse_namespace_object()
parser.assert_end()
- except DefinitionError, e:
+ except DefinitionError as e:
self.state_machine.reporter.warning(e.description,
line=self.lineno)
else:
- env.temp_data['cpp:prefix'] = prefix
+ env.ref_context['cpp:parent'] = [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')
+ parent = env.ref_context.get('cpp:parent')
+ if parent:
+ refnode['cpp:parent'] = parent[:]
if not has_explicit_title:
- target = target.lstrip('~') # only has a meaning for the 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] == '~':
@@ -1248,70 +1808,89 @@ class CPPDomain(Domain):
name = 'cpp'
label = 'C++'
object_types = {
- 'class': ObjType(l_('class'), 'class'),
+ 'class': ObjType(l_('class'), 'class'),
'function': ObjType(l_('function'), 'func'),
- 'member': ObjType(l_('member'), 'member'),
- 'type': ObjType(l_('type'), 'type')
+ 'member': ObjType(l_('member'), 'member'),
+ 'type': ObjType(l_('type'), 'type')
}
directives = {
- 'class': CPPClassObject,
- 'function': CPPFunctionObject,
- 'member': CPPMemberObject,
- 'type': CPPTypeObject,
- 'namespace': CPPCurrentNamespace
+ 'class': CPPClassObject,
+ 'function': CPPFunctionObject,
+ 'member': CPPMemberObject,
+ 'type': CPPTypeObject,
+ 'namespace': CPPNamespaceObject
}
roles = {
- 'class': CPPXRefRole(),
- 'func' : CPPXRefRole(fix_parens=True),
+ 'class': CPPXRefRole(),
+ 'func': CPPXRefRole(fix_parens=True),
'member': CPPXRefRole(),
- 'type': CPPXRefRole()
+ 'type': CPPXRefRole()
}
initial_data = {
- 'objects': {}, # fullname -> docname, objtype
+ 'objects': {}, # prefixedName -> (docname, objectType, id)
}
def clear_doc(self, docname):
- for fullname, (fn, _, _) in self.data['objects'].items():
- if fn == docname:
+ for fullname, data in list(self.data['objects'].items()):
+ if data[0] == docname:
del self.data['objects'][fullname]
- def resolve_xref(self, env, fromdocname, builder,
- typ, target, node, contnode):
- def _create_refnode(expr):
- name = unicode(expr)
+ def merge_domaindata(self, docnames, otherdata):
+ # XXX check duplicates
+ for fullname, data in otherdata['objects'].items():
+ if data[0] in docnames:
+ self.data['objects'][fullname] = data
+
+ def _resolve_xref_inner(self, env, fromdocname, builder,
+ target, node, contnode, warn=True):
+ def _create_refnode(nameAst):
+ name = text_type(nameAst)
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)
+ # try dropping the last template
+ name = nameAst.get_name_no_last_template()
+ if name not in self.data['objects']:
+ return None, None
+ docname, objectType, id = self.data['objects'][name]
+ return make_refnode(builder, fromdocname, docname, id, contnode,
+ name), objectType
parser = DefinitionParser(target)
try:
- expr = parser.parse_type().get_name()
+ nameAst = parser.parse_xref_object().name
parser.skip_ws()
- if not parser.eof or expr is None:
+ if not parser.eof:
raise DefinitionError('')
except DefinitionError:
- env.warn_node('unparseable C++ definition: %r' % target, node)
- return None
-
- parent = node.get('cpp:parent', None)
+ if warn:
+ env.warn_node('unparseable C++ definition: %r' % target, node)
+ return None, None
- rv = _create_refnode(expr)
- if rv is not None or parent is None:
- return rv
- parent = parent.get_name()
+ # try as is the name is fully qualified
+ res = _create_refnode(nameAst)
+ if res[0]:
+ return res
- rv = _create_refnode(expr.prefix(parent))
- if rv is not None:
- return rv
+ # try qualifying it with the parent
+ parent = node.get('cpp:parent', None)
+ if parent and len(parent) > 0:
+ return _create_refnode(nameAst.prefix_nested_name(parent[-1]))
+ else:
+ return None, None
- parent, name = parent.split_owner()
- return _create_refnode(expr.prefix(parent))
+ def resolve_xref(self, env, fromdocname, builder,
+ typ, target, node, contnode):
+ return self._resolve_xref_inner(env, fromdocname, builder, target, node,
+ contnode)[0]
+
+ def resolve_any_xref(self, env, fromdocname, builder, target,
+ node, contnode):
+ node, objtype = self._resolve_xref_inner(env, fromdocname, builder,
+ target, node, contnode, warn=False)
+ if node:
+ return [('cpp:' + self.role_for_objtype(objtype), node)]
+ return []
def get_objects(self):
- for refname, (docname, type, theid) in self.data['objects'].iteritems():
+ for refname, (docname, type, theid) in iteritems(self.data['objects']):
yield (refname, refname, type, docname, refname, 1)
diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py
index 9b7777f4..af215fd6 100644
--- a/sphinx/domains/javascript.py
+++ b/sphinx/domains/javascript.py
@@ -45,7 +45,7 @@ class JSObject(ObjectDescription):
nameprefix = None
name = prefix
- objectname = self.env.temp_data.get('js:object')
+ objectname = self.env.ref_context.get('js:object')
if nameprefix:
if objectname:
# someone documenting the method of an attribute of the current
@@ -77,7 +77,7 @@ class JSObject(ObjectDescription):
def add_target_and_index(self, name_obj, sig, signode):
objectname = self.options.get(
- 'object', self.env.temp_data.get('js:object'))
+ 'object', self.env.ref_context.get('js:object'))
fullname = name_obj[0]
if fullname not in self.state.document.ids:
signode['names'].append(fullname)
@@ -140,7 +140,7 @@ class JSConstructor(JSCallable):
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')
+ refnode['js:object'] = env.ref_context.get('js:object')
if not has_explicit_title:
title = title.lstrip('.')
target = target.lstrip('~')
@@ -179,14 +179,20 @@ class JavaScriptDomain(Domain):
'attr': JSXRefRole(),
}
initial_data = {
- 'objects': {}, # fullname -> docname, objtype
+ 'objects': {}, # fullname -> docname, objtype
}
def clear_doc(self, docname):
- for fullname, (fn, _) in self.data['objects'].items():
+ for fullname, (fn, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
+ def merge_domaindata(self, docnames, otherdata):
+ # XXX check duplicates
+ for fullname, (fn, objtype) in otherdata['objects'].items():
+ if fn in docnames:
+ self.data['objects'][fullname] = (fn, objtype)
+
def find_obj(self, env, obj, name, typ, searchorder=0):
if name[-2:] == '()':
name = name[:-2]
@@ -214,7 +220,17 @@ class JavaScriptDomain(Domain):
return make_refnode(builder, fromdocname, obj[0],
name.replace('$', '_S_'), contnode, name)
+ def resolve_any_xref(self, env, fromdocname, builder, target, node,
+ contnode):
+ objectname = node.get('js:object')
+ name, obj = self.find_obj(env, objectname, target, None, 1)
+ if not obj:
+ return []
+ return [('js:' + self.role_for_objtype(obj[1]),
+ make_refnode(builder, fromdocname, obj[0],
+ name.replace('$', '_S_'), contnode, name))]
+
def get_objects(self):
- for refname, (docname, type) in self.data['objects'].iteritems():
+ for refname, (docname, type) in list(self.data['objects'].items()):
yield refname, refname, type, docname, \
refname.replace('$', '_S_'), 1
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index 792cffd8..4e08eba9 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -11,6 +11,7 @@
import re
+from six import iteritems
from docutils import nodes
from docutils.parsers.rst import directives
@@ -81,6 +82,23 @@ def _pseudo_parse_arglist(signode, arglist):
signode += paramlist
+# This override allows our inline type specifiers to behave like :class: link
+# when it comes to handling "." and "~" prefixes.
+class PyTypedField(TypedField):
+ def make_xref(self, rolename, domain, target, innernode=nodes.emphasis):
+ result = super(PyTypedField, self).make_xref(rolename, domain, target,
+ innernode)
+ if target.startswith('.'):
+ result['reftarget'] = target[1:]
+ result['refspecific'] = True
+ result[0][0] = nodes.Text(target[1:])
+ if target.startswith('~'):
+ result['reftarget'] = target[1:]
+ title = target.split('.')[-1]
+ result[0][0] = nodes.Text(title)
+ return result
+
+
class PyObject(ObjectDescription):
"""
Description of a general Python object.
@@ -92,7 +110,7 @@ class PyObject(ObjectDescription):
}
doc_field_types = [
- TypedField('parameter', label=l_('Parameters'),
+ PyTypedField('parameter', label=l_('Parameters'),
names=('param', 'parameter', 'arg', 'argument',
'keyword', 'kwarg', 'kwparam'),
typerolename='obj', typenames=('paramtype', 'type'),
@@ -138,8 +156,8 @@ class PyObject(ObjectDescription):
# 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')
+ 'module', self.env.ref_context.get('py:module'))
+ classname = self.env.ref_context.get('py:class')
if classname:
add_module = False
if name_prefix and name_prefix.startswith(classname):
@@ -176,7 +194,7 @@ class PyObject(ObjectDescription):
# 'exceptions' module.
elif add_module and self.env.config.add_module_names:
modname = self.options.get(
- 'module', self.env.temp_data.get('py:module'))
+ 'module', self.env.ref_context.get('py:module'))
if modname and modname != 'exceptions':
nodetext = modname + '.'
signode += addnodes.desc_addname(nodetext, nodetext)
@@ -207,7 +225,7 @@ class PyObject(ObjectDescription):
def add_target_and_index(self, name_cls, sig, signode):
modname = self.options.get(
- 'module', self.env.temp_data.get('py:module'))
+ 'module', self.env.ref_context.get('py:module'))
fullname = (modname and modname + '.' or '') + name_cls[0]
# note target
if fullname not in self.state.document.ids:
@@ -236,7 +254,7 @@ class PyObject(ObjectDescription):
def after_content(self):
if self.clsname_set:
- self.env.temp_data['py:class'] = None
+ self.env.ref_context.pop('py:class', None)
class PyModulelevel(PyObject):
@@ -281,7 +299,7 @@ class PyClasslike(PyObject):
def before_content(self):
PyObject.before_content(self)
if self.names:
- self.env.temp_data['py:class'] = self.names[0][0]
+ self.env.ref_context['py:class'] = self.names[0][0]
self.clsname_set = True
@@ -359,8 +377,8 @@ class PyClassmember(PyObject):
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('.')
+ if lastname and not self.env.ref_context.get('py:class'):
+ self.env.ref_context['py:class'] = lastname.strip('.')
self.clsname_set = True
@@ -416,7 +434,7 @@ class PyModule(Directive):
env = self.state.document.settings.env
modname = self.arguments[0].strip()
noindex = 'noindex' in self.options
- env.temp_data['py:module'] = modname
+ env.ref_context['py:module'] = modname
ret = []
if not noindex:
env.domaindata['py']['modules'][modname] = \
@@ -454,16 +472,16 @@ class PyCurrentModule(Directive):
env = self.state.document.settings.env
modname = self.arguments[0].strip()
if modname == 'None':
- env.temp_data['py:module'] = None
+ env.ref_context.pop('py:module', None)
else:
- env.temp_data['py:module'] = modname
+ env.ref_context['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')
+ refnode['py:module'] = env.ref_context.get('py:module')
+ refnode['py:class'] = env.ref_context.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
@@ -497,7 +515,7 @@ class PythonModuleIndex(Index):
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(),
+ modules = sorted(iteritems(self.domain.data['modules']),
key=lambda x: x[0].lower())
# sort out collapsable modules
prev_modname = ''
@@ -547,7 +565,7 @@ class PythonModuleIndex(Index):
collapse = len(modules) - num_toplevels < num_toplevels
# sort by first letter
- content = sorted(content.iteritems())
+ content = sorted(iteritems(content))
return content, collapse
@@ -602,13 +620,22 @@ class PythonDomain(Domain):
]
def clear_doc(self, docname):
- for fullname, (fn, _) in self.data['objects'].items():
+ for fullname, (fn, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
- for modname, (fn, _, _, _) in self.data['modules'].items():
+ for modname, (fn, _, _, _) in list(self.data['modules'].items()):
if fn == docname:
del self.data['modules'][modname]
+ def merge_domaindata(self, docnames, otherdata):
+ # XXX check duplicates?
+ for fullname, (fn, objtype) in otherdata['objects'].items():
+ if fn in docnames:
+ self.data['objects'][fullname] = (fn, objtype)
+ for modname, data in otherdata['modules'].items():
+ if data[0] in docnames:
+ self.data['modules'][modname] = data
+
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.
@@ -625,7 +652,10 @@ class PythonDomain(Domain):
newname = None
if searchmode == 1:
- objtypes = self.objtypes_for_role(type)
+ if type is None:
+ objtypes = list(self.object_types)
+ else:
+ objtypes = self.objtypes_for_role(type)
if objtypes is not None:
if modname and classname:
fullname = modname + '.' + classname + '.' + name
@@ -686,25 +716,47 @@ class PythonDomain(Domain):
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)
+ return self._make_module_refnode(builder, fromdocname, name,
+ contnode)
else:
return make_refnode(builder, fromdocname, obj[0], name,
contnode, name)
+ def resolve_any_xref(self, env, fromdocname, builder, target,
+ node, contnode):
+ modname = node.get('py:module')
+ clsname = node.get('py:class')
+ results = []
+
+ # always search in "refspecific" mode with the :any: role
+ matches = self.find_obj(env, modname, clsname, target, None, 1)
+ for name, obj in matches:
+ if obj[1] == 'module':
+ results.append(('py:mod',
+ self._make_module_refnode(builder, fromdocname,
+ name, contnode)))
+ else:
+ results.append(('py:' + self.role_for_objtype(obj[1]),
+ make_refnode(builder, fromdocname, obj[0], name,
+ contnode, name)))
+ return results
+
+ def _make_module_refnode(self, builder, fromdocname, name, contnode):
+ # get additional info for modules
+ docname, synopsis, platform, deprecated = self.data['modules'][name]
+ title = name
+ if synopsis:
+ title += ': ' + synopsis
+ if deprecated:
+ title += _(' (deprecated)')
+ if platform:
+ title += ' (' + platform + ')'
+ return make_refnode(builder, fromdocname, docname,
+ 'module-' + name, contnode, title)
+
def get_objects(self):
- for modname, info in self.data['modules'].iteritems():
+ for modname, info in iteritems(self.data['modules']):
yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
- for refname, (docname, type) in self.data['objects'].iteritems():
+ for refname, (docname, type) in iteritems(self.data['objects']):
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
index c51c85fe..2c304d0c 100644
--- a/sphinx/domains/rst.py
+++ b/sphinx/domains/rst.py
@@ -11,6 +11,8 @@
import re
+from six import iteritems
+
from sphinx import addnodes
from sphinx.domains import Domain, ObjType
from sphinx.locale import l_, _
@@ -117,10 +119,16 @@ class ReSTDomain(Domain):
}
def clear_doc(self, docname):
- for (typ, name), doc in self.data['objects'].items():
+ for (typ, name), doc in list(self.data['objects'].items()):
if doc == docname:
del self.data['objects'][typ, name]
+ def merge_domaindata(self, docnames, otherdata):
+ # XXX check duplicates
+ for (typ, name), doc in otherdata['objects'].items():
+ if doc in docnames:
+ self.data['objects'][typ, name] = doc
+
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
contnode):
objects = self.data['objects']
@@ -132,6 +140,19 @@ class ReSTDomain(Domain):
objtype + '-' + target,
contnode, target + ' ' + objtype)
+ def resolve_any_xref(self, env, fromdocname, builder, target,
+ node, contnode):
+ objects = self.data['objects']
+ results = []
+ for objtype in self.object_types:
+ if (objtype, target) in self.data['objects']:
+ results.append(('rst:' + self.role_for_objtype(objtype),
+ make_refnode(builder, fromdocname,
+ objects[objtype, target],
+ objtype + '-' + target,
+ contnode, target + ' ' + objtype)))
+ return results
+
def get_objects(self):
- for (typ, name), docname in self.data['objects'].iteritems():
+ for (typ, name), docname in iteritems(self.data['objects']):
yield name, name, typ, docname, typ + '-' + name, 1
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
index 9a7937aa..03228da2 100644
--- a/sphinx/domains/std.py
+++ b/sphinx/domains/std.py
@@ -12,6 +12,7 @@
import re
import unicodedata
+from six import iteritems
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
@@ -21,13 +22,15 @@ 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 import ws_re, get_figtype
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*.*)')
+option_desc_re = re.compile(r'((?:/|--|-|\+)?[-?@#_a-zA-Z0-9]+)(=?\s*.*)')
+# RE for grammar tokens
+token_re = re.compile('`(\w+)`', re.U)
class GenericObject(ObjectDescription):
@@ -143,8 +146,9 @@ class Cmdoption(ObjectDescription):
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)
+ 'look like "opt", "-opt args", "--opt args", '
+ '"/opt args" or "+opt args"' % potential_option,
+ self.lineno)
continue
optname, args = m.groups()
if count:
@@ -162,7 +166,7 @@ class Cmdoption(ObjectDescription):
return firstname
def add_target_and_index(self, firstname, sig, signode):
- currprogram = self.env.temp_data.get('std:program')
+ currprogram = self.env.ref_context.get('std:program')
for optname in signode.get('allnames', []):
targetname = optname.replace('/', '-')
if not targetname.startswith('-'):
@@ -197,36 +201,19 @@ class Program(Directive):
env = self.state.document.settings.env
program = ws_re.sub('-', self.arguments[0].strip())
if program == 'None':
- env.temp_data['std:program'] = None
+ env.ref_context.pop('std:program', None)
else:
- env.temp_data['std:program'] = program
+ env.ref_context['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
+ # validate content
+ if not re.match('(.+ )?[-/+]', target):
+ env.warn_node('Malformed :option: %r, does not contain option '
+ 'marker - or -- or / or +' % target, refnode)
+ refnode['std:program'] = env.ref_context.get('std:program')
return title, target
@@ -326,7 +313,7 @@ class Glossary(Directive):
else:
messages.append(self.state.reporter.system_message(
2, 'glossary seems to be misformatted, check '
- 'indentation', source=source, line=lineno))
+ 'indentation', source=source, line=lineno))
else:
if not in_definition:
# first line of definition, determines indentation
@@ -337,7 +324,7 @@ class Glossary(Directive):
else:
messages.append(self.state.reporter.system_message(
2, 'glossary seems to be misformatted, check '
- 'indentation', source=source, line=lineno))
+ 'indentation', source=source, line=lineno))
was_empty = False
# now, parse all the entries into a big definition list
@@ -358,7 +345,7 @@ class Glossary(Directive):
tmp.source = source
tmp.line = lineno
new_id, termtext, new_termnodes = \
- make_termnodes_from_paragraph_node(env, tmp)
+ make_termnodes_from_paragraph_node(env, tmp)
ids.append(new_id)
termtexts.append(termtext)
termnodes.extend(new_termnodes)
@@ -385,8 +372,6 @@ class Glossary(Directive):
return messages + [node]
-token_re = re.compile('`(\w+)`', re.U)
-
def token_xrefs(text):
retnodes = []
pos = 0
@@ -471,7 +456,7 @@ class StandardDomain(Domain):
'productionlist': ProductionList,
}
roles = {
- 'option': OptionXRefRole(innernodeclass=addnodes.literal_emphasis),
+ 'option': OptionXRefRole(),
'envvar': EnvVarXRefRole(),
# links to tokens in grammar productions
'token': XRefRole(),
@@ -481,6 +466,9 @@ class StandardDomain(Domain):
# links to headings or arbitrary labels
'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
warn_dangling=True),
+ # links to labels of numbered figures, tables and code-blocks
+ 'numref': XRefRole(lowercase=True,
+ warn_dangling=True),
# links to labels, without a different title
'keyword': XRefRole(warn_dangling=True),
}
@@ -504,34 +492,50 @@ class StandardDomain(Domain):
'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)',
+ 'numref': 'undefined label: %(target)s',
'keyword': 'unknown keyword: %(target)s',
}
def clear_doc(self, docname):
- for key, (fn, _) in self.data['progoptions'].items():
+ for key, (fn, _) in list(self.data['progoptions'].items()):
if fn == docname:
del self.data['progoptions'][key]
- for key, (fn, _) in self.data['objects'].items():
+ for key, (fn, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][key]
- for key, (fn, _, _) in self.data['labels'].items():
+ for key, (fn, _, _) in list(self.data['labels'].items()):
if fn == docname:
del self.data['labels'][key]
- for key, (fn, _) in self.data['anonlabels'].items():
+ for key, (fn, _) in list(self.data['anonlabels'].items()):
if fn == docname:
del self.data['anonlabels'][key]
+ def merge_domaindata(self, docnames, otherdata):
+ # XXX duplicates?
+ for key, data in otherdata['progoptions'].items():
+ if data[0] in docnames:
+ self.data['progoptions'][key] = data
+ for key, data in otherdata['objects'].items():
+ if data[0] in docnames:
+ self.data['objects'][key] = data
+ for key, data in otherdata['labels'].items():
+ if data[0] in docnames:
+ self.data['labels'][key] = data
+ for key, data in otherdata['anonlabels'].items():
+ if data[0] in docnames:
+ self.data['anonlabels'][key] = data
+
def process_doc(self, env, docname, document):
labels, anonlabels = self.data['labels'], self.data['anonlabels']
- for name, explicit in document.nametypes.iteritems():
+ for name, explicit in iteritems(document.nametypes):
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_'):
+ if name.isdigit() or 'refuri' in node or \
+ node.tagname.startswith('desc_'):
# ignore footnote labels, labels automatically generated from a
# link and object descriptions
continue
@@ -540,7 +544,7 @@ class StandardDomain(Domain):
'in ' + env.doc2path(labels[name][0]), node)
anonlabels[name] = docname, labelid
if node.tagname == 'section':
- sectname = clean_astext(node[0]) # node[0] == title node
+ sectname = clean_astext(node[0]) # node[0] == title node
elif node.tagname == 'figure':
for n in node:
if n.tagname == 'caption':
@@ -548,6 +552,13 @@ class StandardDomain(Domain):
break
else:
continue
+ elif node.tagname == 'image' and node.parent.tagname == 'figure':
+ for n in node.parent:
+ if n.tagname == 'caption':
+ sectname = clean_astext(n)
+ break
+ else:
+ continue
elif node.tagname == 'table':
for n in node:
if n.tagname == 'title':
@@ -555,52 +566,105 @@ class StandardDomain(Domain):
break
else:
continue
+ elif node.tagname == 'container' and node.get('literal_block'):
+ for n in node:
+ if n.tagname == 'caption':
+ sectname = clean_astext(n)
+ break
+ else:
+ continue
else:
# anonymous-only labels
continue
labels[name] = docname, labelid, sectname
+ def build_reference_node(self, fromdocname, builder,
+ docname, labelid, sectname,
+ **options):
+ nodeclass = options.pop('nodeclass', nodes.reference)
+ newnode = nodeclass('', '', internal=True, **options)
+ 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
+
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, ('',''))
+ 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
+
+ return self.build_reference_node(fromdocname, builder,
+ docname, labelid, sectname)
+ elif typ == 'numref':
+ docname, labelid = self.data['anonlabels'].get(target, ('', ''))
if not docname:
return None
- newnode = nodes.reference('', '', internal=True)
- innernode = nodes.emphasis(sectname, sectname)
- if docname == fromdocname:
- newnode['refid'] = labelid
+
+ if env.config.numfig is False:
+ env.warn(fromdocname, 'numfig is disabled. :numref: is ignored.')
+ return contnode
+
+ try:
+ target = env.get_doctree(docname).ids[labelid]
+ figtype = get_figtype(target)
+ figure_id = target['ids'][0]
+ fignumber = env.toc_fignumbers[docname][figtype][figure_id]
+ except (KeyError, IndexError):
+ return None
+
+ title = contnode.astext()
+ if labelid == title:
+ prefix = env.config.numfig_prefix.get(figtype, '')
+ title = prefix.replace('%s', '#')
+ newtitle = prefix % '.'.join(map(str, fignumber))
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
+ newtitle = title.replace('#', '.'.join(map(str, fignumber)))
+
+ return self.build_reference_node(fromdocname, builder,
+ docname, labelid, newtitle,
+ nodeclass=addnodes.number_reference,
+ title=title)
elif typ == 'keyword':
# keywords are oddballs: they are referenced by named labels
- docname, labelid, _ = self.data['labels'].get(target, ('','',''))
+ 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.get('refprogram', '')
+ target = target.strip()
+ # most obvious thing: we are a flag option without program
+ if target.startswith(('-', '/', '+')):
+ progname = node.get('std:program')
+ else:
+ try:
+ progname, target = re.split(r' (?=-|--|/|\+)', target, 1)
+ except ValueError:
+ return None
+ progname = ws_re.sub('-', progname.strip())
docname, labelid = self.data['progoptions'].get((progname, target),
('', ''))
if not docname:
@@ -620,17 +684,39 @@ class StandardDomain(Domain):
return make_refnode(builder, fromdocname, docname,
labelid, contnode)
+ def resolve_any_xref(self, env, fromdocname, builder, target,
+ node, contnode):
+ results = []
+ ltarget = target.lower() # :ref: lowercases its target automatically
+ for role in ('ref', 'option'): # do not try "keyword"
+ res = self.resolve_xref(env, fromdocname, builder, role,
+ ltarget if role == 'ref' else target,
+ node, contnode)
+ if res:
+ results.append(('std:' + role, res))
+ # all others
+ for objtype in self.object_types:
+ key = (objtype, target)
+ if objtype == 'term':
+ key = (objtype, ltarget)
+ if key in self.data['objects']:
+ docname, labelid = self.data['objects'][key]
+ results.append(('std:' + self.role_for_objtype(objtype),
+ make_refnode(builder, fromdocname, docname,
+ labelid, contnode)))
+ return results
+
def get_objects(self):
- for (prog, option), info in self.data['progoptions'].iteritems():
+ for (prog, option), info in iteritems(self.data['progoptions']):
yield (option, option, 'option', info[0], info[1], 1)
- for (type, name), info in self.data['objects'].iteritems():
+ for (type, name), info in iteritems(self.data['objects']):
yield (name, name, type, info[0], info[1],
self.object_types[type].attrs['searchprio'])
- for name, info in self.data['labels'].iteritems():
+ for name, info in iteritems(self.data['labels']):
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():
+ for name, info in iteritems(self.data['anonlabels']):
if name not in non_anon_labels:
yield (name, name, 'label', info[0], info[1], -1)
diff --git a/sphinx/environment.py b/sphinx/environment.py
index 463204bc..f0021fd3 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -18,11 +18,12 @@ 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 itertools import groupby
+from six import iteritems, itervalues, text_type, class_types
+from six.moves import cPickle as pickle, zip
from docutils import nodes
from docutils.io import FileInput, NullOutput
from docutils.core import Publisher
@@ -32,28 +33,31 @@ 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 docutils.frontend import OptionParser
from sphinx import addnodes
from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \
- FilenameUniqDict
+ FilenameUniqDict, get_figtype
from sphinx.util.nodes import clean_astext, make_refnode, WarningStream
-from sphinx.util.osutil import SEP, fs_encoding, find_catalog_files
+from sphinx.util.osutil import SEP, find_catalog_files, getcwd, fs_encoding
+from sphinx.util.console import bold, purple
from sphinx.util.matching import compile_matchers
-from sphinx.util.pycompat import class_types, getcwd
-from sphinx.util.compat import docutils_version
+from sphinx.util.parallel import ParallelTasks, parallel_available, make_chunks
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
+ HandleCodeBlocks, AutoNumbering, SortIds, CitationReferences, Locale, \
+ RemoveTranslatableInline, SphinxContentsFilter
orig_role_function = roles.role
orig_directive_function = directives.directive
-class ElementLookupError(Exception): pass
+
+class ElementLookupError(Exception):
+ pass
default_settings = {
@@ -70,7 +74,9 @@ default_settings = {
# 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)
+#
+# NOTE: increase base version by 2 to have distinct numbers for Py2 and 3
+ENV_VERSION = 46 + (sys.version_info[0] - 2)
dummy_reporter = Reporter('', 4, 4)
@@ -92,7 +98,7 @@ class SphinxStandaloneReader(standalone.Reader):
Add our own transforms.
"""
transforms = [Locale, CitationReferences, DefaultSubstitutions,
- MoveModuleTargets, HandleCodeBlocks, SortIds,
+ MoveModuleTargets, HandleCodeBlocks, AutoNumbering, SortIds,
RemoveTranslatableInline]
def get_transforms(self):
@@ -106,6 +112,33 @@ class SphinxDummyWriter(UnfilteredWriter):
pass
+class SphinxFileInput(FileInput):
+ def __init__(self, app, env, *args, **kwds):
+ self.app = app
+ self.env = env
+ # don't call sys.exit() on IOErrors
+ kwds['handle_io_errors'] = False
+ kwds['error_handler'] = 'sphinx' # py3: handle error on open.
+ FileInput.__init__(self, *args, **kwds)
+
+ def decode(self, data):
+ if isinstance(data, text_type): # py3: `data` already decoded.
+ return data
+ return data.decode(self.encoding, 'sphinx') # py2: decoding
+
+ def read(self):
+ data = FileInput.read(self)
+ if self.app:
+ arg = [data]
+ self.app.emit('source-read', self.env.docname, arg)
+ data = arg[0]
+ if self.env.config.rst_epilog:
+ data = data + '\n' + self.env.config.rst_epilog + '\n'
+ if self.env.config.rst_prolog:
+ data = self.env.config.rst_prolog + '\n' + data
+ return data
+
+
class BuildEnvironment:
"""
The environment in which the ReST files are translated.
@@ -123,7 +156,7 @@ class BuildEnvironment:
finally:
picklefile.close()
if env.version != ENV_VERSION:
- raise IOError('env version not current')
+ raise IOError('build environment version not current')
env.config.values = config.values
return env
@@ -137,11 +170,11 @@ class BuildEnvironment:
del self.domains
picklefile = open(filename, 'wb')
# remove potentially pickling-problematic values from config
- for key, val in vars(self.config).items():
+ for key, val in list(vars(self.config).items()):
if key.startswith('_') or \
- isinstance(val, types.ModuleType) or \
- isinstance(val, types.FunctionType) or \
- isinstance(val, class_types):
+ 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)
@@ -161,6 +194,7 @@ class BuildEnvironment:
# the method of doctree versioning; see set_versioning_method
self.versioning_condition = None
+ self.versioning_compare = None
# the application object; only set while update() runs
self.app = None
@@ -182,8 +216,8 @@ class BuildEnvironment:
# 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.all_docs = {} # docname -> mtime at the time of reading
+ # contains all read docnames
self.dependencies = {} # docname -> set of dependent file
# names, relative to documentation root
self.reread_always = set() # docnames to re-read unconditionally on
@@ -201,6 +235,8 @@ class BuildEnvironment:
# 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.toc_fignumbers = {} # docname -> dict of figtype ->
+ # dict of figureid -> number
self.toctree_includes = {} # docname -> list of toctree includefiles
self.files_to_rebuild = {} # docname -> set of files
@@ -224,12 +260,16 @@ class BuildEnvironment:
# temporary data storage while reading a document
self.temp_data = {}
+ # context for cross-references (e.g. current module or class)
+ # this is similar to temp_data, but will for example be copied to
+ # attributes of "any" cross references
+ self.ref_context = {}
def set_warnfunc(self, func):
self._warnfunc = func
self.settings['warning_stream'] = WarningStream(func)
- def set_versioning_method(self, method):
+ def set_versioning_method(self, method, compare):
"""This sets the doctree versioning method for this environment.
Versioning methods are a builder property; only builders with the same
@@ -245,6 +285,7 @@ class BuildEnvironment:
'selected builder, please choose another '
'doctree directory.')
self.versioning_condition = condition
+ self.versioning_compare = compare
def warn(self, docname, msg, lineno=None):
"""Emit a warning.
@@ -271,6 +312,7 @@ class BuildEnvironment:
self.longtitles.pop(docname, None)
self.tocs.pop(docname, None)
self.toc_secnumbers.pop(docname, None)
+ self.toc_fignumbers.pop(docname, None)
self.toc_num_entries.pop(docname, None)
self.toctree_includes.pop(docname, None)
self.indexentries.pop(docname, None)
@@ -279,11 +321,11 @@ class BuildEnvironment:
self.images.purge_doc(docname)
self.dlfiles.purge_doc(docname)
- for subfn, fnset in self.files_to_rebuild.items():
+ for subfn, fnset in list(self.files_to_rebuild.items()):
fnset.discard(docname)
if not fnset:
del self.files_to_rebuild[subfn]
- for key, (fn, _) in self.citations.items():
+ for key, (fn, _) in list(self.citations.items()):
if fn == docname:
del self.citations[key]
for version, changes in self.versionchanges.items():
@@ -293,6 +335,50 @@ class BuildEnvironment:
for domain in self.domains.values():
domain.clear_doc(docname)
+ def merge_info_from(self, docnames, other, app):
+ """Merge global information gathered about *docnames* while reading them
+ from the *other* environment.
+
+ This possibly comes from a parallel build process.
+ """
+ docnames = set(docnames)
+ for docname in docnames:
+ self.all_docs[docname] = other.all_docs[docname]
+ if docname in other.reread_always:
+ self.reread_always.add(docname)
+ self.metadata[docname] = other.metadata[docname]
+ if docname in other.dependencies:
+ self.dependencies[docname] = other.dependencies[docname]
+ self.titles[docname] = other.titles[docname]
+ self.longtitles[docname] = other.longtitles[docname]
+ self.tocs[docname] = other.tocs[docname]
+ self.toc_num_entries[docname] = other.toc_num_entries[docname]
+ # toc_secnumbers and toc_fignumbers are not assigned during read
+ if docname in other.toctree_includes:
+ self.toctree_includes[docname] = other.toctree_includes[docname]
+ self.indexentries[docname] = other.indexentries[docname]
+ if docname in other.glob_toctrees:
+ self.glob_toctrees.add(docname)
+ if docname in other.numbered_toctrees:
+ self.numbered_toctrees.add(docname)
+
+ self.images.merge_other(docnames, other.images)
+ self.dlfiles.merge_other(docnames, other.dlfiles)
+
+ for subfn, fnset in other.files_to_rebuild.items():
+ self.files_to_rebuild.setdefault(subfn, set()).update(fnset & docnames)
+ for key, data in other.citations.items():
+ # XXX duplicates?
+ if data[0] in docnames:
+ self.citations[key] = data
+ for version, changes in other.versionchanges.items():
+ self.versionchanges.setdefault(version, []).extend(
+ change for change in changes if change[1] in docnames)
+
+ for domainname, domain in self.domains.items():
+ domain.merge_domaindata(docnames, other.domaindata[domainname])
+ app.emit('env-merge-info', self, docnames, other)
+
def doc2path(self, docname, base=True, suffix=None):
"""Return the filename for the document name.
@@ -340,10 +426,8 @@ class BuildEnvironment:
"""
matchers = compile_matchers(
config.exclude_patterns[:] +
+ config.templates_path +
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(
@@ -410,13 +494,11 @@ class BuildEnvironment:
return added, changed, removed
- def update(self, config, srcdir, doctreedir, app=None):
+ def update(self, config, srcdir, doctreedir, app):
"""(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).
+ 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:
@@ -425,7 +507,7 @@ class BuildEnvironment:
else:
# check if a config value was changed that affects how
# doctrees are read
- for key, descr in config.values.iteritems():
+ for key, descr in iteritems(config.values):
if descr[1] != 'env':
continue
if self.config[key] != config[key]:
@@ -448,6 +530,8 @@ class BuildEnvironment:
# this cache also needs to be updated every time
self._nitpick_ignore = set(self.config.nitpick_ignore)
+ app.info(bold('updating environment: '), nonl=1)
+
added, changed, removed = self.get_outdated_files(config_changed)
# allow user intervention as well
@@ -462,34 +546,102 @@ class BuildEnvironment:
msg += '%s added, %s changed, %s removed' % (len(added), len(changed),
len(removed))
+ app.info(msg)
- def update_generator():
- self.app = app
+ self.app = app
+
+ # clear all files no longer present
+ for docname in removed:
+ app.emit('env-purge-doc', self, docname)
+ self.clear_doc(docname)
+
+ # read all new and changed files
+ docnames = sorted(added | changed)
+ # allow changing and reordering the list of docs to read
+ app.emit('env-before-read-docs', self, docnames)
+
+ # check if we should do parallel or serial read
+ par_ok = False
+ if parallel_available and len(docnames) > 5 and app.parallel > 1:
+ par_ok = True
+ for extname, md in app._extension_metadata.items():
+ ext_ok = md.get('parallel_read_safe')
+ if ext_ok:
+ continue
+ if ext_ok is None:
+ app.warn('the %s extension does not declare if it '
+ 'is safe for parallel reading, assuming it '
+ 'isn\'t - please ask the extension author to '
+ 'check and make it explicit' % extname)
+ app.warn('doing serial read')
+ else:
+ app.warn('the %s extension is not safe for parallel '
+ 'reading, doing serial read' % extname)
+ par_ok = False
+ break
+ if par_ok:
+ self._read_parallel(docnames, app, nproc=app.parallel)
+ else:
+ self._read_serial(docnames, app)
- # clear all files no longer present
- for docname in removed:
- if app:
- app.emit('env-purge-doc', self, docname)
- self.clear_doc(docname)
+ if config.master_doc not in self.all_docs:
+ self.warn(None, 'master file %s not found' %
+ self.doc2path(config.master_doc))
- # read all new and changed files
- for docname in sorted(added | changed):
- yield docname
- self.read_doc(docname, app=app)
+ self.app = None
+ app.emit('env-updated', self)
+ return docnames
- if config.master_doc not in self.all_docs:
- self.warn(None, 'master file %s not found' %
- self.doc2path(config.master_doc))
+ def _read_serial(self, docnames, app):
+ for docname in app.status_iterator(docnames, 'reading sources... ',
+ purple, len(docnames)):
+ # remove all inventory entries for that file
+ app.emit('env-purge-doc', self, docname)
+ self.clear_doc(docname)
+ self.read_doc(docname, app)
- self.app = None
- if app:
- app.emit('env-updated', self)
+ def _read_parallel(self, docnames, app, nproc):
+ # clear all outdated docs at once
+ for docname in docnames:
+ app.emit('env-purge-doc', self, docname)
+ self.clear_doc(docname)
- return msg, len(added | changed), update_generator()
+ def read_process(docs):
+ self.app = app
+ self.warnings = []
+ self.set_warnfunc(lambda *args: self.warnings.append(args))
+ for docname in docs:
+ self.read_doc(docname, app)
+ # allow pickling self to send it back
+ self.set_warnfunc(None)
+ del self.app
+ del self.domains
+ del self.config.values
+ del self.config
+ return self
+
+ def merge(docs, otherenv):
+ warnings.extend(otherenv.warnings)
+ self.merge_info_from(docs, otherenv, app)
+
+ tasks = ParallelTasks(nproc)
+ chunks = make_chunks(docnames, nproc)
+
+ warnings = []
+ for chunk in app.status_iterator(
+ chunks, 'reading sources... ', purple, len(chunks)):
+ tasks.add_task(read_process, chunk, merge)
+
+ # make sure all threads have finished
+ app.info(bold('waiting for workers...'))
+ tasks.join()
+
+ for warning in warnings:
+ self._warnfunc(*warning)
def check_dependents(self, already):
- to_rewrite = self.assign_section_numbers()
- for docname in to_rewrite:
+ to_rewrite = self.assign_section_numbers() + self.assign_figure_numbers()
+ for docname in set(to_rewrite):
if docname not in already:
yield docname
@@ -497,14 +649,15 @@ class BuildEnvironment:
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
+ linestart = error.object.rfind(b'\n', 0, error.start)
+ lineend = error.object.find(b'\n', error.start)
+ if lineend == -1:
+ lineend = len(error.object)
+ lineno = error.object.count(b'\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[linestart+1:error.start] + b'>>>' +
+ error.object[error.start:error.end] + b'<<<' +
error.object[error.end:lineend]), lineno)
return (u'?', error.end)
@@ -553,19 +706,8 @@ class BuildEnvironment:
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)
+ def read_doc(self, docname, app=None):
+ """Parse a file and add/update inventory entries for the doctree."""
self.temp_data['docname'] = docname
# defaults to the global default, but can be re-set in a document
@@ -579,6 +721,12 @@ class BuildEnvironment:
self.patch_lookup_functions()
+ docutilsconf = path.join(self.srcdir, 'docutils.conf')
+ # read docutils.conf from source dir, not from current dir
+ OptionParser.standard_config_files[1] = docutilsconf
+ if path.isfile(docutilsconf):
+ self.note_dependency(docutilsconf)
+
if self.config.default_role:
role_fn, messages = roles.role(self.config.default_role, english,
0, dummy_reporter)
@@ -590,40 +738,17 @@ class BuildEnvironment:
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)
+ src_path = self.doc2path(docname)
+ source = SphinxFileInput(app, self, source=None, source_path=src_path,
+ encoding=self.config.source_encoding)
+ pub.source = source
+ pub.settings._source = src_path
pub.set_destination(None, None)
pub.publish()
doctree = pub.document
@@ -639,34 +764,36 @@ class BuildEnvironment:
self.note_indexentries_from(docname, doctree)
self.note_citations_from(docname, doctree)
self.build_toc_from(docname, doctree)
- for domain in self.domains.itervalues():
+ for domain in itervalues(self.domains):
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
+ # store time of reading, 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)))
+ time.time(), path.getmtime(self.doc2path(docname)))
if self.versioning_condition:
- # get old doctree
- try:
- f = open(self.doc2path(docname,
- self.doctreedir, '.doctree'), 'rb')
+ old_doctree = None
+ if self.versioning_compare:
+ # get old doctree
try:
- old_doctree = pickle.load(f)
- finally:
- f.close()
- except EnvironmentError:
- old_doctree = None
+ f = open(self.doc2path(docname,
+ self.doctreedir, '.doctree'), 'rb')
+ try:
+ old_doctree = pickle.load(f)
+ finally:
+ f.close()
+ except EnvironmentError:
+ pass
# add uids for versioning
- if old_doctree is None:
+ if not self.versioning_compare or old_doctree is None:
list(add_uids(doctree, self.versioning_condition))
else:
list(merge_doctrees(
@@ -684,21 +811,20 @@ class BuildEnvironment:
# 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
+ self.ref_context.clear()
+ roles._roles.pop('', None) # if a document has set a local default role
+
+ # 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()
# utilities to use while reading a document
@@ -709,13 +835,17 @@ class BuildEnvironment:
@property
def currmodule(self):
- """Backwards compatible alias."""
- return self.temp_data.get('py:module')
+ """Backwards compatible alias. Will be removed."""
+ self.warn(self.docname, 'env.currmodule is being referenced by an '
+ 'extension; this API will be removed in the future')
+ return self.ref_context.get('py:module')
@property
def currclass(self):
- """Backwards compatible alias."""
- return self.temp_data.get('py:class')
+ """Backwards compatible alias. Will be removed."""
+ self.warn(self.docname, 'env.currclass is being referenced by an '
+ 'extension; this API will be removed in the future')
+ return self.ref_context.get('py:class')
def new_serialno(self, category=''):
"""Return a serial number, e.g. for index entry targets.
@@ -745,7 +875,7 @@ class BuildEnvironment:
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.ref_context.get('py:module'),
self.temp_data.get('object'), node.astext()))
# post-processing of read doctrees
@@ -768,6 +898,8 @@ class BuildEnvironment:
for dep in deps.list:
# the dependency path is relative to the working dir, so get
# one relative to the srcdir
+ if isinstance(dep, bytes):
+ dep = dep.decode(fs_encoding)
relpath = relative_path(frompath,
path.normpath(path.join(cwd, dep)))
self.dependencies.setdefault(docname, set()).add(relpath)
@@ -816,7 +948,7 @@ class BuildEnvironment:
imgtype = imghdr.what(f)
finally:
f.close()
- except (OSError, IOError), err:
+ except (OSError, IOError) as err:
self.warn_node('image file %s not readable: %s' %
(filename, err), node)
if imgtype:
@@ -825,7 +957,7 @@ class BuildEnvironment:
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():
+ for imgpath in itervalues(candidates):
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,
@@ -851,11 +983,19 @@ class BuildEnvironment:
# 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
+ elif isinstance(node, nodes.TextElement): # e.g. author
md[node.__class__.__name__] = node.astext()
else:
name, body = node
md[name.astext()] = body.astext()
+ for name, value in md.items():
+ if name in ('tocdepth',):
+ try:
+ value = int(value)
+ except ValueError:
+ value = 0
+ md[name] = value
+
del doctree[0]
def process_refonly_bullet_lists(self, docname, doctree):
@@ -927,7 +1067,7 @@ class BuildEnvironment:
longtitlenode = titlenode
# explicit title set with title directive; use this only for
# the <title> tag in HTML output
- if document.has_key('title'):
+ if 'title' in document:
longtitlenode = nodes.title()
longtitlenode += nodes.Text(document['title'])
# look for first section title and use that as the title
@@ -973,12 +1113,7 @@ class BuildEnvironment:
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
+ numentries = [0] # nonlocal again...
def traverse_in_section(node, cls):
"""Like traverse(), but stay within the same section."""
@@ -1003,6 +1138,7 @@ class BuildEnvironment:
if blist:
onlynode += blist.children
entries.append(onlynode)
+ continue
if not isinstance(sectionnode, nodes.section):
for toctreenode in traverse_in_section(sectionnode,
addnodes.toctree):
@@ -1032,8 +1168,7 @@ class BuildEnvironment:
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
+ item += sub_item
entries.append(item)
if entries:
return nodes.bullet_list('', *entries)
@@ -1104,7 +1239,6 @@ class BuildEnvironment:
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
@@ -1119,7 +1253,8 @@ class BuildEnvironment:
# now, resolve all toctree nodes
for toctreenode in doctree.traverse(addnodes.toctree):
result = self.resolve_toctree(docname, builder, toctreenode,
- prune=prune_toctrees, includehidden=includehidden)
+ prune=prune_toctrees,
+ includehidden=includehidden)
if result is None:
toctreenode.replace_self([])
else:
@@ -1176,7 +1311,7 @@ class BuildEnvironment:
else:
# cull sub-entries whose parents aren't 'current'
if (collapse and depth > 1 and
- 'iscurrent' not in subnode.parent):
+ 'iscurrent' not in subnode.parent):
subnode.parent.remove(subnode)
else:
# recurse on visible children
@@ -1221,6 +1356,8 @@ class BuildEnvironment:
try:
refdoc = None
if url_re.match(ref):
+ if title is None:
+ title = ref
reference = nodes.reference('', '', internal=False,
refuri=ref, anchorname='',
*[nodes.Text(title)])
@@ -1249,12 +1386,14 @@ class BuildEnvironment:
continue
refdoc = ref
toc = self.tocs[ref].deepcopy()
+ maxdepth = self.metadata[ref].get('tocdepth', 0)
+ _toctree_prune(toc, 2, maxdepth)
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']:
+ not refnode['anchorname']:
refnode.children = [nodes.Text(title)]
if not toc.children:
# empty toc means: no titles will show up in the toctree
@@ -1344,49 +1483,23 @@ class BuildEnvironment:
domain = self.domains[node['refdomain']]
except KeyError:
raise NoUri
- newnode = domain.resolve_xref(self, fromdocname, builder,
+ newnode = domain.resolve_xref(self, refdoc, builder,
typ, target, node, contnode)
# really hardwired reference types
+ elif typ == 'any':
+ newnode = self._resolve_any_reference(builder, node, contnode)
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)
+ newnode = self._resolve_doc_reference(builder, node, contnode)
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'][:]
+ newnode = self._resolve_citation(builder, refdoc, node, contnode)
# 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
+ # still not found? warn if node wishes to be warned about or
+ # we are in nit-picky mode
if newnode is None:
- self._warn_missing_reference(
- fromdocname, typ, target, node, domain)
+ self._warn_missing_reference(refdoc, typ, target, node, domain)
except NoUri:
newnode = contnode
node.replace_self(newnode or contnode)
@@ -1397,7 +1510,7 @@ class BuildEnvironment:
# allow custom references to be resolved
builder.app.emit('doctree-resolved', doctree, fromdocname)
- def _warn_missing_reference(self, fromdoc, typ, target, node, domain):
+ def _warn_missing_reference(self, refdoc, typ, target, node, domain):
warn = node.get('refwarn')
if self.config.nitpicky:
warn = True
@@ -1416,13 +1529,91 @@ class BuildEnvironment:
msg = 'unknown document: %(target)s'
elif typ == 'citation':
msg = 'citation not found: %(target)s'
- elif node.get('refdomain', 'std') != 'std':
+ elif node.get('refdomain', 'std') not in ('', 'std'):
msg = '%s:%s reference target not found: %%(target)s' % \
(node['refdomain'], typ)
else:
- msg = '%s reference target not found: %%(target)s' % typ
+ msg = '%r reference target not found: %%(target)s' % typ
self.warn_node(msg % {'target': target}, node)
+ def _resolve_doc_reference(self, builder, node, contnode):
+ # directly reference to document by source name;
+ # can be absolute or relative
+ docname = docname_join(node['refdoc'], node['reftarget'])
+ 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(node['refdoc'], docname)
+ newnode.append(innernode)
+ return newnode
+
+ def _resolve_citation(self, builder, fromdocname, node, contnode):
+ docname, labelid = self.citations.get(node['reftarget'], ('', ''))
+ if docname:
+ try:
+ newnode = make_refnode(builder, fromdocname,
+ docname, labelid, contnode)
+ return newnode
+ 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'][:]
+
+ def _resolve_any_reference(self, builder, node, contnode):
+ """Resolve reference generated by the "any" role."""
+ refdoc = node['refdoc']
+ target = node['reftarget']
+ results = []
+ # first, try resolving as :doc:
+ doc_ref = self._resolve_doc_reference(builder, node, contnode)
+ if doc_ref:
+ results.append(('doc', doc_ref))
+ # next, do the standard domain (makes this a priority)
+ results.extend(self.domains['std'].resolve_any_xref(
+ self, refdoc, builder, target, node, contnode))
+ for domain in self.domains.values():
+ if domain.name == 'std':
+ continue # we did this one already
+ try:
+ results.extend(domain.resolve_any_xref(self, refdoc, builder,
+ target, node, contnode))
+ except NotImplementedError:
+ # the domain doesn't yet support the new interface
+ # we have to manually collect possible references (SLOW)
+ for role in domain.roles:
+ res = domain.resolve_xref(self, refdoc, builder, role, target,
+ node, contnode)
+ if res:
+ results.append(('%s:%s' % (domain.name, role), res))
+ # now, see how many matches we got...
+ if not results:
+ return None
+ if len(results) > 1:
+ nice_results = ' or '.join(':%s:' % r[0] for r in results)
+ self.warn_node('more than one target found for \'any\' cross-'
+ 'reference %r: could be %s' % (target, nice_results),
+ node)
+ res_role, newnode = results[0]
+ # Override "any" class with the actual role type to get the styling
+ # approximately correct.
+ res_domain = res_role.split(':')[0]
+ if newnode and newnode[0].get('classes'):
+ newnode[0]['classes'].append(res_domain)
+ newnode[0]['classes'].append(res_role.replace(':', '-'))
+ return newnode
+
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
@@ -1431,7 +1622,7 @@ class BuildEnvironment:
for node in doctree.traverse(addnodes.only):
try:
ret = builder.tags.eval_condition(node['expr'])
- except Exception, err:
+ except Exception as err:
self.warn_node('exception while evaluating only '
'directive expression: %s' % err, node)
node.replace_self(node.children or nodes.comment())
@@ -1446,6 +1637,7 @@ class BuildEnvironment:
# a list of all docnames whose section numbers changed
rewrite_needed = []
+ assigned = set()
old_secnumbers = self.toc_secnumbers
self.toc_secnumbers = {}
@@ -1485,17 +1677,19 @@ class BuildEnvironment:
if depth == 0:
return
for (title, ref) in toctreenode['entries']:
- if url_re.match(ref) or ref == 'self':
+ if url_re.match(ref) or ref == 'self' or ref in assigned:
# don't mess with those
continue
if ref in self.tocs:
secnums = self.toc_secnumbers[ref] = {}
+ assigned.add(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:
+ assigned.add(docname)
doctree = self.get_doctree(docname)
for toctreenode in doctree.traverse(addnodes.toctree):
depth = toctreenode.get('numbered', 0)
@@ -1506,6 +1700,78 @@ class BuildEnvironment:
return rewrite_needed
+ def assign_figure_numbers(self):
+ """Assign a figure number to each figure under a numbered toctree."""
+
+ rewrite_needed = []
+
+ assigned = set()
+ old_fignumbers = self.toc_fignumbers
+ self.toc_fignumbers = {}
+ fignum_counter = {}
+
+ def get_section_number(docname, section):
+ anchorname = '#' + section['ids'][0]
+ secnumbers = self.toc_secnumbers.get(docname, {})
+ if anchorname in secnumbers:
+ secnum = secnumbers.get(anchorname)
+ else:
+ secnum = secnumbers.get('')
+
+ return secnum or tuple()
+
+ def get_next_fignumber(figtype, secnum):
+ counter = fignum_counter.setdefault(figtype, {})
+
+ secnum = secnum[:self.config.numfig_secnum_depth]
+ counter[secnum] = counter.get(secnum, 0) + 1
+ return secnum + (counter[secnum],)
+
+ def register_fignumber(docname, secnum, figtype, figure_id):
+ self.toc_fignumbers.setdefault(docname, {})
+ fignumbers = self.toc_fignumbers[docname].setdefault(figtype, {})
+ fignumbers[figure_id] = get_next_fignumber(figtype, secnum)
+
+ def _walk_doctree(docname, doctree, secnum):
+ for subnode in doctree.children:
+ if isinstance(subnode, nodes.section):
+ next_secnum = get_section_number(docname, subnode)
+ if next_secnum:
+ _walk_doctree(docname, subnode, next_secnum)
+ else:
+ _walk_doctree(docname, subnode, secnum)
+ continue
+ elif isinstance(subnode, addnodes.toctree):
+ for title, subdocname in subnode['entries']:
+ if url_re.match(subdocname) or subdocname == 'self':
+ # don't mess with those
+ continue
+
+ _walk_doc(subdocname, secnum)
+
+ continue
+
+ figtype = get_figtype(subnode)
+ if figtype and subnode['ids']:
+ register_fignumber(docname, secnum,
+ figtype, subnode['ids'][0])
+
+ _walk_doctree(docname, subnode, secnum)
+
+ def _walk_doc(docname, secnum):
+ if docname not in assigned:
+ assigned.add(docname)
+ doctree = self.get_doctree(docname)
+ _walk_doctree(docname, doctree, secnum)
+
+ if self.config.numfig:
+ _walk_doc(self.config.master_doc, tuple())
+ for docname, fignums in iteritems(self.toc_fignumbers):
+ if fignums != old_fignumbers.get(docname):
+ rewrite_needed.append(docname)
+
+ return rewrite_needed
+
def create_index(self, builder, group_entries=True,
_fixre=re.compile(r'(.*) ([(][^()]*[)])')):
"""Create the real index from the collected index entries."""
@@ -1515,7 +1781,7 @@ class BuildEnvironment:
# 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)
+ word = text_type(word)
entry = dic.get(word)
if not entry:
dic[word] = entry = [[], {}]
@@ -1529,7 +1795,7 @@ class BuildEnvironment:
else:
entry[0].append((main, uri))
- for fn, entries in self.indexentries.iteritems():
+ for fn, entries in iteritems(self.indexentries):
# new entry types must be listed in directives/other.py!
for type, value, tid, main in entries:
try:
@@ -1557,7 +1823,7 @@ class BuildEnvironment:
add_entry(first, _('see also %s') % second, link=False)
else:
self.warn(fn, 'unknown index entry type %r' % type)
- except ValueError, err:
+ except ValueError as err:
self.warn(fn, str(err))
# sort the index entries; put all symbols at the front, even those
@@ -1567,8 +1833,7 @@ class BuildEnvironment:
if lckey[0:1] in lcletters:
return chr(127) + lckey
return lckey
- newlist = new.items()
- newlist.sort(key=keyfunc)
+ newlist = sorted(new.items(), key=keyfunc)
if group_entries:
# fixup entries: transform
@@ -1591,7 +1856,7 @@ class BuildEnvironment:
# prefixes match: add entry as subitem of the
# previous entry
oldsubitems.setdefault(m.group(2), [[], {}])[0].\
- extend(targets)
+ extend(targets)
del newlist[i]
continue
oldkey = m.group(1)
@@ -1604,7 +1869,7 @@ class BuildEnvironment:
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())
+ v[1] = sorted((si, se) for (si, (se, void)) in iteritems(v[1]))
# now calculate the key
letter = unicodedata.normalize('NFD', k[0])[0].upper()
if letter in letters:
@@ -1618,6 +1883,7 @@ class BuildEnvironment:
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:
@@ -1656,9 +1922,9 @@ class BuildEnvironment:
# else it will stay None
# same for children
if includes:
- for subindex, args in enumerate(izip(includes,
- [None] + includes,
- includes[1:] + [None])):
+ for subindex, args in enumerate(zip(includes,
+ [None] + includes,
+ includes[1:] + [None])):
collect([(docname, subindex)] + parents,
parents_set.union([docname]), *args)
relations[docname] = [parents[0][0], previous, next]
diff --git a/sphinx/errors.py b/sphinx/errors.py
index 4d737e51..3d7a5eb4 100644
--- a/sphinx/errors.py
+++ b/sphinx/errors.py
@@ -10,6 +10,9 @@
:license: BSD, see LICENSE for details.
"""
+import traceback
+
+
class SphinxError(Exception):
"""
Base class for Sphinx errors that are shown to the user in a nicer
@@ -62,3 +65,13 @@ class PycodeError(Exception):
if len(self.args) > 1:
res += ' (exception was: %r)' % self.args[1]
return res
+
+
+class SphinxParallelError(Exception):
+ def __init__(self, orig_exc, traceback):
+ self.orig_exc = orig_exc
+ self.traceback = traceback
+
+ def __str__(self):
+ return traceback.format_exception_only(
+ self.orig_exc.__class__, self.orig_exc)[0].strip()
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index b4ecf32f..5b0bda17 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -17,10 +17,12 @@ import inspect
import traceback
from types import FunctionType, BuiltinFunctionType, MethodType
+from six import iteritems, itervalues, text_type, class_types
from docutils import nodes
from docutils.utils import assemble_option_dict
from docutils.statemachine import ViewList
+import sphinx
from sphinx.util import rpartition, force_decode
from sphinx.locale import _
from sphinx.pycode import ModuleAnalyzer, PycodeError
@@ -28,8 +30,7 @@ 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
+ safe_getattr, safe_repr, is_builtin_class_method
from sphinx.util.docstrings import prepare_docstring
@@ -49,14 +50,17 @@ class DefDict(dict):
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):
+
+ def __bool__(self):
# docutils check "if option_spec"
return True
+ __nonzero__ = __bool__ # for python2 compatibility
identity = lambda x: x
@@ -70,15 +74,47 @@ class Options(dict):
return None
+class _MockModule(object):
+ """Used by autodoc_mock_imports."""
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def __call__(self, *args, **kwargs):
+ return _MockModule()
+
+ @classmethod
+ def __getattr__(cls, name):
+ if name in ('__file__', '__path__'):
+ return '/dev/null'
+ elif name[0] == name[0].upper():
+ # Not very good, we assume Uppercase names are classes...
+ mocktype = type(name, (), {})
+ mocktype.__module__ = __name__
+ return mocktype
+ else:
+ return _MockModule()
+
+
+def mock_import(modname):
+ if '.' in modname:
+ pkg, _n, mods = modname.rpartition('.')
+ mock_import(pkg)
+ mod = _MockModule()
+ sys.modules[modname] = mod
+ return mod
+
+
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:
@@ -87,6 +123,7 @@ def members_set_option(arg):
SUPPRESS = object()
+
def annotation_option(arg):
if arg is None:
# suppress showing the representation of the object
@@ -94,6 +131,7 @@ def annotation_option(arg):
else:
return arg
+
def bool_option(arg):
"""Used to convert flag options to auto directives. (Instead of
directives.flag(), which returns None).
@@ -170,6 +208,7 @@ def cut_lines(pre, post=0, what=None):
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
@@ -180,6 +219,7 @@ def between(marker, what=None, keepempty=False, exclude=False):
be processed.
"""
marker_re = re.compile(marker)
+
def process(app, what_, name, obj, options, lines):
if what and what_ not in what:
return
@@ -235,7 +275,7 @@ class Documenter(object):
@staticmethod
def get_attr(obj, name, *defargs):
"""getattr() override for types such as Zope interfaces."""
- for typ, func in AutoDirective._special_attrgetters.iteritems():
+ for typ, func in iteritems(AutoDirective._special_attrgetters):
if isinstance(obj, typ):
return func(obj, name, *defargs)
return safe_getattr(obj, name, *defargs)
@@ -294,7 +334,7 @@ class Documenter(object):
# an autogenerated one
try:
explicit_modname, path, base, args, retann = \
- py_ext_sig_re.match(self.name).groups()
+ py_ext_sig_re.match(self.name).groups()
except AttributeError:
self.directive.warn('invalid signature for auto%s (%r)' %
(self.objtype, self.name))
@@ -309,7 +349,7 @@ class Documenter(object):
parents = []
self.modname, self.objpath = \
- self.resolve_name(modname, parents, path, base)
+ self.resolve_name(modname, parents, path, base)
if not self.modname:
return False
@@ -332,6 +372,9 @@ class Documenter(object):
self.modname, '.'.join(self.objpath))
try:
dbg('[autodoc] import %s', self.modname)
+ for modname in self.env.config.autodoc_mock_imports:
+ dbg('[autodoc] adding a mock module %s!', self.modname)
+ mock_import(modname)
__import__(self.modname)
parent = None
obj = self.module = sys.modules[self.modname]
@@ -347,7 +390,7 @@ class Documenter(object):
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), e:
+ 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)
@@ -415,7 +458,7 @@ class Documenter(object):
# try to introspect the signature
try:
args = self.format_args()
- except Exception, err:
+ except Exception as err:
self.directive.warn('error while formatting arguments for '
'%s: %s' % (self.fullname, err))
args = None
@@ -452,7 +495,7 @@ class Documenter(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):
+ if isinstance(docstring, text_type):
return [prepare_docstring(docstring, ignore)]
elif isinstance(docstring, str): # this will not trigger on Py3
return [prepare_docstring(force_decode(docstring, encoding),
@@ -476,9 +519,9 @@ class Documenter(object):
# 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')
+ if not isinstance(self.analyzer.srcname, text_type):
+ filename = text_type(self.analyzer.srcname,
+ sys.getfilesystemencoding(), 'replace')
else:
filename = self.analyzer.srcname
sourcename = u'%s:docstring of %s' % (filename, self.fullname)
@@ -522,7 +565,7 @@ class Documenter(object):
if self.analyzer:
attr_docs = self.analyzer.find_attr_docs()
namespace = '.'.join(self.objpath)
- for item in attr_docs.iteritems():
+ for item in iteritems(attr_docs):
if item[0][0] == namespace:
analyzed_member_names.add(item[0][1])
if not want_all:
@@ -603,19 +646,19 @@ class Documenter(object):
keep = False
if want_all and membername.startswith('__') and \
- membername.endswith('__') and len(membername) > 4:
+ 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 \
+ 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)
+ (has_doc or self.options.undoc_members)
elif (namespace, membername) in attr_docs:
# keep documented attributes
keep = True
@@ -651,7 +694,7 @@ class Documenter(object):
self.env.temp_data['autodoc:class'] = self.objpath[0]
want_all = all_members or self.options.inherited_members or \
- self.options.members is ALL
+ self.options.members is ALL
# find out which members are documentable
members_check_module, members = self.get_object_members(want_all)
@@ -663,7 +706,7 @@ class Documenter(object):
# document non-skipped members
memberdocumenters = []
for (mname, member, isattr) in self.filter_members(members, want_all):
- classes = [cls for cls in AutoDirective._registry.itervalues()
+ classes = [cls for cls in itervalues(AutoDirective._registry)
if cls.can_document_member(member, mname, isattr, self)]
if not classes:
# don't know how to document this member
@@ -673,11 +716,11 @@ class Documenter(object):
# give explicitly separated module name, so that members
# of inner classes can be documented
full_mname = self.modname + '::' + \
- '.'.join(self.objpath + [mname])
+ '.'.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
+ 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
@@ -685,6 +728,7 @@ class Documenter(object):
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))
@@ -735,7 +779,7 @@ class Documenter(object):
# parse right now, to get PycodeErrors on parsing (results will
# be cached anyway)
self.analyzer.find_attr_docs()
- except PycodeError, err:
+ except PycodeError as err:
self.env.app.debug('[autodoc] module analyzer failed: %s', err)
# no source file -- e.g. for builtin and C modules
self.analyzer = None
@@ -838,7 +882,7 @@ class ModuleDocumenter(Documenter):
self.directive.warn(
'missing attribute mentioned in :members: or __all__: '
'module %s, attribute %s' % (
- safe_getattr(self.object, '__name__', '???'), mname))
+ safe_getattr(self.object, '__name__', '???'), mname))
return False, ret
@@ -857,7 +901,7 @@ class ModuleLevelDocumenter(Documenter):
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')
+ modname = self.env.ref_context.get('py:module')
# ... else, it stays None, which means invalid
return modname, parents + [base]
@@ -879,7 +923,7 @@ class ClassLevelDocumenter(Documenter):
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')
+ mod_cls = self.env.ref_context.get('py:class')
# ... if still None, there's no way to know
if mod_cls is None:
return None, []
@@ -889,7 +933,7 @@ class ClassLevelDocumenter(Documenter):
if not modname:
modname = self.env.temp_data.get('autodoc:module')
if not modname:
- modname = self.env.temp_data.get('py:module')
+ modname = self.env.ref_context.get('py:module')
# ... else, it stays None, which means invalid
return modname, parents + [base]
@@ -943,6 +987,24 @@ class DocstringSignatureMixin(object):
return Documenter.format_signature(self)
+class DocstringStripSignatureMixin(DocstringSignatureMixin):
+ """
+ Mixin for AttributeDocumenter to provide the
+ feature of stripping any function signature from the docstring.
+ """
+ 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:
+ # Discarding _args is a only difference with
+ # DocstringSignatureMixin.format_signature.
+ # Documenter.format_signature use self.args value to format.
+ _args, self.retann = result
+ return Documenter.format_signature(self)
+
+
class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
"""
Specialized Documenter subclass for functions.
@@ -956,7 +1018,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
def format_args(self):
if inspect.isbuiltin(self.object) or \
- inspect.ismethoddescriptor(self.object):
+ inspect.ismethoddescriptor(self.object):
# cannot introspect arguments of a C function or method
return None
try:
@@ -1019,8 +1081,8 @@ class ClassDocumenter(ModuleLevelDocumenter):
# 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)):
+ is_builtin_class_method(self.object, '__init__') or \
+ not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
return None
try:
argspec = getargspec(initmeth)
@@ -1058,7 +1120,7 @@ class ClassDocumenter(ModuleLevelDocumenter):
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
+ bases = [b.__module__ in ('__builtin__', 'builtins') and
u':class:`%s`' % b.__name__ or
u':class:`%s.%s`' % (b.__module__, b.__name__)
for b in self.object.__bases__]
@@ -1091,7 +1153,7 @@ class ClassDocumenter(ModuleLevelDocumenter):
# 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.strip() == object.__init__.__doc__)): # for !pypy
initdocstring = None
if initdocstring:
if content == 'init':
@@ -1100,7 +1162,7 @@ class ClassDocumenter(ModuleLevelDocumenter):
docstrings.append(initdocstring)
doc = []
for docstring in docstrings:
- if not isinstance(docstring, unicode):
+ if not isinstance(docstring, text_type):
docstring = force_decode(docstring, encoding)
doc.append(prepare_docstring(docstring))
return doc
@@ -1135,7 +1197,7 @@ class ExceptionDocumenter(ClassDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
return isinstance(member, class_types) and \
- issubclass(member, base_exception)
+ issubclass(member, BaseException)
class DataDocumenter(ModuleLevelDocumenter):
@@ -1182,48 +1244,31 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
@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'
+ not isinstance(parent, ModuleDocumenter)
+
+ def import_object(self):
+ ret = ClassLevelDocumenter.import_object(self)
+ if not ret:
return ret
+ # to distinguish classmethod/staticmethod
+ obj = self.parent.__dict__.get(self.object_name)
+
+ if isinstance(obj, classmethod):
+ self.directivetype = 'classmethod'
+ # document class and static members before ordinary ones
+ self.member_order = self.member_order - 1
+ elif isinstance(obj, staticmethod):
+ 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):
+ inspect.ismethoddescriptor(self.object):
# can never get arguments of a C function or method
return None
argspec = getargspec(self.object)
@@ -1238,7 +1283,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
pass
-class AttributeDocumenter(ClassLevelDocumenter):
+class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
"""
Specialized Documenter subclass for attributes.
"""
@@ -1256,9 +1301,9 @@ class AttributeDocumenter(ClassLevelDocumenter):
@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")
+ 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))
@@ -1269,7 +1314,7 @@ class AttributeDocumenter(ClassLevelDocumenter):
def import_object(self):
ret = ClassLevelDocumenter.import_object(self)
if isdescriptor(self.object) and \
- not isinstance(self.object, self.method_types):
+ not isinstance(self.object, self.method_types):
self._datadescriptor = True
else:
# if it's not a data descriptor
@@ -1278,7 +1323,7 @@ class AttributeDocumenter(ClassLevelDocumenter):
def get_real_modname(self):
return self.get_attr(self.parent or self.object, '__module__', None) \
- or self.modname
+ or self.modname
def add_directive_header(self, sig):
ClassLevelDocumenter.add_directive_header(self, sig)
@@ -1401,7 +1446,7 @@ class AutoDirective(Directive):
try:
self.genopt = Options(assemble_option_dict(
self.options.items(), doc_class.option_spec))
- except (KeyError, ValueError, TypeError), err:
+ except (KeyError, ValueError, TypeError) as 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),
@@ -1445,7 +1490,7 @@ def add_documenter(cls):
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:
+ # if cls.objtype in AutoDirective._registry:
# raise ExtensionError('autodoc documenter for %r is already '
# 'registered' % cls.objtype)
AutoDirective._registry[cls.objtype] = cls
@@ -1465,10 +1510,13 @@ def setup(app):
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_config_value('autodoc_mock_imports', [], True)
app.add_event('autodoc-process-docstring')
app.add_event('autodoc-process-signature')
app.add_event('autodoc-skip-member')
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
+
class testcls:
"""test doc string"""
diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py
index 8798e7f6..908c96ca 100644
--- a/sphinx/ext/autosummary/__init__.py
+++ b/sphinx/ext/autosummary/__init__.py
@@ -60,10 +60,12 @@ import inspect
import posixpath
from types import ModuleType
+from six import text_type
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
from docutils import nodes
+import sphinx
from sphinx import addnodes
from sphinx.util.compat import Directive
from sphinx.pycode import ModuleAnalyzer, PycodeError
@@ -118,7 +120,7 @@ def autosummary_table_visit_html(self, node):
par = col1_entry[0]
for j, subnode in enumerate(list(par)):
if isinstance(subnode, nodes.Text):
- new_text = unicode(subnode.astext())
+ new_text = text_type(subnode.astext())
new_text = new_text.replace(u" ", u"\u00a0")
par[j] = nodes.Text(new_text)
except IndexError:
@@ -271,11 +273,11 @@ class Autosummary(Directive):
# try to also get a source code analyzer for attribute docs
try:
documenter.analyzer = ModuleAnalyzer.for_module(
- documenter.get_real_modname())
+ 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:
+ except PycodeError as err:
documenter.env.app.debug(
'[autodoc] module analyzer failed: %s', err)
# no source file -- e.g. for builtin and C modules
@@ -431,11 +433,11 @@ def get_import_prefixes_from_env(env):
"""
prefixes = [None]
- currmodule = env.temp_data.get('py:module')
+ currmodule = env.ref_context.get('py:module')
if currmodule:
prefixes.insert(0, currmodule)
- currclass = env.temp_data.get('py:class')
+ currclass = env.ref_context.get('py:class')
if currclass:
if currmodule:
prefixes.insert(0, currmodule + "." + currclass)
@@ -498,7 +500,7 @@ def _import_by_name(name):
return obj, parent, modname
else:
return sys.modules[modname], None, modname
- except (ValueError, ImportError, AttributeError, KeyError), e:
+ except (ValueError, ImportError, AttributeError, KeyError) as e:
raise ImportError(*e.args)
@@ -569,3 +571,4 @@ def setup(app):
app.connect('doctree-read', process_autosummary_toc)
app.connect('builder-inited', process_generate_options)
app.add_config_value('autosummary_generate', [], True)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index 47ef9868..11b1dfe7 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -17,6 +17,7 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
import os
import re
@@ -70,10 +71,10 @@ def main(argv=sys.argv):
template_dir=options.templates)
def _simple_info(msg):
- print msg
+ print(msg)
def _simple_warn(msg):
- print >> sys.stderr, 'WARNING: ' + msg
+ print('WARNING: ' + msg, file=sys.stderr)
# -- Generating output ---------------------------------------------------------
@@ -109,14 +110,11 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
# 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):
+ for name, path, template_name in sorted(set(items), key=str):
if path is None:
# The corresponding autosummary:: directive did not have
# a :toctree: option
@@ -127,7 +125,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
try:
name, obj, parent, mod_name = import_by_name(name)
- except ImportError, e:
+ except ImportError as e:
warn('[autosummary] failed to import %r: %s' % (name, e))
continue
@@ -240,9 +238,9 @@ def find_autosummary_in_docstring(name, module=None, filename=None):
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:
+ except ImportError as e:
+ print("Failed to import '%s': %s" % (name, e))
+ except SystemExit as e:
print("Failed to import '%s'; the module executes module level "
"statement and it might call sys.exit()." % name)
return []
diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py
index 52be1bdb..399935cc 100644
--- a/sphinx/ext/coverage.py
+++ b/sphinx/ext/coverage.py
@@ -13,9 +13,12 @@
import re
import glob
import inspect
-import cPickle as pickle
from os import path
+from six import iteritems
+from six.moves import cPickle as pickle
+
+import sphinx
from sphinx.builders import Builder
@@ -52,7 +55,7 @@ class CoverageBuilder(Builder):
self.warn('invalid regex %r in coverage_c_regexes' % exp)
self.c_ignorexps = {}
- for (name, exps) in self.config.coverage_ignore_c_items.iteritems():
+ for (name, exps) in iteritems(self.config.coverage_ignore_c_items):
self.c_ignorexps[name] = compile_regex_list(
'coverage_ignore_c_items', exps, self.warn)
self.mod_ignorexps = compile_regex_list(
@@ -81,7 +84,7 @@ class CoverageBuilder(Builder):
# Fetch all the info from the header files
c_objects = self.env.domaindata['c']['objects']
for filename in self.c_sourcefiles:
- undoc = []
+ undoc = set()
f = open(filename, 'r')
try:
for line in f:
@@ -94,7 +97,7 @@ class CoverageBuilder(Builder):
if exp.match(name):
break
else:
- undoc.append((key, name))
+ undoc.add((key, name))
continue
finally:
f.close()
@@ -109,9 +112,9 @@ class CoverageBuilder(Builder):
write_header(op, 'Undocumented C API elements', '=')
op.write('\n')
- for filename, undoc in self.c_undoc.iteritems():
+ for filename, undoc in iteritems(self.c_undoc):
write_header(op, filename)
- for typ, name in undoc:
+ for typ, name in sorted(undoc):
op.write(' * %-50s [%9s]\n' % (name, typ))
op.write('\n')
finally:
@@ -134,7 +137,7 @@ class CoverageBuilder(Builder):
try:
mod = __import__(mod_name, fromlist=['foo'])
- except ImportError, err:
+ except ImportError as err:
self.warn('module %s could not be imported: %s' %
(mod_name, err))
self.py_undoc[mod_name] = {'error': err}
@@ -211,8 +214,7 @@ class CoverageBuilder(Builder):
try:
if self.config.coverage_write_headline:
write_header(op, 'Undocumented Python objects', '=')
- keys = self.py_undoc.keys()
- keys.sort()
+ keys = sorted(self.py_undoc.keys())
for name in keys:
undoc = self.py_undoc[name]
if 'error' in undoc:
@@ -229,7 +231,7 @@ class CoverageBuilder(Builder):
if undoc['classes']:
op.write('Classes:\n')
for name, methods in sorted(
- undoc['classes'].iteritems()):
+ iteritems(undoc['classes'])):
if not methods:
op.write(' * %s\n' % name)
else:
@@ -263,3 +265,4 @@ def setup(app):
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)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py
index 70beb9bf..216325cb 100644
--- a/sphinx/ext/doctest.py
+++ b/sphinx/ext/doctest.py
@@ -14,24 +14,25 @@ import re
import sys
import time
import codecs
-import StringIO
from os import path
# circumvent relative import
doctest = __import__('doctest')
+from six import itervalues, StringIO, binary_type
from docutils import nodes
from docutils.parsers.rst import directives
+import sphinx
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):
@@ -79,30 +80,35 @@ class TestDirective(Directive):
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):
+ 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,
@@ -112,6 +118,7 @@ class TestoutputDirective(TestDirective):
parser = doctest.DocTestParser()
+
# helper classes
class TestGroup(object):
@@ -158,7 +165,7 @@ class TestCode(object):
class SphinxDocTestRunner(doctest.DocTestRunner):
def summarize(self, out, verbose=None):
- string_io = StringIO.StringIO()
+ string_io = StringIO()
old_stdout = sys.stdout
sys.stdout = string_io
try:
@@ -196,7 +203,7 @@ class DocTestBuilder(Builder):
def init(self):
# default options
self.opt = doctest.DONT_ACCEPT_TRUE_FOR_1 | doctest.ELLIPSIS | \
- doctest.IGNORE_EXCEPTION_DETAIL
+ doctest.IGNORE_EXCEPTION_DETAIL
# HACK HACK HACK
# doctest compiles its snippets with type 'single'. That is nice
@@ -233,7 +240,7 @@ Results of doctest builder run on %s
self.info(text, nonl=True)
if self.app.quiet:
self.warn(text)
- if isinstance(text, bytes):
+ if isinstance(text, binary_type):
text = force_decode(text, None)
self.outfile.write(text)
@@ -247,6 +254,10 @@ Results of doctest builder run on %s
# write executive summary
def s(v):
return v != 1 and 's' or ''
+ repl = (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._out('''
Doctest summary
===============
@@ -254,10 +265,7 @@ Doctest summary
%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)))
+''' % repl)
self.outfile.close()
if self.total_failures or self.setup_failures or self.cleanup_failures:
@@ -289,14 +297,14 @@ Doctest summary
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)
+ and 'testnodetype' in node) or \
+ isinstance(node, nodes.doctest_block)
else:
def condition(node):
return isinstance(node, (nodes.literal_block, nodes.comment)) \
- and node.has_key('testnodetype')
+ and 'testnodetype' in node
for node in doctree.traverse(condition):
- source = node.has_key('test') and node['test'] or node.astext()
+ source = 'test' in node and node['test'] or node.astext()
if not source:
self.warn('no code/output in %s block at %s:%s' %
(node.get('testnodetype', 'doctest'),
@@ -312,24 +320,24 @@ Doctest summary
groups[groupname] = TestGroup(groupname)
groups[groupname].add_code(code)
for code in add_to_all_groups:
- for group in groups.itervalues():
+ for group in itervalues(groups):
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():
+ for group in itervalues(groups):
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():
+ for group in itervalues(groups):
group.add_code(code)
if not groups:
return
self._out('\nDocument: %s\n----------%s\n' %
(docname, '-'*len(docname)))
- for group in groups.itervalues():
+ for group in itervalues(groups):
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)
@@ -364,7 +372,7 @@ Doctest summary
filename, 0, None)
sim_doctest.globs = ns
old_f = runner.failures
- self.type = 'exec' # the snippet may contain multiple statements
+ 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
@@ -394,7 +402,7 @@ Doctest summary
new_opt = code[0].options.copy()
new_opt.update(example.options)
example.options = new_opt
- self.type = 'single' # as for ordinary doctests
+ self.type = 'single' # as for ordinary doctests
else:
# testcode and output separate
output = code[1] and code[1].code or ''
@@ -413,7 +421,7 @@ Doctest summary
options=options)
test = doctest.DocTest([example], {}, group.name,
filename, code[0].lineno, None)
- self.type = 'exec' # multiple statements again
+ 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
@@ -435,3 +443,4 @@ def setup(app):
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)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/extlinks.py b/sphinx/ext/extlinks.py
index 18da573e..ae65dbb8 100644
--- a/sphinx/ext/extlinks.py
+++ b/sphinx/ext/extlinks.py
@@ -24,8 +24,10 @@
:license: BSD, see LICENSE for details.
"""
+from six import iteritems
from docutils import nodes, utils
+import sphinx
from sphinx.util.nodes import split_explicit_title
@@ -51,9 +53,10 @@ def make_link_role(base_url, prefix):
return role
def setup_link_roles(app):
- for name, (base_url, prefix) in app.config.extlinks.iteritems():
+ for name, (base_url, prefix) in iteritems(app.config.extlinks):
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)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py
index 028560b1..71e7ba65 100644
--- a/sphinx/ext/graphviz.py
+++ b/sphinx/ext/graphviz.py
@@ -15,14 +15,14 @@ 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 hashlib import sha1
+from six import text_type
from docutils import nodes
from docutils.parsers.rst import directives
+from docutils.statemachine import ViewList
+import sphinx
from sphinx.errors import SphinxError
from sphinx.locale import _
from sphinx.util.osutil import ensuredir, ENOENT, EPIPE, EINVAL
@@ -40,6 +40,20 @@ class graphviz(nodes.General, nodes.Element):
pass
+def figure_wrapper(directive, node, caption):
+ figure_node = nodes.figure('', node)
+
+ parsed = nodes.Element()
+ directive.state.nested_parse(ViewList([caption], source=''),
+ directive.content_offset, parsed)
+ caption_node = nodes.caption(parsed[0].rawsource, '',
+ *parsed[0].children)
+ caption_node.source = parsed[0].source
+ caption_node.line = parsed[0].line
+ figure_node += caption_node
+ return figure_node
+
+
class Graphviz(Directive):
"""
Directive to insert arbitrary dot markup.
@@ -85,9 +99,12 @@ class Graphviz(Directive):
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
+
+ caption = self.options.get('caption')
+ if caption and not node['inline']:
+ node = figure_wrapper(self, node, caption)
+
return [node]
@@ -112,9 +129,12 @@ class GraphvizSimple(Directive):
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
+
+ caption = self.options.get('caption')
+ if caption and not node['inline']:
+ node = figure_wrapper(self, node, caption)
+
return [node]
@@ -125,15 +145,9 @@ def render_dot(self, code, options, format, prefix='graphviz'):
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)
+ fname = '%s-%s.%s' % (prefix, sha1(hashkey).hexdigest(), format)
+ relfn = posixpath.join(self.builder.imgpath, fname)
+ outfn = path.join(self.builder.outdir, self.builder.imagedir, fname)
if path.isfile(outfn):
return relfn, outfn
@@ -145,7 +159,7 @@ def render_dot(self, code, options, format, prefix='graphviz'):
ensuredir(path.dirname(outfn))
# graphviz expects UTF-8 by default
- if isinstance(code, unicode):
+ if isinstance(code, text_type):
code = code.encode('utf-8')
dot_args = [self.builder.config.graphviz_dot]
@@ -156,7 +170,7 @@ def render_dot(self, code, options, format, prefix='graphviz'):
dot_args.extend(['-Tcmapx', '-o%s.map' % outfn])
try:
p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE)
- except OSError, err:
+ except OSError as err:
if err.errno != ENOENT: # No such file or directory
raise
self.builder.warn('dot command %r cannot be run (needed for graphviz '
@@ -168,7 +182,7 @@ def render_dot(self, code, options, format, prefix='graphviz'):
# 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:
+ except (OSError, IOError) as err:
if err.errno not in (EPIPE, EINVAL):
raise
# in this case, read the standard output and standard error streams
@@ -192,7 +206,7 @@ def render_dot_html(self, node, code, options, prefix='graphviz',
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:
+ except GraphvizError as exc:
self.builder.warn('dot code %r: ' % code + str(exc))
raise nodes.SkipNode
@@ -228,9 +242,6 @@ def render_dot_html(self, node, code, options, prefix='graphviz',
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
@@ -243,7 +254,7 @@ def html_visit_graphviz(self, node):
def render_dot_latex(self, node, code, options, prefix='graphviz'):
try:
fname, outfn = render_dot(self, code, options, 'pdf', prefix)
- except GraphvizError, exc:
+ except GraphvizError as exc:
self.builder.warn('dot code %r: ' % code + str(exc))
raise nodes.SkipNode
@@ -254,18 +265,8 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'):
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))
+ self.body.append('%s\\includegraphics{%s}%s' %
+ (para_separator, fname, para_separator))
raise nodes.SkipNode
@@ -276,16 +277,11 @@ def latex_visit_graphviz(self, node):
def render_dot_texinfo(self, node, code, options, prefix='graphviz'):
try:
fname, outfn = render_dot(self, code, options, 'png', prefix)
- except GraphvizError, exc:
+ except GraphvizError as exc:
self.builder.warn('dot code %r: ' % code + str(exc))
raise nodes.SkipNode
if fname is not None:
- self.body.append('\n\n@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])
+ self.body.append('@image{%s,,,[graphviz],png}\n' % fname[:-4])
raise nodes.SkipNode
def texinfo_visit_graphviz(self, node):
@@ -321,3 +317,4 @@ def setup(app):
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')
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/ifconfig.py b/sphinx/ext/ifconfig.py
index 3362e56a..a4e4a02d 100644
--- a/sphinx/ext/ifconfig.py
+++ b/sphinx/ext/ifconfig.py
@@ -22,6 +22,7 @@
from docutils import nodes
+import sphinx
from sphinx.util.nodes import set_source_info
from sphinx.util.compat import Directive
@@ -53,7 +54,7 @@ def process_ifconfig_nodes(app, doctree, docname):
for node in doctree.traverse(ifconfig):
try:
res = eval(node['expr'], ns)
- except Exception, err:
+ except Exception as err:
# handle exceptions in a clean fashion
from traceback import format_exception_only
msg = ''.join(format_exception_only(err.__class__, err))
@@ -72,3 +73,4 @@ def setup(app):
app.add_node(ifconfig)
app.add_directive('ifconfig', IfConfig)
app.connect('doctree-resolved', process_ifconfig_nodes)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py
index 5b8eab3f..0b2e5ce3 100644
--- a/sphinx/ext/inheritance_diagram.py
+++ b/sphinx/ext/inheritance_diagram.py
@@ -39,15 +39,18 @@ r"""
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 six import text_type
+from six.moves import builtins
+
from docutils import nodes
from docutils.parsers.rst import directives
+import sphinx
from sphinx.ext.graphviz import render_dot_html, render_dot_latex, \
render_dot_texinfo
from sphinx.pycode import ModuleAnalyzer
@@ -145,10 +148,10 @@ class InheritanceGraph(object):
displayed node names.
"""
all_classes = {}
- builtins = vars(__builtin__).values()
+ py_builtins = vars(builtins).values()
def recurse(cls):
- if not show_builtins and cls in builtins:
+ if not show_builtins and cls in py_builtins:
return
if not private_bases and cls.__name__.startswith('_'):
return
@@ -162,7 +165,7 @@ class InheritanceGraph(object):
if cls.__doc__:
enc = ModuleAnalyzer.for_module(cls.__module__).encoding
doc = cls.__doc__.strip().split("\n")[0]
- if not isinstance(doc, unicode):
+ if not isinstance(doc, text_type):
doc = force_decode(doc, enc)
if doc:
tooltip = '"%s"' % doc.replace('"', '\\"')
@@ -172,7 +175,7 @@ class InheritanceGraph(object):
baselist = []
all_classes[cls] = (nodename, fullname, baselist, tooltip)
for base in cls.__bases__:
- if not show_builtins and base in builtins:
+ if not show_builtins and base in py_builtins:
continue
if not private_bases and base.__name__.startswith('_'):
continue
@@ -192,7 +195,7 @@ class InheritanceGraph(object):
completely general.
"""
module = cls.__module__
- if module == '__builtin__':
+ if module in ('__builtin__', 'builtins'):
fullname = cls.__name__
else:
fullname = '%s.%s' % (module, cls.__name__)
@@ -308,10 +311,10 @@ class InheritanceDiagram(Directive):
# Create a graph starting with the list of classes
try:
graph = InheritanceGraph(
- class_names, env.temp_data.get('py:module'),
+ class_names, env.ref_context.get('py:module'),
parts=node['parts'],
private_bases='private-bases' in self.options)
- except InheritanceException, err:
+ except InheritanceException as err:
return [node.document.reporter.warning(err.args[0],
line=self.lineno)]
@@ -405,3 +408,4 @@ def setup(app):
app.add_config_value('inheritance_graph_attrs', {}, False),
app.add_config_value('inheritance_node_attrs', {}, False),
app.add_config_value('inheritance_edge_attrs', {}, False),
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py
index c3adf563..6f3d44eb 100644
--- a/sphinx/ext/intersphinx.py
+++ b/sphinx/ext/intersphinx.py
@@ -27,27 +27,28 @@
import time
import zlib
import codecs
-import urllib2
import posixpath
from os import path
import re
+from six import iteritems
+from six.moves.urllib import request
from docutils import nodes
from docutils.utils import relative_path
+import sphinx
from sphinx.locale import _
from sphinx.builders.html import INVENTORY_FILENAME
-from sphinx.util.pycompat import b
-handlers = [urllib2.ProxyHandler(), urllib2.HTTPRedirectHandler(),
- urllib2.HTTPHandler()]
+handlers = [request.ProxyHandler(), request.HTTPRedirectHandler(),
+ request.HTTPHandler()]
try:
- handlers.append(urllib2.HTTPSHandler)
+ handlers.append(request.HTTPSHandler)
except AttributeError:
pass
-urllib2.install_opener(urllib2.build_opener(*handlers))
+request.install_opener(request.build_opener(*handlers))
UTF8StreamReader = codecs.lookup('utf-8')[2]
@@ -55,9 +56,9 @@ UTF8StreamReader = codecs.lookup('utf-8')[2]
def read_inventory_v1(f, uri, join):
f = UTF8StreamReader(f)
invdata = {}
- line = f.next()
+ line = next(f)
projname = line.rstrip()[11:]
- line = f.next()
+ line = next(f)
version = line.rstrip()[11:]
for line in f:
name, type, location = line.rstrip().split(None, 2)
@@ -85,19 +86,19 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024):
def read_chunks():
decompressor = zlib.decompressobj()
- for chunk in iter(lambda: f.read(bufsize), b('')):
+ for chunk in iter(lambda: f.read(bufsize), b''):
yield decompressor.decompress(chunk)
yield decompressor.flush()
def split_lines(iter):
- buf = b('')
+ buf = b''
for chunk in iter:
buf += chunk
- lineend = buf.find(b('\n'))
+ lineend = buf.find(b'\n')
while lineend != -1:
yield buf[:lineend].decode('utf-8')
buf = buf[lineend+1:]
- lineend = buf.find(b('\n'))
+ lineend = buf.find(b'\n')
assert not buf
for line in split_lines(read_chunks()):
@@ -129,10 +130,10 @@ def fetch_inventory(app, uri, inv):
join = localuri and path.join or posixpath.join
try:
if inv.find('://') != -1:
- f = urllib2.urlopen(inv)
+ f = request.urlopen(inv)
else:
f = open(path.join(app.srcdir, inv), 'rb')
- except Exception, err:
+ except Exception as err:
app.warn('intersphinx inventory %r not fetchable due to '
'%s: %s' % (inv, err.__class__, err))
return
@@ -149,7 +150,7 @@ def fetch_inventory(app, uri, inv):
except ValueError:
f.close()
raise ValueError('unknown or unsupported inventory version')
- except Exception, err:
+ except Exception as err:
app.warn('intersphinx inventory %r not readable due to '
'%s: %s' % (inv, err.__class__.__name__, err))
else:
@@ -167,7 +168,7 @@ def load_mappings(app):
env.intersphinx_named_inventory = {}
cache = env.intersphinx_cache
update = False
- for key, value in app.config.intersphinx_mapping.iteritems():
+ for key, value in iteritems(app.config.intersphinx_mapping):
if isinstance(value, tuple):
# new format
name, (uri, inv) = key, value
@@ -179,19 +180,25 @@ def load_mappings(app):
# 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 not isinstance(inv, tuple):
+ invs = (inv, )
+ else:
+ invs = inv
+
+ for inv in invs:
+ 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)
+ update = True
+ break
+
if update:
env.intersphinx_inventory = {}
env.intersphinx_named_inventory = {}
@@ -202,28 +209,34 @@ def load_mappings(app):
# 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())
+ cached_vals = list(cache.values())
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():
+ for type, objects in iteritems(invdata):
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]
+ if node['reftype'] == 'any':
+ # we search anything!
+ objtypes = ['%s:%s' % (domain.name, objtype)
+ for domain in env.domains.values()
+ for objtype in domain.object_types]
+ else:
+ domain = node.get('refdomain')
+ if not domain:
+ # only objects in domains are in the inventory
+ return
+ 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:
@@ -241,7 +254,7 @@ def missing_reference(app, env, node, contnode):
# 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))
+ reftitle=_('(in %s v%s)') % (proj, version))
if node.get('refexplicit'):
# use whatever title was given
newnode.append(contnode)
@@ -269,3 +282,4 @@ def setup(app):
app.add_config_value('intersphinx_cache_limit', 5, False)
app.connect('missing-reference', missing_reference)
app.connect('builder-inited', load_mappings)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py
index 8907576f..9bf38f62 100644
--- a/sphinx/ext/jsmath.py
+++ b/sphinx/ext/jsmath.py
@@ -12,6 +12,7 @@
from docutils import nodes
+import sphinx
from sphinx.application import ExtensionError
from sphinx.ext.mathbase import setup_math as mathbase_setup
@@ -56,3 +57,4 @@ 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)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/linkcode.py b/sphinx/ext/linkcode.py
index 77bd9f28..37e021e8 100644
--- a/sphinx/ext/linkcode.py
+++ b/sphinx/ext/linkcode.py
@@ -11,13 +11,16 @@
from docutils import nodes
+import sphinx
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
@@ -67,6 +70,8 @@ def doctree_read(app, doctree):
classes=['viewcode-link'])
signode += onlynode
+
def setup(app):
app.connect('doctree-read', doctree_read)
app.add_config_value('linkcode_resolve', None, '')
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py
index ee278667..f677ff48 100644
--- a/sphinx/ext/mathjax.py
+++ b/sphinx/ext/mathjax.py
@@ -13,6 +13,7 @@
from docutils import nodes
+import sphinx
from sphinx.application import ExtensionError
from sphinx.ext.mathbase import setup_math as mathbase_setup
@@ -60,9 +61,12 @@ def builder_inited(app):
def setup(app):
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
+ # more information for mathjax secure url is here:
+ # http://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn
app.add_config_value('mathjax_path',
- 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?'
+ 'https://c328740.ssl.cf1.rackcdn.com/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)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py
new file mode 100644
index 00000000..9b43d8fd
--- /dev/null
+++ b/sphinx/ext/napoleon/__init__.py
@@ -0,0 +1,391 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.napoleon
+ ~~~~~~~~~~~~~~~~~~~
+
+ Support for NumPy and Google style docstrings.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+
+from six import PY2, iteritems
+
+import sphinx
+from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring
+
+
+class Config(object):
+ """Sphinx napoleon extension settings in `conf.py`.
+
+ Listed below are all the settings used by napoleon and their default
+ values. These settings can be changed in the Sphinx `conf.py` file. Make
+ sure that both "sphinx.ext.autodoc" and "sphinx.ext.napoleon" are
+ enabled in `conf.py`::
+
+ # conf.py
+
+ # Add any Sphinx extension module names here, as strings
+ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
+
+ # Napoleon settings
+ napoleon_google_docstring = True
+ napoleon_numpy_docstring = True
+ napoleon_include_private_with_doc = False
+ napoleon_include_special_with_doc = True
+ napoleon_use_admonition_for_examples = False
+ napoleon_use_admonition_for_notes = False
+ napoleon_use_admonition_for_references = False
+ napoleon_use_ivar = False
+ napoleon_use_param = True
+ napoleon_use_rtype = True
+
+ .. _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
+
+ Attributes
+ ----------
+ napoleon_google_docstring : bool, defaults to True
+ True to parse `Google style`_ docstrings. False to disable support
+ for Google style docstrings.
+ napoleon_numpy_docstring : bool, defaults to True
+ True to parse `NumPy style`_ docstrings. False to disable support
+ for NumPy style docstrings.
+ napoleon_include_private_with_doc : bool, defaults to False
+ True to include private members (like ``_membername``) with docstrings
+ in the documentation. False to fall back to Sphinx's default behavior.
+
+ **If True**::
+
+ def _included(self):
+ \"\"\"
+ This will be included in the docs because it has a docstring
+ \"\"\"
+ pass
+
+ def _skipped(self):
+ # This will NOT be included in the docs
+ pass
+
+ napoleon_include_special_with_doc : bool, defaults to True
+ True to include special members (like ``__membername__``) with
+ docstrings in the documentation. False to fall back to Sphinx's
+ default behavior.
+
+ **If True**::
+
+ def __str__(self):
+ \"\"\"
+ This will be included in the docs because it has a docstring
+ \"\"\"
+ return unicode(self).encode('utf-8')
+
+ def __unicode__(self):
+ # This will NOT be included in the docs
+ return unicode(self.__class__.__name__)
+
+ napoleon_use_admonition_for_examples : bool, defaults to False
+ True to use the ``.. admonition::`` directive for the **Example** and
+ **Examples** sections. False to use the ``.. rubric::`` directive
+ instead. One may look better than the other depending on what HTML
+ theme is used.
+
+ This `NumPy style`_ snippet will be converted as follows::
+
+ Example
+ -------
+ This is just a quick example
+
+ **If True**::
+
+ .. admonition:: Example
+
+ This is just a quick example
+
+ **If False**::
+
+ .. rubric:: Example
+
+ This is just a quick example
+
+ napoleon_use_admonition_for_notes : bool, defaults to False
+ True to use the ``.. admonition::`` directive for **Notes** sections.
+ False to use the ``.. rubric::`` directive instead.
+
+ Note
+ ----
+ The singular **Note** section will always be converted to a
+ ``.. note::`` directive.
+
+ See Also
+ --------
+ :attr:`napoleon_use_admonition_for_examples`
+
+ napoleon_use_admonition_for_references : bool, defaults to False
+ True to use the ``.. admonition::`` directive for **References**
+ sections. False to use the ``.. rubric::`` directive instead.
+
+ See Also
+ --------
+ :attr:`napoleon_use_admonition_for_examples`
+
+ napoleon_use_ivar : bool, defaults to False
+ True to use the ``:ivar:`` role for instance variables. False to use
+ the ``.. attribute::`` directive instead.
+
+ This `NumPy style`_ snippet will be converted as follows::
+
+ Attributes
+ ----------
+ attr1 : int
+ Description of `attr1`
+
+ **If True**::
+
+ :ivar attr1: Description of `attr1`
+ :vartype attr1: int
+
+ **If False**::
+
+ .. attribute:: attr1
+
+ *int*
+
+ Description of `attr1`
+
+ napoleon_use_param : bool, defaults to True
+ True to use a ``:param:`` role for each function parameter. False to
+ use a single ``:parameters:`` role for all the parameters.
+
+ This `NumPy style`_ snippet will be converted as follows::
+
+ Parameters
+ ----------
+ arg1 : str
+ Description of `arg1`
+ arg2 : int, optional
+ Description of `arg2`, defaults to 0
+
+ **If True**::
+
+ :param arg1: Description of `arg1`
+ :type arg1: str
+ :param arg2: Description of `arg2`, defaults to 0
+ :type arg2: int, optional
+
+ **If False**::
+
+ :parameters: * **arg1** (*str*) --
+ Description of `arg1`
+ * **arg2** (*int, optional*) --
+ Description of `arg2`, defaults to 0
+
+ napoleon_use_rtype : bool, defaults to True
+ True to use the ``:rtype:`` role for the return type. False to output
+ the return type inline with the description.
+
+ This `NumPy style`_ snippet will be converted as follows::
+
+ Returns
+ -------
+ bool
+ True if successful, False otherwise
+
+ **If True**::
+
+ :returns: True if successful, False otherwise
+ :rtype: bool
+
+ **If False**::
+
+ :returns: *bool* -- True if successful, False otherwise
+
+ """
+ _config_values = {
+ 'napoleon_google_docstring': (True, 'env'),
+ 'napoleon_numpy_docstring': (True, 'env'),
+ 'napoleon_include_private_with_doc': (False, 'env'),
+ 'napoleon_include_special_with_doc': (True, 'env'),
+ 'napoleon_use_admonition_for_examples': (False, 'env'),
+ 'napoleon_use_admonition_for_notes': (False, 'env'),
+ 'napoleon_use_admonition_for_references': (False, 'env'),
+ 'napoleon_use_ivar': (False, 'env'),
+ 'napoleon_use_param': (True, 'env'),
+ 'napoleon_use_rtype': (True, 'env'),
+ }
+
+ def __init__(self, **settings):
+ for name, (default, rebuild) in iteritems(self._config_values):
+ setattr(self, name, default)
+ for name, value in iteritems(settings):
+ setattr(self, name, value)
+
+
+def setup(app):
+ """Sphinx extension setup function.
+
+ When the extension is loaded, Sphinx imports this module and executes
+ the ``setup()`` function, which in turn notifies Sphinx of everything
+ the extension offers.
+
+ Parameters
+ ----------
+ app : sphinx.application.Sphinx
+ Application object representing the Sphinx process
+
+ See Also
+ --------
+ The Sphinx documentation on `Extensions`_, the `Extension Tutorial`_, and
+ the `Extension API`_.
+
+ .. _Extensions: http://sphinx-doc.org/extensions.html
+ .. _Extension Tutorial: http://sphinx-doc.org/ext/tutorial.html
+ .. _Extension API: http://sphinx-doc.org/ext/appapi.html
+
+ """
+ from sphinx.application import Sphinx
+ if not isinstance(app, Sphinx):
+ return # probably called by tests
+
+ app.connect('autodoc-process-docstring', _process_docstring)
+ app.connect('autodoc-skip-member', _skip_member)
+
+ for name, (default, rebuild) in iteritems(Config._config_values):
+ app.add_config_value(name, default, rebuild)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
+
+
+def _process_docstring(app, what, name, obj, options, lines):
+ """Process the docstring for a given python object.
+
+ Called when autodoc has read and processed a docstring. `lines` is a list
+ of docstring lines that `_process_docstring` modifies in place to change
+ what Sphinx outputs.
+
+ The following settings in conf.py control what styles of docstrings will
+ be parsed:
+
+ * ``napoleon_google_docstring`` -- parse Google style docstrings
+ * ``napoleon_numpy_docstring`` -- parse NumPy style docstrings
+
+ Parameters
+ ----------
+ app : sphinx.application.Sphinx
+ Application object representing the Sphinx process.
+ what : str
+ A string specifying the type of the object to which the docstring
+ belongs. Valid values: "module", "class", "exception", "function",
+ "method", "attribute".
+ name : str
+ The fully qualified name of the object.
+ obj : module, class, exception, function, method, or attribute
+ The object to which the docstring belongs.
+ options : sphinx.ext.autodoc.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.
+ lines : list of str
+ The lines of the docstring, see above.
+
+ .. note:: `lines` is modified *in place*
+
+ """
+ result_lines = lines
+ if app.config.napoleon_numpy_docstring:
+ docstring = NumpyDocstring(result_lines, app.config, app, what, name,
+ obj, options)
+ result_lines = docstring.lines()
+ if app.config.napoleon_google_docstring:
+ docstring = GoogleDocstring(result_lines, app.config, app, what, name,
+ obj, options)
+ result_lines = docstring.lines()
+ lines[:] = result_lines[:]
+
+
+def _skip_member(app, what, name, obj, skip, options):
+ """Determine if private and special class members are included in docs.
+
+ The following settings in conf.py determine if private and special class
+ members are included in the generated documentation:
+
+ * ``napoleon_include_private_with_doc`` --
+ include private members if they have docstrings
+ * ``napoleon_include_special_with_doc`` --
+ include special members if they have docstrings
+
+ Parameters
+ ----------
+ app : sphinx.application.Sphinx
+ Application object representing the Sphinx process
+ what : str
+ A string specifying the type of the object to which the member
+ belongs. Valid values: "module", "class", "exception", "function",
+ "method", "attribute".
+ name : str
+ The name of the member.
+ obj : module, class, exception, function, method, or attribute.
+ For example, if the member is the __init__ method of class A, then
+ `obj` will be `A.__init__`.
+ skip : bool
+ A boolean indicating if autodoc will skip this member if `_skip_member`
+ does not override the decision
+ options : sphinx.ext.autodoc.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.
+
+ Returns
+ -------
+ bool
+ True if the member should be skipped during creation of the docs,
+ False if it should be included in the docs.
+
+ """
+ has_doc = getattr(obj, '__doc__', False)
+ is_member = (what == 'class' or what == 'exception' or what == 'module')
+ if name != '__weakref__' and name != '__init__' and has_doc and is_member:
+ cls_is_owner = False
+ if what == 'class' or what == 'exception':
+ if PY2:
+ cls = getattr(obj, 'im_class', getattr(obj, '__objclass__',
+ None))
+ cls_is_owner = (cls and hasattr(cls, name) and
+ name in cls.__dict__)
+ elif sys.version_info >= (3, 3):
+ qualname = getattr(obj, '__qualname__', '')
+ cls_path, _, _ = qualname.rpartition('.')
+ if cls_path:
+ try:
+ if '.' in cls_path:
+ import importlib
+ import functools
+
+ mod = importlib.import_module(obj.__module__)
+ mod_path = cls_path.split('.')
+ cls = functools.reduce(getattr, mod_path, mod)
+ else:
+ cls = obj.__globals__[cls_path]
+ except:
+ cls_is_owner = False
+ else:
+ cls_is_owner = (cls and hasattr(cls, name) and
+ name in cls.__dict__)
+ else:
+ cls_is_owner = False
+ else:
+ cls_is_owner = True
+
+ if what == 'module' or cls_is_owner:
+ is_special = name.startswith('__') and name.endswith('__')
+ is_private = not is_special and name.startswith('_')
+ inc_special = app.config.napoleon_include_special_with_doc
+ inc_private = app.config.napoleon_include_private_with_doc
+ if (is_special and inc_special) or (is_private and inc_private):
+ return False
+ return skip
diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py
new file mode 100644
index 00000000..19f5f395
--- /dev/null
+++ b/sphinx/ext/napoleon/docstring.py
@@ -0,0 +1,860 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.napoleon.docstring
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+ Classes for docstring parsing and formatting.
+
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import collections
+import inspect
+import re
+
+from six import string_types
+from six.moves import range
+
+from sphinx.ext.napoleon.iterators import modify_iter
+from sphinx.util.pycompat import UnicodeMixin
+
+
+_directive_regex = re.compile(r'\.\. \S+::')
+_google_untyped_arg_regex = re.compile(r'\s*(\w+)\s*:\s*(.*)')
+_google_typed_arg_regex = re.compile(r'\s*(\w+)\s*\(\s*(.+?)\s*\)\s*:\s*(.*)')
+
+
+class GoogleDocstring(UnicodeMixin):
+ """Parse Google style docstrings.
+
+ Convert Google style docstrings to reStructuredText.
+
+ Parameters
+ ----------
+ docstring : str or list of str
+ The docstring to parse, given either as a string or split into
+ individual lines.
+ config : sphinx.ext.napoleon.Config or sphinx.config.Config, optional
+ The configuration settings to use. If not given, defaults to the
+ config object on `app`; or if `app` is not given defaults to the
+ a new `sphinx.ext.napoleon.Config` object.
+
+ See Also
+ --------
+ :class:`sphinx.ext.napoleon.Config`
+
+ Other Parameters
+ ----------------
+ app : sphinx.application.Sphinx, optional
+ Application object representing the Sphinx process.
+ what : str, optional
+ A string specifying the type of the object to which the docstring
+ belongs. Valid values: "module", "class", "exception", "function",
+ "method", "attribute".
+ name : str, optional
+ The fully qualified name of the object.
+ obj : module, class, exception, function, method, or attribute
+ The object to which the docstring belongs.
+ options : sphinx.ext.autodoc.Options, optional
+ 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.
+
+ Example
+ -------
+ >>> from sphinx.ext.napoleon import Config
+ >>> config = Config(napoleon_use_param=True, napoleon_use_rtype=True)
+ >>> docstring = '''One line summary.
+ ...
+ ... Extended description.
+ ...
+ ... Args:
+ ... arg1(int): Description of `arg1`
+ ... arg2(str): Description of `arg2`
+ ... Returns:
+ ... str: Description of return value.
+ ... '''
+ >>> print(GoogleDocstring(docstring, config))
+ One line summary.
+ <BLANKLINE>
+ Extended description.
+ <BLANKLINE>
+ :param arg1: Description of `arg1`
+ :type arg1: int
+ :param arg2: Description of `arg2`
+ :type arg2: str
+ <BLANKLINE>
+ :returns: Description of return value.
+ :rtype: str
+
+ """
+ def __init__(self, docstring, config=None, app=None, what='', name='',
+ obj=None, options=None):
+ self._config = config
+ self._app = app
+
+ if not self._config:
+ from sphinx.ext.napoleon import Config
+ self._config = self._app and self._app.config or Config()
+
+ if not what:
+ if inspect.isclass(obj):
+ what = 'class'
+ elif inspect.ismodule(obj):
+ what = 'module'
+ elif isinstance(obj, collections.Callable):
+ what = 'function'
+ else:
+ what = 'object'
+
+ self._what = what
+ self._name = name
+ self._obj = obj
+ self._opt = options
+ if isinstance(docstring, string_types):
+ docstring = docstring.splitlines()
+ self._lines = docstring
+ self._line_iter = modify_iter(docstring, modifier=lambda s: s.rstrip())
+ self._parsed_lines = []
+ self._is_in_section = False
+ self._section_indent = 0
+ if not hasattr(self, '_directive_sections'):
+ self._directive_sections = []
+ if not hasattr(self, '_sections'):
+ self._sections = {
+ 'args': self._parse_parameters_section,
+ 'arguments': self._parse_parameters_section,
+ 'attributes': self._parse_attributes_section,
+ 'example': self._parse_examples_section,
+ 'examples': self._parse_examples_section,
+ 'keyword args': self._parse_keyword_arguments_section,
+ 'keyword arguments': self._parse_keyword_arguments_section,
+ 'methods': self._parse_methods_section,
+ 'note': self._parse_note_section,
+ 'notes': self._parse_notes_section,
+ 'other parameters': self._parse_other_parameters_section,
+ 'parameters': self._parse_parameters_section,
+ 'return': self._parse_returns_section,
+ 'returns': self._parse_returns_section,
+ 'raises': self._parse_raises_section,
+ 'references': self._parse_references_section,
+ 'see also': self._parse_see_also_section,
+ 'warning': self._parse_warning_section,
+ 'warnings': self._parse_warning_section,
+ 'warns': self._parse_warns_section,
+ 'yields': self._parse_yields_section,
+ }
+ self._parse()
+
+ def __unicode__(self):
+ """Return the parsed docstring in reStructuredText format.
+
+ Returns
+ -------
+ unicode
+ Unicode version of the docstring.
+
+ """
+ return u'\n'.join(self.lines())
+
+ def lines(self):
+ """Return the parsed lines of the docstring in reStructuredText format.
+
+ Returns
+ -------
+ list of str
+ The lines of the docstring in a list.
+
+ """
+ return self._parsed_lines
+
+ def _consume_indented_block(self, indent=1):
+ lines = []
+ line = self._line_iter.peek()
+ while(not self._is_section_break()
+ and (not line or self._is_indented(line, indent))):
+ lines.append(next(self._line_iter))
+ line = self._line_iter.peek()
+ return lines
+
+ def _consume_contiguous(self):
+ lines = []
+ while (self._line_iter.has_next()
+ and self._line_iter.peek()
+ and not self._is_section_header()):
+ lines.append(next(self._line_iter))
+ return lines
+
+ def _consume_empty(self):
+ lines = []
+ line = self._line_iter.peek()
+ while self._line_iter.has_next() and not line:
+ lines.append(next(self._line_iter))
+ line = self._line_iter.peek()
+ return lines
+
+ def _consume_field(self, parse_type=True, prefer_type=False):
+ line = next(self._line_iter)
+
+ match = None
+ _name, _type, _desc = line.strip(), '', ''
+ if parse_type:
+ match = _google_typed_arg_regex.match(line)
+ if match:
+ _name = match.group(1)
+ _type = match.group(2)
+ _desc = match.group(3)
+
+ if not match:
+ match = _google_untyped_arg_regex.match(line)
+ if match:
+ _name = match.group(1)
+ _desc = match.group(2)
+
+ if prefer_type and not _type:
+ _type, _name = _name, _type
+ indent = self._get_indent(line) + 1
+ _desc = [_desc] + self._dedent(self._consume_indented_block(indent))
+ _desc = self.__class__(_desc, self._config).lines()
+ return _name, _type, _desc
+
+ def _consume_fields(self, parse_type=True, prefer_type=False):
+ self._consume_empty()
+ fields = []
+ while not self._is_section_break():
+ _name, _type, _desc = self._consume_field(parse_type, prefer_type)
+ if _name or _type or _desc:
+ fields.append((_name, _type, _desc,))
+ return fields
+
+ def _consume_returns_section(self):
+ lines = self._dedent(self._consume_to_next_section())
+ if lines:
+ _name, _type, _desc = '', '', lines
+ match = _google_typed_arg_regex.match(lines[0])
+ if match:
+ _name = match.group(1)
+ _type = match.group(2)
+ _desc = match.group(3)
+ else:
+ match = _google_untyped_arg_regex.match(lines[0])
+ if match:
+ _type = match.group(1)
+ _desc = match.group(2)
+ if match:
+ lines[0] = _desc
+ _desc = lines
+
+ _desc = self.__class__(_desc, self._config).lines()
+ return [(_name, _type, _desc,)]
+ else:
+ return []
+
+ def _consume_section_header(self):
+ section = next(self._line_iter)
+ stripped_section = section.strip(':')
+ if stripped_section.lower() in self._sections:
+ section = stripped_section
+ return section
+
+ def _consume_to_next_section(self):
+ self._consume_empty()
+ lines = []
+ while not self._is_section_break():
+ lines.append(next(self._line_iter))
+ return lines + self._consume_empty()
+
+ def _dedent(self, lines, full=False):
+ if full:
+ return [line.lstrip() for line in lines]
+ else:
+ min_indent = self._get_min_indent(lines)
+ return [line[min_indent:] for line in lines]
+
+ def _format_admonition(self, admonition, lines):
+ lines = self._strip_empty(lines)
+ if len(lines) == 1:
+ return ['.. %s:: %s' % (admonition, lines[0].strip()), '']
+ elif lines:
+ lines = self._indent(self._dedent(lines), 3)
+ return ['.. %s::' % admonition, ''] + lines + ['']
+ else:
+ return ['.. %s::' % admonition, '']
+
+ def _format_block(self, prefix, lines, padding=None):
+ if lines:
+ if padding is None:
+ padding = ' ' * len(prefix)
+ result_lines = []
+ for i, line in enumerate(lines):
+ if line:
+ if i == 0:
+ result_lines.append(prefix + line)
+ else:
+ result_lines.append(padding + line)
+ else:
+ result_lines.append('')
+ return result_lines
+ else:
+ return [prefix]
+
+ def _format_field(self, _name, _type, _desc):
+ separator = any([s for s in _desc]) and ' --' or ''
+ if _name:
+ if _type:
+ if '`' in _type:
+ field = ['**%s** (%s)%s' % (_name, _type, separator)]
+ else:
+ field = ['**%s** (*%s*)%s' % (_name, _type, separator)]
+ else:
+ field = ['**%s**%s' % (_name, separator)]
+ elif _type:
+ if '`' in _type:
+ field = ['%s%s' % (_type, separator)]
+ else:
+ field = ['*%s*%s' % (_type, separator)]
+ else:
+ field = []
+ return field + _desc
+
+ def _format_fields(self, field_type, fields):
+ field_type = ':%s:' % field_type.strip()
+ padding = ' ' * len(field_type)
+ multi = len(fields) > 1
+ lines = []
+ for _name, _type, _desc in fields:
+ field = self._format_field(_name, _type, _desc)
+ if multi:
+ if lines:
+ lines.extend(self._format_block(padding + ' * ', field))
+ else:
+ lines.extend(self._format_block(field_type + ' * ', field))
+ else:
+ lines.extend(self._format_block(field_type + ' ', field))
+ return lines
+
+ def _get_current_indent(self, peek_ahead=0):
+ line = self._line_iter.peek(peek_ahead + 1)[peek_ahead]
+ while line != self._line_iter.sentinel:
+ if line:
+ return self._get_indent(line)
+ peek_ahead += 1
+ line = self._line_iter.peek(peek_ahead + 1)[peek_ahead]
+ return 0
+
+ def _get_indent(self, line):
+ for i, s in enumerate(line):
+ if not s.isspace():
+ return i
+ return len(line)
+
+ def _get_min_indent(self, lines):
+ min_indent = None
+ for line in lines:
+ if line:
+ indent = self._get_indent(line)
+ if min_indent is None:
+ min_indent = indent
+ elif indent < min_indent:
+ min_indent = indent
+ return min_indent or 0
+
+ def _indent(self, lines, n=4):
+ return [(' ' * n) + line for line in lines]
+
+ def _is_indented(self, line, indent=1):
+ for i, s in enumerate(line):
+ if i >= indent:
+ return True
+ elif not s.isspace():
+ return False
+ return False
+
+ def _is_section_header(self):
+ section = self._line_iter.peek().lower()
+ if section.strip(':') in self._sections:
+ header_indent = self._get_indent(section)
+ section_indent = self._get_current_indent(peek_ahead=1)
+ return section_indent > header_indent
+ elif self._directive_sections:
+ if _directive_regex.match(section):
+ for directive_section in self._directive_sections:
+ if section.startswith(directive_section):
+ return True
+ return False
+
+ def _is_section_break(self):
+ line = self._line_iter.peek()
+ return (not self._line_iter.has_next()
+ or self._is_section_header()
+ or (self._is_in_section
+ and line
+ and not self._is_indented(line, self._section_indent)))
+
+ def _parse(self):
+ self._parsed_lines = self._consume_empty()
+ while self._line_iter.has_next():
+ if self._is_section_header():
+ try:
+ section = self._consume_section_header()
+ self._is_in_section = True
+ self._section_indent = self._get_current_indent()
+ if _directive_regex.match(section):
+ lines = [section] + self._consume_to_next_section()
+ else:
+ lines = self._sections[section.lower()](section)
+ finally:
+ self._is_in_section = False
+ self._section_indent = 0
+ else:
+ if not self._parsed_lines:
+ lines = self._consume_contiguous() + self._consume_empty()
+ else:
+ lines = self._consume_to_next_section()
+ self._parsed_lines.extend(lines)
+
+ def _parse_attributes_section(self, section):
+ lines = []
+ for _name, _type, _desc in self._consume_fields():
+ if self._config.napoleon_use_ivar:
+ field = ':ivar %s: ' % _name
+ lines.extend(self._format_block(field, _desc))
+ if _type:
+ lines.append(':vartype %s: %s' % (_name, _type))
+ else:
+ lines.append('.. attribute:: ' + _name)
+ if _type:
+ lines.append('')
+ if '`' in _type:
+ lines.append(' %s' % _type)
+ else:
+ lines.append(' *%s*' % _type)
+ if _desc:
+ lines.extend([''] + self._indent(_desc, 3))
+ lines.append('')
+ if self._config.napoleon_use_ivar:
+ lines.append('')
+ return lines
+
+ def _parse_examples_section(self, section):
+ use_admonition = self._config.napoleon_use_admonition_for_examples
+ return self._parse_generic_section(section, use_admonition)
+
+ def _parse_generic_section(self, section, use_admonition):
+ lines = self._strip_empty(self._consume_to_next_section())
+ lines = self._dedent(lines)
+ if use_admonition:
+ header = '.. admonition:: %s' % section
+ lines = self._indent(lines, 3)
+ else:
+ header = '.. rubric:: %s' % section
+ if lines:
+ return [header, ''] + lines + ['']
+ else:
+ return [header, '']
+
+ def _parse_keyword_arguments_section(self, section):
+ return self._format_fields('Keyword Arguments', self._consume_fields())
+
+ def _parse_methods_section(self, section):
+ lines = []
+ for _name, _, _desc in self._consume_fields(parse_type=False):
+ lines.append('.. method:: %s' % _name)
+ if _desc:
+ lines.extend([''] + self._indent(_desc, 3))
+ lines.append('')
+ return lines
+
+ def _parse_note_section(self, section):
+ lines = self._consume_to_next_section()
+ return self._format_admonition('note', lines)
+
+ def _parse_notes_section(self, section):
+ use_admonition = self._config.napoleon_use_admonition_for_notes
+ return self._parse_generic_section('Notes', use_admonition)
+
+ def _parse_other_parameters_section(self, section):
+ return self._format_fields('Other Parameters', self._consume_fields())
+
+ def _parse_parameters_section(self, section):
+ fields = self._consume_fields()
+ if self._config.napoleon_use_param:
+ lines = []
+ for _name, _type, _desc in fields:
+ field = ':param %s: ' % _name
+ lines.extend(self._format_block(field, _desc))
+ if _type:
+ lines.append(':type %s: %s' % (_name, _type))
+ return lines + ['']
+ else:
+ return self._format_fields('Parameters', fields)
+
+ def _parse_raises_section(self, section):
+ fields = self._consume_fields()
+ field_type = ':raises:'
+ padding = ' ' * len(field_type)
+ multi = len(fields) > 1
+ lines = []
+ for _name, _type, _desc in fields:
+ sep = _desc and ' -- ' or ''
+ if _name:
+ if ' ' in _name:
+ _name = '**%s**' % _name
+ else:
+ _name = ':exc:`%s`' % _name
+ if _type:
+ if '`' in _type:
+ field = ['%s (%s)%s' % (_name, _type, sep)]
+ else:
+ field = ['%s (*%s*)%s' % (_name, _type, sep)]
+ else:
+ field = ['%s%s' % (_name, sep)]
+ elif _type:
+ if '`' in _type:
+ field = ['%s%s' % (_type, sep)]
+ else:
+ field = ['*%s*%s' % (_type, sep)]
+ else:
+ field = []
+ field = field + _desc
+ if multi:
+ if lines:
+ lines.extend(self._format_block(padding + ' * ', field))
+ else:
+ lines.extend(self._format_block(field_type + ' * ', field))
+ else:
+ lines.extend(self._format_block(field_type + ' ', field))
+ return lines
+
+ def _parse_references_section(self, section):
+ use_admonition = self._config.napoleon_use_admonition_for_references
+ return self._parse_generic_section('References', use_admonition)
+
+ def _parse_returns_section(self, section):
+ fields = self._consume_returns_section()
+ multi = len(fields) > 1
+ if multi:
+ use_rtype = False
+ else:
+ use_rtype = self._config.napoleon_use_rtype
+
+ lines = []
+ for _name, _type, _desc in fields:
+ if use_rtype:
+ field = self._format_field(_name, '', _desc)
+ else:
+ field = self._format_field(_name, _type, _desc)
+
+ if multi:
+ if lines:
+ lines.extend(self._format_block(' * ', field))
+ else:
+ lines.extend(self._format_block(':returns: * ', field))
+ else:
+ lines.extend(self._format_block(':returns: ', field))
+ if _type and use_rtype:
+ lines.append(':rtype: %s' % _type)
+ lines.append('')
+ return lines
+
+ def _parse_see_also_section(self, section):
+ lines = self._consume_to_next_section()
+ return self._format_admonition('seealso', lines)
+
+ def _parse_warning_section(self, section):
+ lines = self._consume_to_next_section()
+ return self._format_admonition('warning', lines)
+
+ def _parse_warns_section(self, section):
+ return self._format_fields('Warns', self._consume_fields())
+
+ def _parse_yields_section(self, section):
+ fields = self._consume_fields(prefer_type=True)
+ return self._format_fields('Yields', fields)
+
+ def _strip_empty(self, lines):
+ if lines:
+ start = -1
+ for i, line in enumerate(lines):
+ if line:
+ start = i
+ break
+ if start == -1:
+ lines = []
+ end = -1
+ for i in reversed(range(len(lines))):
+ line = lines[i]
+ if line:
+ end = i
+ break
+ if start > 0 or end + 1 < len(lines):
+ lines = lines[start:end + 1]
+ return lines
+
+
+class NumpyDocstring(GoogleDocstring):
+ """Parse NumPy style docstrings.
+
+ Convert NumPy style docstrings to reStructuredText.
+
+ Parameters
+ ----------
+ docstring : str or list of str
+ The docstring to parse, given either as a string or split into
+ individual lines.
+ config : sphinx.ext.napoleon.Config or sphinx.config.Config, optional
+ The configuration settings to use. If not given, defaults to the
+ config object on `app`; or if `app` is not given defaults to the
+ a new `sphinx.ext.napoleon.Config` object.
+
+ See Also
+ --------
+ :class:`sphinx.ext.napoleon.Config`
+
+ Other Parameters
+ ----------------
+ app : sphinx.application.Sphinx, optional
+ Application object representing the Sphinx process.
+ what : str, optional
+ A string specifying the type of the object to which the docstring
+ belongs. Valid values: "module", "class", "exception", "function",
+ "method", "attribute".
+ name : str, optional
+ The fully qualified name of the object.
+ obj : module, class, exception, function, method, or attribute
+ The object to which the docstring belongs.
+ options : sphinx.ext.autodoc.Options, optional
+ 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.
+
+ Example
+ -------
+ >>> from sphinx.ext.napoleon import Config
+ >>> config = Config(napoleon_use_param=True, napoleon_use_rtype=True)
+ >>> docstring = '''One line summary.
+ ...
+ ... Extended description.
+ ...
+ ... Parameters
+ ... ----------
+ ... arg1 : int
+ ... Description of `arg1`
+ ... arg2 : str
+ ... Description of `arg2`
+ ... Returns
+ ... -------
+ ... str
+ ... Description of return value.
+ ... '''
+ >>> print(NumpyDocstring(docstring, config))
+ One line summary.
+ <BLANKLINE>
+ Extended description.
+ <BLANKLINE>
+ :param arg1: Description of `arg1`
+ :type arg1: int
+ :param arg2: Description of `arg2`
+ :type arg2: str
+ <BLANKLINE>
+ :returns: Description of return value.
+ :rtype: str
+
+ Methods
+ -------
+ __str__()
+ Return the parsed docstring in reStructuredText format.
+
+ Returns
+ -------
+ str
+ UTF-8 encoded version of the docstring.
+
+ __unicode__()
+ Return the parsed docstring in reStructuredText format.
+
+ Returns
+ -------
+ unicode
+ Unicode version of the docstring.
+
+ lines()
+ Return the parsed lines of the docstring in reStructuredText format.
+
+ Returns
+ -------
+ list of str
+ The lines of the docstring in a list.
+
+ """
+ def __init__(self, docstring, config=None, app=None, what='', name='',
+ obj=None, options=None):
+ self._directive_sections = ['.. index::']
+ super(NumpyDocstring, self).__init__(docstring, config, app, what,
+ name, obj, options)
+
+ def _consume_field(self, parse_type=True, prefer_type=False):
+ line = next(self._line_iter)
+ if parse_type:
+ _name, _, _type = line.partition(':')
+ else:
+ _name, _type = line, ''
+ _name, _type = _name.strip(), _type.strip()
+ if prefer_type and not _type:
+ _type, _name = _name, _type
+ indent = self._get_indent(line)
+ _desc = self._dedent(self._consume_indented_block(indent + 1))
+ _desc = self.__class__(_desc, self._config).lines()
+ return _name, _type, _desc
+
+ def _consume_returns_section(self):
+ return self._consume_fields(prefer_type=True)
+
+ def _consume_section_header(self):
+ section = next(self._line_iter)
+ if not _directive_regex.match(section):
+ # Consume the header underline
+ next(self._line_iter)
+ return section
+
+ def _is_section_break(self):
+ line1, line2 = self._line_iter.peek(2)
+ return (not self._line_iter.has_next()
+ or self._is_section_header()
+ or ['', ''] == [line1, line2]
+ or (self._is_in_section
+ and line1
+ and not self._is_indented(line1, self._section_indent)))
+
+ def _is_section_header(self):
+ section, underline = self._line_iter.peek(2)
+ section = section.lower()
+ if section in self._sections and isinstance(underline, string_types):
+ pattern = r'[=\-`:\'"~^_*+#<>]{' + str(len(section)) + r'}$'
+ return bool(re.match(pattern, underline))
+ elif self._directive_sections:
+ if _directive_regex.match(section):
+ for directive_section in self._directive_sections:
+ if section.startswith(directive_section):
+ return True
+ return False
+
+ _name_rgx = re.compile(r"^\s*(:(?P<role>\w+):`(?P<name>[a-zA-Z0-9_.-]+)`|"
+ r" (?P<name2>[a-zA-Z0-9_.-]+))\s*", re.X)
+
+ def _parse_see_also_section(self, section):
+ lines = self._consume_to_next_section()
+ try:
+ return self._parse_numpydoc_see_also_section(lines)
+ except ValueError:
+ return self._format_admonition('seealso', lines)
+
+ def _parse_numpydoc_see_also_section(self, content):
+ """
+ Derived from the NumpyDoc implementation of _parse_see_also.
+
+ func_name : Descriptive text
+ continued text
+ another_func_name : Descriptive text
+ func_name1, func_name2, :meth:`func_name`, func_name3
+
+ """
+ items = []
+
+ def parse_item_name(text):
+ """Match ':role:`name`' or 'name'"""
+ m = self._name_rgx.match(text)
+ if m:
+ g = m.groups()
+ if g[1] is None:
+ return g[3], None
+ else:
+ return g[2], g[1]
+ raise ValueError("%s is not a item name" % text)
+
+ def push_item(name, rest):
+ if not name:
+ return
+ name, role = parse_item_name(name)
+ items.append((name, list(rest), role))
+ del rest[:]
+
+ current_func = None
+ rest = []
+
+ for line in content:
+ if not line.strip():
+ continue
+
+ m = self._name_rgx.match(line)
+ if m and line[m.end():].strip().startswith(':'):
+ push_item(current_func, rest)
+ current_func, line = line[:m.end()], line[m.end():]
+ rest = [line.split(':', 1)[1].strip()]
+ if not rest[0]:
+ rest = []
+ elif not line.startswith(' '):
+ push_item(current_func, rest)
+ current_func = None
+ if ',' in line:
+ for func in line.split(','):
+ if func.strip():
+ push_item(func, [])
+ elif line.strip():
+ current_func = line
+ elif current_func is not None:
+ rest.append(line.strip())
+ push_item(current_func, rest)
+
+ if not items:
+ return []
+
+ roles = {
+ 'method': 'meth',
+ 'meth': 'meth',
+ 'function': 'func',
+ 'func': 'func',
+ 'class': 'class',
+ 'exception': 'exc',
+ 'exc': 'exc',
+ 'object': 'obj',
+ 'obj': 'obj',
+ 'module': 'mod',
+ 'mod': 'mod',
+ 'data': 'data',
+ 'constant': 'const',
+ 'const': 'const',
+ 'attribute': 'attr',
+ 'attr': 'attr'
+ }
+ if self._what is None:
+ func_role = 'obj'
+ else:
+ func_role = roles.get(self._what, '')
+ lines = []
+ last_had_desc = True
+ for func, desc, role in items:
+ if role:
+ link = ':%s:`%s`' % (role, func)
+ elif func_role:
+ link = ':%s:`%s`' % (func_role, func)
+ else:
+ link = "`%s`_" % func
+ if desc or last_had_desc:
+ lines += ['']
+ lines += [link]
+ else:
+ lines[-1] += ", %s" % link
+ if desc:
+ lines += self._indent([' '.join(desc)])
+ last_had_desc = True
+ else:
+ last_had_desc = False
+ lines += ['']
+
+ return self._format_admonition('seealso', lines)
diff --git a/sphinx/ext/napoleon/iterators.py b/sphinx/ext/napoleon/iterators.py
new file mode 100644
index 00000000..482fe1dd
--- /dev/null
+++ b/sphinx/ext/napoleon/iterators.py
@@ -0,0 +1,239 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.ext.napoleon.iterators
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+ A collection of helpful iterators.
+
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import collections
+
+
+class peek_iter(object):
+ """An iterator object that supports peeking ahead.
+
+ Parameters
+ ----------
+ o : iterable or callable
+ `o` is interpreted very differently depending on the presence of
+ `sentinel`.
+
+ If `sentinel` is not given, then `o` must be a collection object
+ which supports either the iteration protocol or the sequence protocol.
+
+ If `sentinel` is given, then `o` must be a callable object.
+
+ sentinel : any value, optional
+ If given, the iterator will call `o` with no arguments for each
+ call to its `next` method; if the value returned is equal to
+ `sentinel`, :exc:`StopIteration` will be raised, otherwise the
+ value will be returned.
+
+ See Also
+ --------
+ `peek_iter` can operate as a drop in replacement for the built-in
+ `iter <http://docs.python.org/2/library/functions.html#iter>`_ function.
+
+ Attributes
+ ----------
+ sentinel
+ The value used to indicate the iterator is exhausted. If `sentinel`
+ was not given when the `peek_iter` was instantiated, then it will
+ be set to a new object instance: ``object()``.
+
+ """
+ def __init__(self, *args):
+ """__init__(o, sentinel=None)"""
+ self._iterable = iter(*args)
+ self._cache = collections.deque()
+ if len(args) == 2:
+ self.sentinel = args[1]
+ else:
+ self.sentinel = object()
+
+ def __iter__(self):
+ return self
+
+ def __next__(self, n=None):
+ # note: prevent 2to3 to transform self.next() in next(self) which
+ # causes an infinite loop !
+ return getattr(self, 'next')(n)
+
+ def _fillcache(self, n):
+ """Cache `n` items. If `n` is 0 or None, then 1 item is cached."""
+ if not n:
+ n = 1
+ try:
+ while len(self._cache) < n:
+ self._cache.append(next(self._iterable))
+ except StopIteration:
+ while len(self._cache) < n:
+ self._cache.append(self.sentinel)
+
+ def has_next(self):
+ """Determine if iterator is exhausted.
+
+ Returns
+ -------
+ bool
+ True if iterator has more items, False otherwise.
+
+ Note
+ ----
+ Will never raise :exc:`StopIteration`.
+
+ """
+ return self.peek() != self.sentinel
+
+ def next(self, n=None):
+ """Get the next item or `n` items of the iterator.
+
+ Parameters
+ ----------
+ n : int or None
+ The number of items to retrieve. Defaults to None.
+
+ Returns
+ -------
+ item or list of items
+ The next item or `n` items of the iterator. If `n` is None, the
+ item itself is returned. If `n` is an int, the items will be
+ returned in a list. If `n` is 0, an empty list is returned.
+
+ Raises
+ ------
+ StopIteration
+ Raised if the iterator is exhausted, even if `n` is 0.
+
+ """
+ self._fillcache(n)
+ if not n:
+ if self._cache[0] == self.sentinel:
+ raise StopIteration
+ if n is None:
+ result = self._cache.popleft()
+ else:
+ result = []
+ else:
+ if self._cache[n - 1] == self.sentinel:
+ raise StopIteration
+ result = [self._cache.popleft() for i in range(n)]
+ return result
+
+ def peek(self, n=None):
+ """Preview the next item or `n` items of the iterator.
+
+ The iterator is not advanced when peek is called.
+
+ Returns
+ -------
+ item or list of items
+ The next item or `n` items of the iterator. If `n` is None, the
+ item itself is returned. If `n` is an int, the items will be
+ returned in a list. If `n` is 0, an empty list is returned.
+
+ If the iterator is exhausted, `peek_iter.sentinel` is returned,
+ or placed as the last item in the returned list.
+
+ Note
+ ----
+ Will never raise :exc:`StopIteration`.
+
+ """
+ self._fillcache(n)
+ if n is None:
+ result = self._cache[0]
+ else:
+ result = [self._cache[i] for i in range(n)]
+ return result
+
+
+class modify_iter(peek_iter):
+ """An iterator object that supports modifying items as they are returned.
+
+ Parameters
+ ----------
+ o : iterable or callable
+ `o` is interpreted very differently depending on the presence of
+ `sentinel`.
+
+ If `sentinel` is not given, then `o` must be a collection object
+ which supports either the iteration protocol or the sequence protocol.
+
+ If `sentinel` is given, then `o` must be a callable object.
+
+ sentinel : any value, optional
+ If given, the iterator will call `o` with no arguments for each
+ call to its `next` method; if the value returned is equal to
+ `sentinel`, :exc:`StopIteration` will be raised, otherwise the
+ value will be returned.
+
+ modifier : callable, optional
+ The function that will be used to modify each item returned by the
+ iterator. `modifier` should take a single argument and return a
+ single value. Defaults to ``lambda x: x``.
+
+ If `sentinel` is not given, `modifier` must be passed as a keyword
+ argument.
+
+ Attributes
+ ----------
+ modifier : callable
+ `modifier` is called with each item in `o` as it is iterated. The
+ return value of `modifier` is returned in lieu of the item.
+
+ Values returned by `peek` as well as `next` are affected by
+ `modifier`. However, `modify_iter.sentinel` is never passed through
+ `modifier`; it will always be returned from `peek` unmodified.
+
+ Example
+ -------
+ >>> a = [" A list ",
+ ... " of strings ",
+ ... " with ",
+ ... " extra ",
+ ... " whitespace. "]
+ >>> modifier = lambda s: s.strip().replace('with', 'without')
+ >>> for s in modify_iter(a, modifier=modifier):
+ ... print('"%s"' % s)
+ "A list"
+ "of strings"
+ "without"
+ "extra"
+ "whitespace."
+
+ """
+ def __init__(self, *args, **kwargs):
+ """__init__(o, sentinel=None, modifier=lambda x: x)"""
+ if 'modifier' in kwargs:
+ self.modifier = kwargs['modifier']
+ elif len(args) > 2:
+ self.modifier = args[2]
+ args = args[:2]
+ else:
+ self.modifier = lambda x: x
+ if not callable(self.modifier):
+ raise TypeError('modify_iter(o, modifier): '
+ 'modifier must be callable')
+ super(modify_iter, self).__init__(*args)
+
+ def _fillcache(self, n):
+ """Cache `n` modified items. If `n` is 0 or None, 1 item is cached.
+
+ Each item returned by the iterator is passed through the
+ `modify_iter.modified` function before being cached.
+
+ """
+ if not n:
+ n = 1
+ try:
+ while len(self._cache) < n:
+ self._cache.append(self.modifier(next(self._iterable)))
+ except StopIteration:
+ while len(self._cache) < n:
+ self._cache.append(self.sentinel)
diff --git a/sphinx/ext/oldcmarkup.py b/sphinx/ext/oldcmarkup.py
deleted file mode 100644
index aa10246b..00000000
--- a/sphinx/ext/oldcmarkup.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# -*- 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
index abac15cd..81a6f9d5 100644
--- a/sphinx/ext/pngmath.py
+++ b/sphinx/ext/pngmath.py
@@ -8,7 +8,6 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-from __future__ import with_statement
import re
import codecs
@@ -17,17 +16,16 @@ import tempfile
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 hashlib import sha1
+from six import text_type
from docutils import nodes
+import sphinx
from sphinx.errors import SphinxError
from sphinx.util.png import read_png_depth, write_png_depth
from sphinx.util.osutil import ensuredir, ENOENT, cd
-from sphinx.util.pycompat import b, sys_encoding
+from sphinx.util.pycompat import sys_encoding
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
class MathExtError(SphinxError):
@@ -67,7 +65,7 @@ DOC_BODY_PREVIEW = r'''
\end{document}
'''
-depth_re = re.compile(b(r'\[\d+ depth=(-?\d+)\]'))
+depth_re = re.compile(br'\[\d+ depth=(-?\d+)\]')
def render_math(self, math):
"""Render the LaTeX math expression *math* using latex and dvipng.
@@ -86,9 +84,9 @@ def render_math(self, math):
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()
+ shasum = "%s.png" % sha1(latex.encode('utf-8')).hexdigest()
relfn = posixpath.join(self.builder.imgpath, 'math', shasum)
- outfn = path.join(self.builder.outdir, '_images', 'math', shasum)
+ outfn = path.join(self.builder.outdir, self.builder.imagedir, 'math', shasum)
if path.isfile(outfn):
depth = read_png_depth(outfn)
return relfn, depth
@@ -121,7 +119,7 @@ def render_math(self, math):
with cd(tempdir):
try:
p = Popen(ltx_args, stdout=PIPE, stderr=PIPE)
- except OSError, err:
+ except OSError as err:
if err.errno != ENOENT: # No such file or directory
raise
self.builder.warn('LaTeX command %r cannot be run (needed for math '
@@ -146,7 +144,7 @@ def render_math(self, math):
dvipng_args.append(path.join(tempdir, 'math.dvi'))
try:
p = Popen(dvipng_args, stdout=PIPE, stderr=PIPE)
- except OSError, err:
+ except OSError as err:
if err.errno != ENOENT: # No such file or directory
raise
self.builder.warn('dvipng command %r cannot be run (needed for math '
@@ -186,8 +184,8 @@ def get_tooltip(self, node):
def html_visit_math(self, node):
try:
fname, depth = render_math(self, '$'+node['latex']+'$')
- except MathExtError, exc:
- msg = unicode(exc)
+ except MathExtError as exc:
+ msg = text_type(exc)
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
@@ -211,7 +209,7 @@ def html_visit_displaymath(self, node):
latex = wrap_displaymath(node['latex'], None)
try:
fname, depth = render_math(self, latex)
- except MathExtError, exc:
+ except MathExtError as exc:
sm = nodes.system_message(str(exc), type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
@@ -243,3 +241,4 @@ def setup(app):
app.add_config_value('pngmath_latex_preamble', '', 'html')
app.add_config_value('pngmath_add_tooltips', True, 'html')
app.connect('build-finished', cleanup_tempdir)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py
index 9f521fb4..ae434dd4 100644
--- a/sphinx/ext/todo.py
+++ b/sphinx/ext/todo.py
@@ -14,6 +14,7 @@
from docutils import nodes
+import sphinx
from sphinx.locale import _
from sphinx.environment import NoUri
from sphinx.util.nodes import set_source_info
@@ -149,6 +150,14 @@ def purge_todos(app, env, docname):
if todo['docname'] != docname]
+def merge_info(app, env, docnames, other):
+ if not hasattr(other, 'todo_all_todos'):
+ return
+ if not hasattr(env, 'todo_all_todos'):
+ env.todo_all_todos = []
+ env.todo_all_todos.extend(other.todo_all_todos)
+
+
def visit_todo_node(self, node):
self.visit_admonition(node)
@@ -171,4 +180,5 @@ def setup(app):
app.connect('doctree-read', process_todos)
app.connect('doctree-resolved', process_todo_nodes)
app.connect('env-purge-doc', purge_todos)
-
+ app.connect('env-merge-info', merge_info)
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
index 74a00463..cd3f2ac7 100644
--- a/sphinx/ext/viewcode.py
+++ b/sphinx/ext/viewcode.py
@@ -9,12 +9,37 @@
:license: BSD, see LICENSE for details.
"""
+import traceback
+
+from six import iteritems, text_type
from docutils import nodes
+import sphinx
from sphinx import addnodes
from sphinx.locale import _
from sphinx.pycode import ModuleAnalyzer
+from sphinx.util import get_full_modname
from sphinx.util.nodes import make_refnode
+from sphinx.util.console import blue
+
+
+def _get_full_modname(app, modname, attribute):
+ try:
+ return get_full_modname(modname, attribute)
+ except AttributeError:
+ # sphinx.ext.viewcode can't follow class instance attribute
+ # then AttributeError logging output only verbose mode.
+ app.verbose('Didn\'t find %s in %s' % (attribute, modname))
+ return None
+ except Exception as e:
+ # sphinx.ext.viewcode follow python domain directives.
+ # because of that, if there are no real modules exists that specified
+ # by py:function or other directives, viewcode emits a lot of warnings.
+ # It should be displayed only verbose mode.
+ app.verbose(traceback.format_exc().rstrip())
+ app.verbose('viewcode can\'t import %s, failed with error "%s"' %
+ (modname, e))
+ return None
def doctree_read(app, doctree):
@@ -22,24 +47,24 @@ def doctree_read(app, doctree):
if not hasattr(env, '_viewcode_modules'):
env._viewcode_modules = {}
- def has_tag(modname, fullname, docname):
+ def has_tag(modname, fullname, docname, refname):
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):
+ if not isinstance(analyzer.code, text_type):
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, {}
+ entry = code, analyzer.tags, {}, refname
env._viewcode_modules[modname] = entry
elif entry is False:
return
- code, tags, used = entry
+ _, tags, used, _ = entry
if fullname in tags:
used[fullname] = docname
return True
@@ -52,10 +77,14 @@ def doctree_read(app, doctree):
if not isinstance(signode, addnodes.desc_signature):
continue
modname = signode.get('module')
+ fullname = signode.get('fullname')
+ refname = modname
+ if env.config.viewcode_import:
+ modname = _get_full_modname(app, modname, fullname)
if not modname:
continue
fullname = signode.get('fullname')
- if not has_tag(modname, fullname, env.docname):
+ if not has_tag(modname, fullname, env.docname, refname):
continue
if fullname in names:
# only one link per name, please
@@ -72,6 +101,16 @@ def doctree_read(app, doctree):
signode += onlynode
+def env_merge_info(app, env, docnames, other):
+ if not hasattr(other, '_viewcode_modules'):
+ return
+ # create a _viewcode_modules dict on the main environment
+ if not hasattr(env, '_viewcode_modules'):
+ env._viewcode_modules = {}
+ # now merge in the information from the subprocess
+ env._viewcode_modules.update(other._viewcode_modules)
+
+
def missing_reference(app, env, node, contnode):
# resolve our "viewcode" reference nodes -- they need special treatment
if node['reftype'] == 'viewcode':
@@ -88,13 +127,15 @@ def collect_pages(app):
modnames = set(env._viewcode_modules)
- app.builder.info(' (%d module code pages)' %
- len(env._viewcode_modules), nonl=1)
+# app.builder.info(' (%d module code pages)' %
+# len(env._viewcode_modules), nonl=1)
- for modname, entry in env._viewcode_modules.iteritems():
+ for modname, entry in app.status_iterator(
+ iteritems(env._viewcode_modules), 'highlighting module code... ',
+ blue, len(env._viewcode_modules), lambda x: x[0]):
if not entry:
continue
- code, tags, used = entry
+ code, tags, used, refname = entry
# construct a page name for the highlighted source
pagename = '_modules/' + modname.replace('.', '/')
# highlight the source using the builder's highlighter
@@ -109,9 +150,9 @@ def collect_pages(app):
# the collected tags (HACK: this only works if the tag boundaries are
# properly nested!)
maxindex = len(lines) - 1
- for name, docname in used.iteritems():
+ for name, docname in iteritems(used):
type, start, end = tags[name]
- backlink = urito(pagename, docname) + '#' + modname + '.' + name
+ backlink = urito(pagename, docname) + '#' + refname + '.' + name
lines[start] = (
'<div class="viewcode-block" id="%s"><a class="viewcode-back" '
'href="%s">%s</a>' % (name, backlink, _('[docs]'))
@@ -134,15 +175,14 @@ def collect_pages(app):
context = {
'parents': parents,
'title': modname,
- 'body': _('<h1>Source code for %s</h1>') % modname + \
- '\n'.join(lines)
+ '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 = ['']
@@ -162,16 +202,19 @@ def collect_pages(app):
html.append('</ul>' * (len(stack) - 1))
context = {
'title': _('Overview: module code'),
- 'body': _('<h1>All modules for which code is available</h1>') + \
- ''.join(html),
+ 'body': (_('<h1>All modules for which code is available</h1>') +
+ ''.join(html)),
}
yield ('_modules/index', context, 'page.html')
def setup(app):
+ app.add_config_value('viewcode_import', True, False)
app.connect('doctree-read', doctree_read)
+ app.connect('env-merge-info', env_merge_info)
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')
+ # app.add_config_value('viewcode_include_modules', [], 'env')
+ # app.add_config_value('viewcode_exclude_modules', [], 'env')
+ return {'version': sphinx.__version__, 'parallel_read_safe': True}
diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py
index 600a7cf0..e257c370 100644
--- a/sphinx/highlighting.py
+++ b/sphinx/highlighting.py
@@ -9,7 +9,6 @@
:license: BSD, see LICENSE for details.
"""
-import sys
import re
import textwrap
@@ -19,62 +18,44 @@ except ImportError:
# parser is not available on Jython
parser = None
+from six import PY2, text_type
+
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')
+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
+
+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
@@ -85,8 +66,6 @@ class PygmentsBridge(object):
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':
@@ -117,7 +96,7 @@ class PygmentsBridge(object):
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' + \
+ return '\\begin{Verbatim}[frame=single,commandchars=\\\\\\{\\}]\n' + \
source + '\\end{Verbatim}\n'
def try_parse(self, src):
@@ -137,11 +116,7 @@ class PygmentsBridge(object):
# 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):
+ if PY2 and isinstance(src, text_type):
# 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
@@ -149,27 +124,19 @@ class PygmentsBridge(object):
# 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:
+ except (SyntaxError, UnicodeEncodeError):
return False
else:
return True
def highlight_block(self, source, lang, warn=None, force=False, **kwargs):
- if not isinstance(source, unicode):
+ if not isinstance(source, text_type):
source = source.decode()
- if not pygments:
- return self.unhighlighted(source)
# find out which lexer to use
if lang in ('py', 'python'):
@@ -223,16 +190,13 @@ class PygmentsBridge(object):
if self.dest == 'html':
return hlsource
else:
- if not isinstance(hlsource, unicode): # Py2 / Pygments < 1.6
+ hlsource = re.sub(r'(?<=\\begin{Verbatim}\[)(?=commandchars)',
+ r'frame=single,', hlsource)
+ if not isinstance(hlsource, text_type): # 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')
diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py
index f4a5a815..b161b427 100644
--- a/sphinx/jinja2glue.py
+++ b/sphinx/jinja2glue.py
@@ -12,6 +12,7 @@
from os import path
from pprint import pformat
+from six import string_types
from jinja2 import FileSystemLoader, BaseLoader, TemplateNotFound, \
contextfunction
from jinja2.utils import open_if_exists
@@ -22,7 +23,7 @@ from sphinx.util.osutil import mtimes_of_files
def _tobool(val):
- if isinstance(val, basestring):
+ if isinstance(val, string_types):
return val.lower() in ('true', '1', 'yes', 'on')
return bool(val)
@@ -113,7 +114,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
self.pathchain = pathchain
# make the paths into loaders
- self.loaders = map(SphinxFileSystemLoader, loaderchain)
+ self.loaders = [SphinxFileSystemLoader(x) for x in loaderchain]
use_i18n = builder.app.translator is not None
extensions = use_i18n and ['jinja2.ext.i18n'] or []
diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py
index b76aab1f..9332f474 100644
--- a/sphinx/locale/__init__.py
+++ b/sphinx/locale/__init__.py
@@ -9,12 +9,13 @@
:license: BSD, see LICENSE for details.
"""
-import sys
import gettext
-import UserString
+from six import PY3, text_type
+from six.moves import UserString
-class _TranslationProxy(UserString.UserString, object):
+
+class _TranslationProxy(UserString, object):
"""
Class for proxy strings from gettext translations. This is a helper for the
lazy_* functions from this module.
@@ -32,7 +33,7 @@ class _TranslationProxy(UserString.UserString, object):
def __new__(cls, func, *args):
if not args:
# not called with "function" and "arguments", but a plain string
- return unicode(func)
+ return text_type(func)
return object.__new__(cls)
def __getnewargs__(self):
@@ -59,11 +60,12 @@ class _TranslationProxy(UserString.UserString, object):
def __contains__(self, key):
return key in self.data
- def __nonzero__(self):
+ def __bool__(self):
return bool(self.data)
+ __nonzero__ = __bool__ # for python2 compatibility
def __dir__(self):
- return dir(unicode)
+ return dir(text_type)
def __iter__(self):
return iter(self.data)
@@ -75,7 +77,7 @@ class _TranslationProxy(UserString.UserString, object):
return str(self.data)
def __unicode__(self):
- return unicode(self.data)
+ return text_type(self.data)
def __add__(self, other):
return self.data + other
@@ -132,7 +134,7 @@ class _TranslationProxy(UserString.UserString, object):
def __repr__(self):
try:
- return 'i' + repr(unicode(self.data))
+ return 'i' + repr(text_type(self.data))
except:
return '<%s broken>' % self.__class__.__name__
@@ -183,7 +185,7 @@ pairindextypes = {
translators = {}
-if sys.version_info >= (3, 0):
+if PY3:
def _(message):
return translators['sphinx'].gettext(message)
else:
diff --git a/sphinx/locale/sphinx.pot b/sphinx/locale/sphinx.pot
index e19aea72..e0d51efb 100644
--- a/sphinx/locale/sphinx.pot
+++ b/sphinx/locale/sphinx.pot
@@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: Sphinx 1.2.2+/6728a8b81a26+\n"
+"Project-Id-Version: Sphinx 1.3a0\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2014-08-11 21:54+0900\n"
+"POT-Creation-Date: 2014-10-06 15:34+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,185 +17,201 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"
-#: sphinx/config.py:81
+#: sphinx/config.py:75
+#, python-format
+msgid "Fig. %s"
+msgstr ""
+
+#: sphinx/config.py:76
+#, python-format
+msgid "Table %s"
+msgstr ""
+
+#: sphinx/config.py:77
+#, python-format
+msgid "Listing %s"
+msgstr ""
+
+#: sphinx/config.py:84
#, python-format
msgid "%s %s documentation"
msgstr ""
-#: sphinx/environment.py:1550
+#: sphinx/environment.py:1825
#, python-format
msgid "see %s"
msgstr ""
-#: sphinx/environment.py:1553
+#: sphinx/environment.py:1828
#, python-format
msgid "see also %s"
msgstr ""
-#: sphinx/environment.py:1610
+#: sphinx/environment.py:1884
msgid "Symbols"
msgstr ""
-#: sphinx/roles.py:175
+#: sphinx/roles.py:193
#, 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
+#: sphinx/transforms.py:55 sphinx/writers/latex.py:210
+#: sphinx/writers/manpage.py:67 sphinx/writers/texinfo.py:221
#, python-format
msgid "%B %d, %Y"
msgstr ""
-#: sphinx/builders/changes.py:73
+#: sphinx/builders/changes.py:75
msgid "Builtins"
msgstr ""
-#: sphinx/builders/changes.py:75
+#: sphinx/builders/changes.py:77
msgid "Module level"
msgstr ""
-#: sphinx/builders/html.py:291
+#: sphinx/builders/html.py:290
#, python-format
msgid "%b %d, %Y"
msgstr ""
-#: sphinx/builders/html.py:310 sphinx/themes/basic/defindex.html:30
+#: sphinx/builders/html.py:309 sphinx/themes/basic/defindex.html:30
msgid "General Index"
msgstr ""
-#: sphinx/builders/html.py:310
+#: sphinx/builders/html.py:309
msgid "index"
msgstr ""
-#: sphinx/builders/html.py:370
+#: sphinx/builders/html.py:369
msgid "next"
msgstr ""
-#: sphinx/builders/html.py:379
+#: sphinx/builders/html.py:378
msgid "previous"
msgstr ""
-#: sphinx/builders/latex.py:142 sphinx/builders/texinfo.py:197
+#: sphinx/builders/latex.py:144 sphinx/builders/texinfo.py:198
msgid " (in "
msgstr ""
-#: sphinx/directives/other.py:138
+#: sphinx/directives/other.py:139
msgid "Section author: "
msgstr ""
-#: sphinx/directives/other.py:140
+#: sphinx/directives/other.py:141
msgid "Module author: "
msgstr ""
-#: sphinx/directives/other.py:142
+#: sphinx/directives/other.py:143
msgid "Code author: "
msgstr ""
-#: sphinx/directives/other.py:144
+#: sphinx/directives/other.py:145
msgid "Author: "
msgstr ""
-#: sphinx/domains/__init__.py:244
+#: sphinx/domains/__init__.py:273
#, python-format
msgid "%s %s"
msgstr ""
-#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:984 sphinx/domains/python.py:95
+#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:1637
+#: sphinx/domains/python.py:113
msgid "Parameters"
msgstr ""
-#: sphinx/domains/c.py:54 sphinx/domains/cpp.py:990
-#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:107
+#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:1643
+#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:125
msgid "Returns"
msgstr ""
-#: sphinx/domains/c.py:56 sphinx/domains/javascript.py:130
-#: sphinx/domains/python.py:109
+#: sphinx/domains/c.py:63 sphinx/domains/javascript.py:130
+#: sphinx/domains/python.py:127
msgid "Return type"
msgstr ""
-#: sphinx/domains/c.py:146
+#: sphinx/domains/c.py:177
#, python-format
msgid "%s (C function)"
msgstr ""
-#: sphinx/domains/c.py:148
+#: sphinx/domains/c.py:179
#, python-format
msgid "%s (C member)"
msgstr ""
-#: sphinx/domains/c.py:150
+#: sphinx/domains/c.py:181
#, python-format
msgid "%s (C macro)"
msgstr ""
-#: sphinx/domains/c.py:152
+#: sphinx/domains/c.py:183
#, python-format
msgid "%s (C type)"
msgstr ""
-#: sphinx/domains/c.py:154
+#: sphinx/domains/c.py:185
#, 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
+#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:1812
+#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:578
msgid "function"
msgstr ""
-#: sphinx/domains/c.py:212 sphinx/domains/cpp.py:1253
+#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:1813
msgid "member"
msgstr ""
-#: sphinx/domains/c.py:213
+#: sphinx/domains/c.py:244
msgid "macro"
msgstr ""
-#: sphinx/domains/c.py:214 sphinx/domains/cpp.py:1254
+#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:1814
msgid "type"
msgstr ""
-#: sphinx/domains/c.py:215
+#: sphinx/domains/c.py:246
msgid "variable"
msgstr ""
-#: sphinx/domains/cpp.py:987 sphinx/domains/javascript.py:125
+#: sphinx/domains/cpp.py:1640 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
+#: sphinx/domains/cpp.py:1705
#, python-format
msgid "%s (C++ type)"
msgstr ""
-#: sphinx/domains/cpp.py:1126
+#: sphinx/domains/cpp.py:1717
#, python-format
msgid "%s (C++ member)"
msgstr ""
-#: sphinx/domains/cpp.py:1182
+#: sphinx/domains/cpp.py:1728
#, python-format
msgid "%s (C++ function)"
msgstr ""
-#: sphinx/domains/cpp.py:1251 sphinx/domains/javascript.py:165
-#: sphinx/domains/python.py:562
+#: sphinx/domains/cpp.py:1739
+#, python-format
+msgid "%s (C++ class)"
+msgstr ""
+
+#: sphinx/domains/cpp.py:1811 sphinx/domains/javascript.py:165
+#: sphinx/domains/python.py:580
msgid "class"
msgstr ""
-#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:253
+#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:271
#, python-format
msgid "%s() (built-in function)"
msgstr ""
-#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:317
+#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:335
#, python-format
msgid "%s() (%s method)"
msgstr ""
@@ -210,7 +226,7 @@ msgstr ""
msgid "%s (global variable or constant)"
msgstr ""
-#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
+#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:373
#, python-format
msgid "%s (%s attribute)"
msgstr ""
@@ -219,319 +235,319 @@ msgstr ""
msgid "Arguments"
msgstr ""
-#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
+#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:579
msgid "data"
msgstr ""
-#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
+#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:585
msgid "attribute"
msgstr ""
-#: sphinx/domains/python.py:100
+#: sphinx/domains/python.py:118
msgid "Variables"
msgstr ""
-#: sphinx/domains/python.py:104
+#: sphinx/domains/python.py:122
msgid "Raises"
msgstr ""
-#: sphinx/domains/python.py:254 sphinx/domains/python.py:311
-#: sphinx/domains/python.py:323 sphinx/domains/python.py:336
+#: sphinx/domains/python.py:272 sphinx/domains/python.py:329
+#: sphinx/domains/python.py:341 sphinx/domains/python.py:354
#, python-format
msgid "%s() (in module %s)"
msgstr ""
-#: sphinx/domains/python.py:257
+#: sphinx/domains/python.py:275
#, python-format
msgid "%s (built-in variable)"
msgstr ""
-#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
+#: sphinx/domains/python.py:276 sphinx/domains/python.py:367
#, python-format
msgid "%s (in module %s)"
msgstr ""
-#: sphinx/domains/python.py:274
+#: sphinx/domains/python.py:292
#, python-format
msgid "%s (built-in class)"
msgstr ""
-#: sphinx/domains/python.py:275
+#: sphinx/domains/python.py:293
#, python-format
msgid "%s (class in %s)"
msgstr ""
-#: sphinx/domains/python.py:315
+#: sphinx/domains/python.py:333
#, python-format
msgid "%s() (%s.%s method)"
msgstr ""
-#: sphinx/domains/python.py:327
+#: sphinx/domains/python.py:345
#, python-format
msgid "%s() (%s.%s static method)"
msgstr ""
-#: sphinx/domains/python.py:330
+#: sphinx/domains/python.py:348
#, python-format
msgid "%s() (%s static method)"
msgstr ""
-#: sphinx/domains/python.py:340
+#: sphinx/domains/python.py:358
#, python-format
msgid "%s() (%s.%s class method)"
msgstr ""
-#: sphinx/domains/python.py:343
+#: sphinx/domains/python.py:361
#, python-format
msgid "%s() (%s class method)"
msgstr ""
-#: sphinx/domains/python.py:353
+#: sphinx/domains/python.py:371
#, python-format
msgid "%s (%s.%s attribute)"
msgstr ""
-#: sphinx/domains/python.py:434
+#: sphinx/domains/python.py:452
#, python-format
msgid "%s (module)"
msgstr ""
-#: sphinx/domains/python.py:491
+#: sphinx/domains/python.py:509
msgid "Python Module Index"
msgstr ""
-#: sphinx/domains/python.py:492
+#: sphinx/domains/python.py:510
msgid "modules"
msgstr ""
-#: sphinx/domains/python.py:538
+#: sphinx/domains/python.py:556
msgid "Deprecated"
msgstr ""
-#: sphinx/domains/python.py:563 sphinx/locale/__init__.py:179
+#: sphinx/domains/python.py:581 sphinx/locale/__init__.py:181
msgid "exception"
msgstr ""
-#: sphinx/domains/python.py:564
+#: sphinx/domains/python.py:582
msgid "method"
msgstr ""
-#: sphinx/domains/python.py:565
+#: sphinx/domains/python.py:583
msgid "class method"
msgstr ""
-#: sphinx/domains/python.py:566
+#: sphinx/domains/python.py:584
msgid "static method"
msgstr ""
-#: sphinx/domains/python.py:568 sphinx/locale/__init__.py:175
+#: sphinx/domains/python.py:586 sphinx/locale/__init__.py:177
msgid "module"
msgstr ""
-#: sphinx/domains/python.py:696
+#: sphinx/domains/python.py:751
msgid " (deprecated)"
msgstr ""
-#: sphinx/domains/rst.py:53
+#: sphinx/domains/rst.py:55
#, python-format
msgid "%s (directive)"
msgstr ""
-#: sphinx/domains/rst.py:55
+#: sphinx/domains/rst.py:57
#, python-format
msgid "%s (role)"
msgstr ""
-#: sphinx/domains/rst.py:104
+#: sphinx/domains/rst.py:106
msgid "directive"
msgstr ""
-#: sphinx/domains/rst.py:105
+#: sphinx/domains/rst.py:107
msgid "role"
msgstr ""
-#: sphinx/domains/std.py:69 sphinx/domains/std.py:85
+#: sphinx/domains/std.py:72 sphinx/domains/std.py:88
#, python-format
msgid "environment variable; %s"
msgstr ""
-#: sphinx/domains/std.py:180
+#: sphinx/domains/std.py:184
#, python-format
msgid "%scommand line option; %s"
msgstr ""
-#: sphinx/domains/std.py:457
+#: sphinx/domains/std.py:442
msgid "glossary term"
msgstr ""
-#: sphinx/domains/std.py:458
+#: sphinx/domains/std.py:443
msgid "grammar token"
msgstr ""
-#: sphinx/domains/std.py:459
+#: sphinx/domains/std.py:444
msgid "reference label"
msgstr ""
-#: sphinx/domains/std.py:461
+#: sphinx/domains/std.py:446
msgid "environment variable"
msgstr ""
-#: sphinx/domains/std.py:462
+#: sphinx/domains/std.py:447
msgid "program option"
msgstr ""
-#: sphinx/domains/std.py:492 sphinx/themes/basic/genindex-single.html:32
+#: sphinx/domains/std.py:477 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
+#: sphinx/writers/latex.py:199 sphinx/writers/texinfo.py:479
msgid "Index"
msgstr ""
-#: sphinx/domains/std.py:493
+#: sphinx/domains/std.py:478
msgid "Module Index"
msgstr ""
-#: sphinx/domains/std.py:494 sphinx/themes/basic/defindex.html:25
+#: sphinx/domains/std.py:479 sphinx/themes/basic/defindex.html:25
msgid "Search Page"
msgstr ""
-#: sphinx/ext/autodoc.py:1065
+#: sphinx/ext/autodoc.py:1127
#, python-format
msgid " Bases: %s"
msgstr ""
-#: sphinx/ext/autodoc.py:1113
+#: sphinx/ext/autodoc.py:1175
#, python-format
msgid "alias of :class:`%s`"
msgstr ""
-#: sphinx/ext/graphviz.py:297 sphinx/ext/graphviz.py:305
+#: sphinx/ext/graphviz.py:293 sphinx/ext/graphviz.py:301
#, python-format
msgid "[graph: %s]"
msgstr ""
-#: sphinx/ext/graphviz.py:299 sphinx/ext/graphviz.py:307
+#: sphinx/ext/graphviz.py:295 sphinx/ext/graphviz.py:303
msgid "[graph]"
msgstr ""
-#: sphinx/ext/intersphinx.py:244
+#: sphinx/ext/intersphinx.py:257
#, python-format
msgid "(in %s v%s)"
msgstr ""
-#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
+#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:99
msgid "[source]"
msgstr ""
-#: sphinx/ext/todo.py:42
+#: sphinx/ext/todo.py:43
msgid "Todo"
msgstr ""
-#: sphinx/ext/todo.py:112
+#: sphinx/ext/todo.py:113
#, python-format
msgid "(The <<original entry>> is located in %s, line %d.)"
msgstr ""
-#: sphinx/ext/todo.py:121
+#: sphinx/ext/todo.py:122
msgid "original entry"
msgstr ""
-#: sphinx/ext/viewcode.py:117
+#: sphinx/ext/viewcode.py:158
msgid "[docs]"
msgstr ""
-#: sphinx/ext/viewcode.py:131
+#: sphinx/ext/viewcode.py:172
msgid "Module code"
msgstr ""
-#: sphinx/ext/viewcode.py:137
+#: sphinx/ext/viewcode.py:178
#, python-format
msgid "<h1>Source code for %s</h1>"
msgstr ""
-#: sphinx/ext/viewcode.py:164
+#: sphinx/ext/viewcode.py:204
msgid "Overview: module code"
msgstr ""
-#: sphinx/ext/viewcode.py:165
+#: sphinx/ext/viewcode.py:205
msgid "<h1>All modules for which code is available</h1>"
msgstr ""
-#: sphinx/locale/__init__.py:155
+#: sphinx/locale/__init__.py:157
msgid "Attention"
msgstr ""
-#: sphinx/locale/__init__.py:156
+#: sphinx/locale/__init__.py:158
msgid "Caution"
msgstr ""
-#: sphinx/locale/__init__.py:157
+#: sphinx/locale/__init__.py:159
msgid "Danger"
msgstr ""
-#: sphinx/locale/__init__.py:158
+#: sphinx/locale/__init__.py:160
msgid "Error"
msgstr ""
-#: sphinx/locale/__init__.py:159
+#: sphinx/locale/__init__.py:161
msgid "Hint"
msgstr ""
-#: sphinx/locale/__init__.py:160
+#: sphinx/locale/__init__.py:162
msgid "Important"
msgstr ""
-#: sphinx/locale/__init__.py:161
+#: sphinx/locale/__init__.py:163
msgid "Note"
msgstr ""
-#: sphinx/locale/__init__.py:162
+#: sphinx/locale/__init__.py:164
msgid "See also"
msgstr ""
-#: sphinx/locale/__init__.py:163
+#: sphinx/locale/__init__.py:165
msgid "Tip"
msgstr ""
-#: sphinx/locale/__init__.py:164
+#: sphinx/locale/__init__.py:166
msgid "Warning"
msgstr ""
-#: sphinx/locale/__init__.py:168
+#: sphinx/locale/__init__.py:170
#, python-format
msgid "New in version %s"
msgstr ""
-#: sphinx/locale/__init__.py:169
+#: sphinx/locale/__init__.py:171
#, python-format
msgid "Changed in version %s"
msgstr ""
-#: sphinx/locale/__init__.py:170
+#: sphinx/locale/__init__.py:172
#, python-format
msgid "Deprecated since version %s"
msgstr ""
-#: sphinx/locale/__init__.py:176
+#: sphinx/locale/__init__.py:178
msgid "keyword"
msgstr ""
-#: sphinx/locale/__init__.py:177
+#: sphinx/locale/__init__.py:179
msgid "operator"
msgstr ""
-#: sphinx/locale/__init__.py:178
+#: sphinx/locale/__init__.py:180
msgid "object"
msgstr ""
-#: sphinx/locale/__init__.py:180
+#: sphinx/locale/__init__.py:182
msgid "statement"
msgstr ""
-#: sphinx/locale/__init__.py:181
+#: sphinx/locale/__init__.py:183
msgid "built-in function"
msgstr ""
@@ -540,21 +556,21 @@ msgstr ""
msgid "Table Of Contents"
msgstr ""
-#: sphinx/themes/agogo/layout.html:50 sphinx/themes/basic/layout.html:137
+#: sphinx/themes/agogo/layout.html:51 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
+#: sphinx/themes/agogo/layout.html:54 sphinx/themes/basic/searchbox.html:15
msgid "Go"
msgstr ""
-#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
+#: sphinx/themes/agogo/layout.html:59 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
+#: sphinx/themes/agogo/layout.html:84 sphinx/themes/basic/sourcelink.html:15
msgid "Show Source"
msgstr ""
@@ -716,7 +732,7 @@ msgstr ""
msgid "Quick search"
msgstr ""
-#: sphinx/themes/basic/sourcelink.html:11
+#: sphinx/themes/basic/sourcelink.html:12
msgid "This Page"
msgstr ""
@@ -748,12 +764,11 @@ msgstr ""
msgid "Other changes"
msgstr ""
-#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:542
-#: sphinx/writers/html.py:548
+#: sphinx/themes/basic/static/doctools.js:142 sphinx/writers/html.py:600
msgid "Permalink to this headline"
msgstr ""
-#: sphinx/themes/basic/static/doctools.js:148 sphinx/writers/html.py:108
+#: sphinx/themes/basic/static/doctools.js:148
msgid "Permalink to this definition"
msgstr ""
@@ -791,29 +806,34 @@ msgstr ""
msgid "Contents"
msgstr ""
-#: sphinx/writers/latex.py:192
+#: sphinx/writers/html.py:266
+#, python-format
+msgid "Permalink to this %s"
+msgstr ""
+
+#: sphinx/writers/latex.py:197
msgid "Release"
msgstr ""
-#: sphinx/writers/latex.py:624 sphinx/writers/manpage.py:178
-#: sphinx/writers/texinfo.py:612
+#: sphinx/writers/latex.py:638 sphinx/writers/manpage.py:177
+#: sphinx/writers/texinfo.py:616
msgid "Footnotes"
msgstr ""
-#: sphinx/writers/latex.py:709
+#: sphinx/writers/latex.py:723
msgid "continued from previous page"
msgstr ""
-#: sphinx/writers/latex.py:715
+#: sphinx/writers/latex.py:729
msgid "Continued on next page"
msgstr ""
-#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:538
+#: sphinx/writers/manpage.py:223 sphinx/writers/text.py:541
#, python-format
msgid "[image: %s]"
msgstr ""
-#: sphinx/writers/manpage.py:225 sphinx/writers/text.py:539
+#: sphinx/writers/manpage.py:224 sphinx/writers/text.py:542
msgid "[image]"
msgstr ""
diff --git a/sphinx/make_mode.py b/sphinx/make_mode.py
index 45f62b9b..d95c848b 100644
--- a/sphinx/make_mode.py
+++ b/sphinx/make_mode.py
@@ -14,7 +14,7 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-from __future__ import with_statement
+from __future__ import print_function
import os
import sys
@@ -71,92 +71,93 @@ class Make(object):
if not path.exists(self.builddir):
return
elif not path.isdir(self.builddir):
- print "Error: %r is not a directory!" % self.builddir
+ print("Error: %r is not a directory!" % self.builddir)
return 1
- print "Removing everything under %r..." % self.builddir
+ 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)
+ 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)
+ 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')
+ 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')
+ 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')
+ 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.'
+ 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.'
+ 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')
+ 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)
+ 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"
+ 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')
+ 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')
+ 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)."
+ 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:
@@ -173,17 +174,17 @@ class Make(object):
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')
+ 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')
+ 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)."
+ 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:
@@ -195,50 +196,50 @@ class Make(object):
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')
+ 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')
+ 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')
+ 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'))
+ 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?"
+ 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'))
+ 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')
+ 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')
+ 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
@@ -254,8 +255,8 @@ class Make(object):
def run_make_mode(args):
if len(args) < 3:
- print >>sys.stderr, ('Error: at least 3 arguments (builder, source '
- 'dir, build dir) are required.')
+ print('Error: at least 3 arguments (builder, source '
+ 'dir, build dir) are required.', file=sys.stderr)
return 1
make = Make(args[1], args[2], args[3:])
run_method = 'build_' + args[0]
diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py
index 7a6f59b1..461eea05 100644
--- a/sphinx/pycode/__init__.py
+++ b/sphinx/pycode/__init__.py
@@ -8,16 +8,19 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
import sys
from os import path
+from six import iteritems, text_type, BytesIO, StringIO
+
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.pycompat import TextIOWrapper
from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc
@@ -29,9 +32,9 @@ 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():
+for k, v in iteritems(pygrammar.symbol2number):
setattr(sym, k, v)
-for k, v in token.tok_name.iteritems():
+for k, v in iteritems(token.tok_name):
setattr(sym, v, k)
# a dict mapping terminal and nonterminal numbers to their names
@@ -97,7 +100,7 @@ class AttrDocVisitor(nodes.NodeVisitor):
continue # skip over semicolon
if parent[idx].type == sym.NEWLINE:
prefix = parent[idx].get_prefix()
- if not isinstance(prefix, unicode):
+ if not isinstance(prefix, text_type):
prefix = prefix.decode(self.encoding)
docstring = prepare_commentdoc(prefix)
if docstring:
@@ -115,7 +118,7 @@ class AttrDocVisitor(nodes.NodeVisitor):
if not pnode or pnode.type not in (token.INDENT, token.DEDENT):
break
prefix = pnode.get_prefix()
- if not isinstance(prefix, unicode):
+ if not isinstance(prefix, text_type):
prefix = prefix.decode(self.encoding)
docstring = prepare_commentdoc(prefix)
self.add_docstring(node, docstring)
@@ -182,7 +185,7 @@ class ModuleAnalyzer(object):
return cls.cache['file', filename]
try:
fileobj = open(filename, 'rb')
- except Exception, err:
+ except Exception as err:
raise PycodeError('error opening %r' % filename, err)
obj = cls(fileobj, modname, filename)
cls.cache['file', filename] = obj
@@ -202,7 +205,7 @@ class ModuleAnalyzer(object):
obj = cls.for_string(source, modname)
else:
obj = cls.for_file(source, modname)
- except PycodeError, err:
+ except PycodeError as err:
cls.cache['module', modname] = err
raise
cls.cache['module', modname] = obj
@@ -245,7 +248,7 @@ class ModuleAnalyzer(object):
return
try:
self.tokens = list(tokenize.generate_tokens(self.source.readline))
- except tokenize.TokenError, err:
+ except tokenize.TokenError as err:
raise PycodeError('tokenizing failed', err)
self.source.close()
@@ -256,7 +259,7 @@ class ModuleAnalyzer(object):
self.tokenize()
try:
self.parsetree = pydriver.parse_tokens(self.tokens)
- except parse.ParseError, err:
+ except parse.ParseError as err:
raise PycodeError('parsing failed', err)
def find_attr_docs(self, scope=''):
@@ -338,10 +341,10 @@ if __name__ == '__main__':
x1 = time.time()
ma.parse()
x2 = time.time()
- #for (ns, name), doc in ma.find_attr_docs().iteritems():
+ #for (ns, name), doc in iteritems(ma.find_attr_docs()):
# 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)
+ print("tokenizing %.4f, parsing %.4f, finding %.4f" % (x1-x0, x2-x1, x3-x2))
diff --git a/sphinx/pycode/pgen2/driver.py b/sphinx/pycode/pgen2/driver.py
index 422671db..c531edb3 100644
--- a/sphinx/pycode/pgen2/driver.py
+++ b/sphinx/pycode/pgen2/driver.py
@@ -131,7 +131,7 @@ def load_grammar(gt="Grammar.txt", gp=None,
logger.info("Writing grammar tables to %s", gp)
try:
g.dump(gp)
- except IOError, e:
+ except IOError as e:
logger.info("Writing failed:"+str(e))
else:
g = grammar.Grammar()
diff --git a/sphinx/pycode/pgen2/grammar.py b/sphinx/pycode/pgen2/grammar.py
index 01d84346..91874fa2 100644
--- a/sphinx/pycode/pgen2/grammar.py
+++ b/sphinx/pycode/pgen2/grammar.py
@@ -11,6 +11,7 @@ token module; the Python tokenize module reports all operators as the
fallback token code OP, but the parser needs the actual token code.
"""
+from __future__ import print_function
# Python imports
import pickle
@@ -100,17 +101,17 @@ class Grammar(object):
def report(self):
"""Dump the grammar tables to standard output, for debugging."""
from pprint import pprint
- print "s2n"
+ print("s2n")
pprint(self.symbol2number)
- print "n2s"
+ print("n2s")
pprint(self.number2symbol)
- print "states"
+ print("states")
pprint(self.states)
- print "dfas"
+ print("dfas")
pprint(self.dfas)
- print "labels"
+ print("labels")
pprint(self.labels)
- print "start", self.start
+ print("start", self.start)
# Map from operator to number (since tokenize doesn't do this)
diff --git a/sphinx/pycode/pgen2/literals.py b/sphinx/pycode/pgen2/literals.py
index d4893702..25e09b62 100644
--- a/sphinx/pycode/pgen2/literals.py
+++ b/sphinx/pycode/pgen2/literals.py
@@ -4,9 +4,13 @@
# Extended to handle raw and unicode literals by Georg Brandl.
"""Safely evaluate Python string literals without using eval()."""
+from __future__ import print_function
import re
+from six import text_type
+
+
simple_escapes = {"a": "\a",
"b": "\b",
"f": "\f",
@@ -66,7 +70,7 @@ uni_escape_re = re.compile(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3}|"
def evalString(s, encoding=None):
regex = escape_re
repl = escape
- if encoding and not isinstance(s, unicode):
+ if encoding and not isinstance(s, text_type):
s = s.decode(encoding)
if s.startswith('u') or s.startswith('U'):
regex = uni_escape_re
@@ -89,7 +93,7 @@ def test():
s = repr(c)
e = evalString(s)
if e != c:
- print i, c, s, e
+ print(i, c, s, e)
if __name__ == "__main__":
diff --git a/sphinx/pycode/pgen2/parse.c b/sphinx/pycode/pgen2/parse.c
index e09f5058..96fa6c8b 100644
--- a/sphinx/pycode/pgen2/parse.c
+++ b/sphinx/pycode/pgen2/parse.c
@@ -353,95 +353,6 @@ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name); /*proto*/
-#if PY_VERSION_HEX < 0x02050000
-#ifndef PyAnySet_CheckExact
-
-#define PyAnySet_CheckExact(ob) \
- ((ob)->ob_type == &PySet_Type || \
- (ob)->ob_type == &PyFrozenSet_Type)
-
-#define PySet_New(iterable) \
- PyObject_CallFunctionObjArgs((PyObject *)&PySet_Type, (iterable), NULL)
-
-#define Pyx_PyFrozenSet_New(iterable) \
- PyObject_CallFunctionObjArgs((PyObject *)&PyFrozenSet_Type, (iterable), NULL)
-
-#define PySet_Size(anyset) \
- PyObject_Size((anyset))
-
-#define PySet_Contains(anyset, key) \
- PySequence_Contains((anyset), (key))
-
-#define PySet_Pop(set) \
- PyObject_CallMethod(set, (char *)"pop", NULL)
-
-static INLINE int PySet_Clear(PyObject *set) {
- PyObject *ret = PyObject_CallMethod(set, (char *)"clear", NULL);
- if (!ret) return -1;
- Py_DECREF(ret); return 0;
-}
-
-static INLINE int PySet_Discard(PyObject *set, PyObject *key) {
- PyObject *ret = PyObject_CallMethod(set, (char *)"discard", (char *)"O", key);
- if (!ret) return -1;
- Py_DECREF(ret); return 0;
-}
-
-static INLINE int PySet_Add(PyObject *set, PyObject *key) {
- PyObject *ret = PyObject_CallMethod(set, (char *)"add", (char *)"O", key);
- if (!ret) return -1;
- Py_DECREF(ret); return 0;
-}
-
-#endif /* PyAnySet_CheckExact (<= Py2.4) */
-
-#if PY_VERSION_HEX < 0x02040000
-#ifndef Py_SETOBJECT_H
-#define Py_SETOBJECT_H
-
-static PyTypeObject *__Pyx_PySet_Type = NULL;
-static PyTypeObject *__Pyx_PyFrozenSet_Type = NULL;
-
-#define PySet_Type (*__Pyx_PySet_Type)
-#define PyFrozenSet_Type (*__Pyx_PyFrozenSet_Type)
-
-#define PyAnySet_Check(ob) \
- (PyAnySet_CheckExact(ob) || \
- PyType_IsSubtype((ob)->ob_type, &PySet_Type) || \
- PyType_IsSubtype((ob)->ob_type, &PyFrozenSet_Type))
-
-#define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type)
-
-static int __Pyx_Py23SetsImport(void) {
- PyObject *sets=0, *Set=0, *ImmutableSet=0;
-
- sets = PyImport_ImportModule((char *)"sets");
- if (!sets) goto bad;
- Set = PyObject_GetAttrString(sets, (char *)"Set");
- if (!Set) goto bad;
- ImmutableSet = PyObject_GetAttrString(sets, (char *)"ImmutableSet");
- if (!ImmutableSet) goto bad;
- Py_DECREF(sets);
-
- __Pyx_PySet_Type = (PyTypeObject*) Set;
- __Pyx_PyFrozenSet_Type = (PyTypeObject*) ImmutableSet;
-
- return 0;
-
- bad:
- Py_XDECREF(sets);
- Py_XDECREF(Set);
- Py_XDECREF(ImmutableSet);
- return -1;
-}
-
-#else
-static int __Pyx_Py23SetsImport(void) { return 0; }
-#endif /* !Py_SETOBJECT_H */
-#endif /* < Py2.4 */
-#endif /* < Py2.5 */
-
-
static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
PyObject *r;
if (!j) return NULL;
diff --git a/sphinx/pycode/pgen2/pgen.py b/sphinx/pycode/pgen2/pgen.py
index 0a04447d..e199ed8a 100644
--- a/sphinx/pycode/pgen2/pgen.py
+++ b/sphinx/pycode/pgen2/pgen.py
@@ -1,7 +1,12 @@
# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
# Licensed to PSF under a Contributor Agreement.
+from __future__ import print_function
+
+from six import iteritems
+
# Pgen imports
+
from sphinx.pycode.pgen2 import grammar, token, tokenize
class PgenGrammar(grammar.Grammar):
@@ -26,7 +31,7 @@ class ParserGenerator(object):
def make_grammar(self):
c = PgenGrammar()
- names = self.dfas.keys()
+ names = list(self.dfas.keys())
names.sort()
names.remove(self.startsymbol)
names.insert(0, self.startsymbol)
@@ -39,7 +44,7 @@ class ParserGenerator(object):
states = []
for state in dfa:
arcs = []
- for label, next in state.arcs.iteritems():
+ for label, next in iteritems(state.arcs):
arcs.append((self.make_label(c, label), dfa.index(next)))
if state.isfinal:
arcs.append((0, dfa.index(state)))
@@ -105,7 +110,7 @@ class ParserGenerator(object):
return ilabel
def addfirstsets(self):
- names = self.dfas.keys()
+ names = list(self.dfas.keys())
names.sort()
for name in names:
if name not in self.first:
@@ -118,7 +123,7 @@ class ParserGenerator(object):
state = dfa[0]
totalset = {}
overlapcheck = {}
- for label, next in state.arcs.iteritems():
+ for label, next in iteritems(state.arcs):
if label in self.dfas:
if label in self.first:
fset = self.first[label]
@@ -133,7 +138,7 @@ class ParserGenerator(object):
totalset[label] = 1
overlapcheck[label] = {label: 1}
inverse = {}
- for label, itsfirst in overlapcheck.iteritems():
+ for label, itsfirst in iteritems(overlapcheck):
for symbol in itsfirst:
if symbol in inverse:
raise ValueError("rule %s is ambiguous; %s is in the"
@@ -192,7 +197,7 @@ class ParserGenerator(object):
for label, next in nfastate.arcs:
if label is not None:
addclosure(next, arcs.setdefault(label, {}))
- for label, nfaset in arcs.iteritems():
+ for label, nfaset in iteritems(arcs):
for st in states:
if st.nfaset == nfaset:
break
@@ -203,10 +208,10 @@ class ParserGenerator(object):
return states # List of DFAState instances; first one is start
def dump_nfa(self, name, start, finish):
- print "Dump of NFA for", name
+ print("Dump of NFA for", name)
todo = [start]
for i, state in enumerate(todo):
- print " State", i, state is finish and "(final)" or ""
+ print(" State", i, state is finish and "(final)" or "")
for label, next in state.arcs:
if next in todo:
j = todo.index(next)
@@ -214,16 +219,16 @@ class ParserGenerator(object):
j = len(todo)
todo.append(next)
if label is None:
- print " -> %d" % j
+ print(" -> %d" % j)
else:
- print " %s -> %d" % (label, j)
+ print(" %s -> %d" % (label, j))
def dump_dfa(self, name, dfa):
- print "Dump of DFA for", name
+ 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))
+ print(" State", i, state.isfinal and "(final)" or "")
+ for label, next in iteritems(state.arcs):
+ print(" %s -> %d" % (label, dfa.index(next)))
def simplify_dfa(self, dfa):
# This is not theoretically optimal, but works well enough.
@@ -319,9 +324,9 @@ class ParserGenerator(object):
return value
def gettoken(self):
- tup = self.generator.next()
+ tup = next(self.generator)
while tup[0] in (tokenize.COMMENT, tokenize.NL):
- tup = self.generator.next()
+ tup = next(self.generator)
self.type, self.value, self.begin, self.end, self.line = tup
#print token.tok_name[self.type], repr(self.value)
@@ -330,7 +335,7 @@ class ParserGenerator(object):
try:
msg = msg % args
except:
- msg = " ".join([msg] + map(str, args))
+ msg = " ".join([msg] + [str(x) for x in args])
raise SyntaxError(msg, (self.filename, self.end[0],
self.end[1], self.line))
@@ -348,7 +353,7 @@ class DFAState(object):
def __init__(self, nfaset, final):
assert isinstance(nfaset, dict)
- assert isinstance(iter(nfaset).next(), NFAState)
+ assert isinstance(next(iter(nfaset)), NFAState)
assert isinstance(final, NFAState)
self.nfaset = nfaset
self.isfinal = final in nfaset
@@ -361,7 +366,7 @@ class DFAState(object):
self.arcs[label] = next
def unifystate(self, old, new):
- for label, next in self.arcs.iteritems():
+ for label, next in iteritems(self.arcs):
if next is old:
self.arcs[label] = new
@@ -374,7 +379,7 @@ class DFAState(object):
# would invoke this method recursively, with cycles...
if len(self.arcs) != len(other.arcs):
return False
- for label, next in self.arcs.iteritems():
+ for label, next in iteritems(self.arcs):
if next is not other.arcs.get(label):
return False
return True
diff --git a/sphinx/pycode/pgen2/token.py b/sphinx/pycode/pgen2/token.py
index 56a40ce7..55bf5e8d 100755
--- a/sphinx/pycode/pgen2/token.py
+++ b/sphinx/pycode/pgen2/token.py
@@ -68,7 +68,7 @@ NT_OFFSET = 256
#--end constants--
tok_name = {}
-for _name, _value in globals().items():
+for _name, _value in list(globals().items()):
if type(_value) is type(0):
tok_name[_value] = _name
diff --git a/sphinx/pycode/pgen2/tokenize.py b/sphinx/pycode/pgen2/tokenize.py
index 7ad9f012..d6253505 100644
--- a/sphinx/pycode/pgen2/tokenize.py
+++ b/sphinx/pycode/pgen2/tokenize.py
@@ -23,13 +23,17 @@ Older entry points
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."""
+each time a new token is found.
+"""
+
+from __future__ import print_function
__author__ = 'Ka-Ping Yee <ping@lfw.org>'
__credits__ = \
'GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, Skip Montanaro'
import string, re
+from six import PY3
from sphinx.pycode.pgen2.token import *
from sphinx.pycode.pgen2 import token
@@ -81,6 +85,9 @@ Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"<>", r"!=",
Bracket = '[][(){}]'
Special = group(r'\r?\n', r'[:;.,`@]')
+if PY3:
+ Ellipsis_ = r'\.{3}'
+ Special = group(Ellipsis_, Special)
Funny = group(Operator, Bracket, Special)
PlainToken = group(Number, Funny, String, Name)
@@ -94,8 +101,9 @@ ContStr = group(r"[uUbB]?[rR]?'[^\n'\\]*(?:\\.[^\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))
+tokenprog, pseudoprog, single3prog, double3prog = [
+ re.compile(x) for x in (Token, PseudoToken, Single3, Double3)
+]
endprogs = {"'": re.compile(Single), '"': re.compile(Double),
"'''": single3prog, '"""': double3prog,
"r'''": single3prog, 'r"""': double3prog,
@@ -146,8 +154,8 @@ 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))
+ print("%d,%d-%d,%d:\t%s\t%s" %
+ (srow, scol, erow, ecol, tok_name[type], repr(token)))
def tokenize(readline, tokeneater=printtoken):
"""
@@ -352,8 +360,9 @@ def generate_tokens(readline):
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
+ if initial in numchars or (
+ initial == '.' and token not in ('.', '...')
+ ): # ordinary number
yield (NUMBER, token, spos, epos, line)
elif initial in '\r\n':
newline = NEWLINE
@@ -389,6 +398,8 @@ def generate_tokens(readline):
yield (STRING, token, spos, epos, line)
elif initial in namechars: # ordinary name
yield (NAME, token, spos, epos, line)
+ elif token in ('...',): # 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)
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py
index dbb01c59..184c25cb 100644
--- a/sphinx/quickstart.py
+++ b/sphinx/quickstart.py
@@ -8,32 +8,61 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
-import sys, os, time, re
+import re
+import os
+import sys
+import optparse
+import time
from os import path
+from io import open
TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
+# try to import readline, unix specific enhancement
+try:
+ import readline
+ if readline.__doc__ and 'libedit' in readline.__doc__:
+ readline.parse_and_bind("bind ^I rl_complete")
+ else:
+ readline.parse_and_bind("tab: complete")
+except ImportError:
+ pass
+
+from six import PY2, PY3, text_type
+from six.moves import input
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
+ 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
-
+term_input = input
+
+DEFAULT_VALUE = {
+ 'path': '.',
+ 'sep': False,
+ 'dot': '_',
+ 'language': None,
+ 'suffix': '.rst',
+ 'master': 'index',
+ 'epub': False,
+ 'ext_autodoc': False,
+ 'ext_doctest': False,
+ 'makefile': True,
+ 'batchfile': True,
+ }
+
+EXTENSIONS = ('autodoc', 'doctest', 'intersphinx', 'todo', 'coverage',
+ 'pngmath', 'mathjax', 'ifconfig', 'viewcode')
PROMPT_PREFIX = '> '
-if sys.version_info >= (3, 0):
+if PY3:
# prevents that the file is checked for being written in Python 2.x syntax
QUICKSTART_CONF = u'#!/usr/bin/env python3\n'
else:
@@ -99,7 +128,10 @@ release = '%(release_str)s'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
-#language = None
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = %(language)r
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
@@ -217,10 +249,23 @@ html_static_path = ['%(dot)sstatic']
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
+# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
+#html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# Now only 'ja' uses this config value
+#html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#html_search_scorer = 'scorer.js'
+
# Output file base name for HTML help builder.
htmlhelp_basename = '%(project_fn)sdoc'
-
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
@@ -232,6 +277,9 @@ latex_elements = {
# Additional stuff for the LaTeX preamble.
#'preamble': '',
+
+# Latex figure (float) alignment
+#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
@@ -320,7 +368,7 @@ epub_copyright = u'%(copyright_str)s'
#epub_theme = 'epub'
# The language of the text. It defaults to the language option
-# or en if the language is not set.
+# or 'en' if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
@@ -432,7 +480,7 @@ $(SPHINXOPTS) %(rsrcdir)s
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
+epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
\t@echo "Please use \\`make <target>' where <target> is one of"
@@ -459,6 +507,7 @@ help:
\t@echo " linkcheck to check all external links for integrity"
\t@echo " doctest to run all doctests embedded in the documentation \
(if enabled)"
+\t@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
\trm -rf $(BUILDDIR)/*
@@ -581,6 +630,11 @@ doctest:
\t@echo "Testing of doctests in the sources finished, look at the " \\
\t "results in $(BUILDDIR)/doctest/output.txt."
+coverage:
+\t$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
+\t@echo "Testing of coverage in the sources finished, look at the " \\
+\t "results in $(BUILDDIR)/coverage/python.txt."
+
xml:
\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
\t@echo
@@ -632,6 +686,7 @@ if "%%1" == "help" (
\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
+\techo. coverage to run coverage check of the documentation if enabled
\tgoto end
)
@@ -642,6 +697,14 @@ if "%%1" == "clean" (
)
+REM Check if sphinx-build is available and fallback to Python version if any
+%%SPHINXBUILD%% 2> nul
+if errorlevel 9009 goto sphinx_python
+goto sphinx_ok
+
+:sphinx_python
+
+set SPHINXBUILD=python -m sphinx.__init__
%%SPHINXBUILD%% 2> nul
if errorlevel 9009 (
\techo.
@@ -655,6 +718,9 @@ if errorlevel 9009 (
\texit /b 1
)
+:sphinx_ok
+
+
if "%%1" == "html" (
\t%%SPHINXBUILD%% -b html %%ALLSPHINXOPTS%% %%BUILDDIR%%/html
\tif errorlevel 1 exit /b 1
@@ -744,7 +810,7 @@ if "%%1" == "latexpdf" (
\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
\tcd %%BUILDDIR%%/latex
\tmake all-pdf
-\tcd %%BUILDDIR%%/..
+\tcd %%~dp0
\techo.
\techo.Build finished; the PDF files are in %%BUILDDIR%%/latex.
\tgoto end
@@ -754,7 +820,7 @@ if "%%1" == "latexpdfja" (
\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
\tcd %%BUILDDIR%%/latex
\tmake all-pdf-ja
-\tcd %%BUILDDIR%%/..
+\tcd %%~dp0
\techo.
\techo.Build finished; the PDF files are in %%BUILDDIR%%/latex.
\tgoto end
@@ -818,6 +884,15 @@ results in %%BUILDDIR%%/doctest/output.txt.
\tgoto end
)
+if "%%1" == "coverage" (
+\t%%SPHINXBUILD%% -b coverage %%ALLSPHINXOPTS%% %%BUILDDIR%%/coverage
+\tif errorlevel 1 exit /b 1
+\techo.
+\techo.Testing of coverage in the sources finished, look at the ^
+results in %%BUILDDIR%%/coverage/python.txt.
+\tgoto end
+)
+
if "%%1" == "xml" (
\t%%SPHINXBUILD%% -b xml %%ALLSPHINXOPTS%% %%BUILDDIR%%/xml
\tif errorlevel 1 exit /b 1
@@ -918,16 +993,20 @@ def mkdir_p(dir):
class ValidationError(Exception):
"""Raised for validation errors."""
+
def is_path(x):
+ x = path.expanduser(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:
@@ -935,17 +1014,20 @@ def choice(*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
@@ -956,16 +1038,16 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default)
else:
prompt = PROMPT_PREFIX + text + ': '
- if sys.version_info < (3, 0):
+ if PY2:
# 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 '
+ print(turquoise('* Note: non-ASCII default value provided '
'and terminal encoding unknown -- assuming '
- 'UTF-8 or Latin-1.')
+ 'UTF-8 or Latin-1.'))
try:
prompt = prompt.encode('utf-8')
except UnicodeEncodeError:
@@ -974,29 +1056,29 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
x = term_input(prompt).strip()
if default and not x:
x = default
- if not isinstance(x, unicode):
+ if not isinstance(x, text_type):
# 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 '
+ print(turquoise('* Note: non-ASCII characters entered '
'and terminal encoding unknown -- assuming '
- 'UTF-8 or Latin-1.')
+ '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))
+ except ValidationError as err:
+ print(red('* ' + str(err)))
continue
break
d[key] = x
-if sys.version_info >= (3, 0):
+if PY3:
# remove Unicode literal prefixes
def _convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
return rex.sub('\\1', source)
@@ -1019,6 +1101,7 @@ def ask_user(d):
* author: author names
* version: version of project
* release: release of project
+ * language: document language
* suffix: source file suffix
* master: master document name
* epub: use epub (bool)
@@ -1027,98 +1110,110 @@ def ask_user(d):
* batchfile: make command file
"""
- print bold('Welcome to the Sphinx %s quickstart utility.') % __version__
- print '''
+ 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).'''
+accept a default value, if one is given in brackets).''')
if 'path' in d:
- print bold('''
-Selected root path: %s''' % d['path'])
+ print(bold('''
+Selected root path: %s''' % d['path']))
else:
- print '''
-Enter the root path for documentation.'''
+ 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
+ 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 '''
+ 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.'''
+"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 '''
+ 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.'''
+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.'''
+ 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 '''
+ 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.'''
+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 'language' not in d:
+ print('''
+If the documents are to be written in a language other than English,
+you can select a language here by its language code. Sphinx will then
+translate text that it generates into that language.
+
+For a list of supported codes, see
+http://sphinx-doc.org/config.html#confval-language.''')
+ do_prompt(d, 'language', 'Project language', 'en')
+ if d['language'] == 'en':
+ d['language'] = None
+
if 'suffix' not in d:
- print '''
+ print('''
The file name suffix for source files. Commonly, this is either ".txt"
-or ".rst". Only files with this suffix are considered documents.'''
+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 '''
+ 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.'''
+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
+ 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:'''
+ 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:'''
+ 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:
@@ -1140,8 +1235,8 @@ Please indicate if you want to use one of the following Sphinx extensions:'''
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.'''
+ 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 '
@@ -1150,16 +1245,20 @@ pngmath has been deselected.'''
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 '''
+ if 'no_makefile' in d:
+ d['makefile'] = False
+ elif '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.'''
+directly.''')
do_prompt(d, 'makefile', 'Create Makefile? (y/n)', 'y', boolean)
- if 'batchfile' not in d:
+ if 'no_batchfile' in d:
+ d['batchfile'] = False
+ elif 'batchfile' not in d:
do_prompt(d, 'batchfile', 'Create Windows command file? (y/n)',
'y', boolean)
- print
+ print()
def generate(d, overwrite=True, silent=False):
@@ -1179,19 +1278,18 @@ def generate(d, overwrite=True, silent=False):
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')
+ for name in EXTENSIONS
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['author_texescaped'] = text_type(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)
+ d['project_doc_texescaped'] = text_type(d['project'] + ' Documentation').\
+ translate(texescape.tex_escape_map)
# escape backslashes and single quotes in strings that are put into
# a Python string literal
@@ -1218,14 +1316,14 @@ def generate(d, overwrite=True, silent=False):
def write_file(fpath, content, newline=None):
if overwrite or not path.isfile(fpath):
- print 'Creating file %s.' % 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
+ print('File %s already exists, skipping.' % fpath)
conf_text = QUICKSTART_CONF % d
if d['epub']:
@@ -1238,22 +1336,22 @@ def generate(d, overwrite=True, silent=False):
masterfile = path.join(srcdir, d['master'] + d['suffix'])
write_file(masterfile, MASTER_FILE % d)
- if d['makefile']:
+ if d['makefile'] is True:
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']:
+ if d['batchfile'] is True:
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 '''
+ 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:
@@ -1263,23 +1361,144 @@ 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 usage(argv, msg=None):
+ if msg:
+ print(msg, file=sys.stderr)
+ print(file=sys.stderr)
+
+USAGE = """\
+Sphinx v%s
+Usage: %%prog [options] [projectdir]
+""" % __version__
+
+EPILOG = """\
+For more information, visit <http://sphinx-doc.org/>.
+"""
+
+
+class MyFormatter(optparse.IndentedHelpFormatter):
+ def format_usage(self, usage):
+ return usage
+
+ def format_help(self, formatter):
+ result = []
+ if self.description:
+ result.append(self.format_description(formatter))
+ if self.option_list:
+ result.append(self.format_option_help(formatter))
+ return "\n".join(result)
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]
+ parser = optparse.OptionParser(USAGE, epilog=EPILOG,
+ version='Sphinx v%s' % __version__,
+ formatter=MyFormatter())
+ parser.add_option('-q', '--quiet', action='store_true', dest='quiet',
+ default=False,
+ help='quiet mode')
+
+ group = parser.add_option_group('Structure options')
+ group.add_option('--sep', action='store_true', dest='sep',
+ help='if specified, separate source and build dirs')
+ group.add_option('--dot', metavar='DOT', dest='dot',
+ help='replacement for dot in _templates etc.')
+
+ group = parser.add_option_group('Project basic options')
+ group.add_option('-p', '--project', metavar='PROJECT', dest='project',
+ help='project name')
+ group.add_option('-a', '--author', metavar='AUTHOR', dest='author',
+ help='author names')
+ group.add_option('-v', metavar='VERSION', dest='version',
+ help='version of project')
+ group.add_option('-r', '--release', metavar='RELEASE', dest='release',
+ help='release of project')
+ group.add_option('-l', '--language', metavar='LANGUAGE', dest='language',
+ help='document language')
+ group.add_option('--suffix', metavar='SUFFIX', dest='suffix',
+ help='source file suffix')
+ group.add_option('--master', metavar='MASTER', dest='master',
+ help='master document name')
+ group.add_option('--epub', action='store_true', dest='epub',
+ default=False,
+ help='use epub')
+
+ group = parser.add_option_group('Extension options')
+ for ext in EXTENSIONS:
+ group.add_option('--ext-' + ext, action='store_true',
+ dest='ext_' + ext, default=False,
+ help='enable %s extension' % ext)
+
+ group = parser.add_option_group('Makefile and Batchfile creation')
+ group.add_option('--makefile', action='store_true', dest='makefile',
+ default=False,
+ help='create makefile')
+ group.add_option('--no-makefile', action='store_true', dest='no_makefile',
+ default=False,
+ help='not create makefile')
+ group.add_option('--batchfile', action='store_true', dest='batchfile',
+ default=False,
+ help='create batchfile')
+ group.add_option('--no-batchfile', action='store_true', dest='no_batchfile',
+ default=False,
+ help='not create batchfile')
+
+ # parse options
try:
- ask_user(d)
+ opts, args = parser.parse_args()
+ except SystemExit as err:
+ return err.code
+
+ if len(args) > 0:
+ opts.ensure_value('path', args[0])
+
+ d = vars(opts)
+ for k, v in d.items():
+ # delete None or False value
+ if v is None or v is False:
+ del d[k]
+
+ try:
+ if 'quiet' in d:
+ if 'project' not in d or 'author' not in d or \
+ 'version' not in d:
+ print('''"quiet" is specified, but any of "project", \
+"author" or "version" is not specified.''')
+ return
+
+ if all(['quiet' in d, 'project' in d, 'author' in d,
+ 'version' in d]):
+ # quiet mode with all required params satisfied, use default
+ d.setdefault('release', d['version'])
+ d2 = DEFAULT_VALUE.copy()
+ d2.update(dict(("ext_"+ext, False) for ext in EXTENSIONS))
+ d2.update(d)
+ d = d2
+ if 'no_makefile' in d:
+ d['makefile'] = False
+ if 'no_batchfile' in d:
+ d['batchfile'] = False
+
+ if path.exists(d['path']) and (
+ not path.isdir(d['path']) or os.listdir(d['path'])):
+ print()
+ print(bold('Error: specified path is not a directory, or not a'
+ ' empty directory.'))
+ print('sphinx-quickstart only generate into a empty directory.'
+ ' Please specify a new root path.')
+ return
+ else:
+ ask_user(d)
except (KeyboardInterrupt, EOFError):
- print
- print '[Interrupted.]'
+ print()
+ print('[Interrupted.]')
return
generate(d)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/sphinx/roles.py b/sphinx/roles.py
index c31ec055..451cfe60 100644
--- a/sphinx/roles.py
+++ b/sphinx/roles.py
@@ -11,34 +11,37 @@
import re
+from six import iteritems
from docutils import nodes, utils
from docutils.parsers.rst import roles
from sphinx import addnodes
from sphinx.locale import _
+from sphinx.errors import SphinxError
from sphinx.util import ws_re
from sphinx.util.nodes import split_explicit_title, process_index_entry, \
- set_role_source_info
+ 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,
+ 'command': addnodes.literal_strong,
+ 'dfn': nodes.emphasis,
+ 'kbd': nodes.literal,
+ 'mailheader': addnodes.literal_emphasis,
+ 'makevar': addnodes.literal_strong,
+ 'manpage': addnodes.literal_emphasis,
+ 'mimetype': addnodes.literal_emphasis,
+ 'newsgroup': addnodes.literal_emphasis,
+ 'program': addnodes.literal_strong, # XXX should be an x-ref
+ 'regexp': nodes.literal,
}
-for rolename, nodeclass in generic_docroles.iteritems():
+for rolename, nodeclass in iteritems(generic_docroles):
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):
@@ -95,7 +98,11 @@ class XRefRole(object):
options={}, content=[]):
env = inliner.document.settings.env
if not typ:
- typ = env.config.default_role
+ typ = env.temp_data.get('default_role')
+ if not typ:
+ typ = env.config.default_role
+ if not typ:
+ raise SphinxError('cannot determine default role!')
else:
typ = typ.lower()
if ':' not in typ:
@@ -157,7 +164,16 @@ class XRefRole(object):
return [node], []
-def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
+class AnyXRefRole(XRefRole):
+ def process_link(self, env, refnode, has_explicit_title, title, target):
+ result = XRefRole.process_link(self, env, refnode, has_explicit_title,
+ title, target)
+ # add all possible context info (i.e. std:program, py:module etc.)
+ refnode.attributes.update(env.ref_context)
+ return result
+
+
+def indexmarkup_role(typ, rawtext, text, lineno, inliner,
options={}, content=[]):
"""Role for PEP/RFC references that generate an index entry."""
env = inliner.document.settings.env
@@ -165,47 +181,53 @@ def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
typ = env.config.default_role
else:
typ = typ.lower()
- text = utils.unescape(etext)
+ has_explicit_title, title, target = split_explicit_title(text)
+ title = utils.unescape(title)
+ target = utils.unescape(target)
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,
+ ('single', _('Python Enhancement Proposals; PEP %s') % target,
targetid, '')]
anchor = ''
- anchorindex = text.find('#')
+ anchorindex = target.find('#')
if anchorindex > 0:
- text, anchor = text[:anchorindex], text[anchorindex:]
+ target, anchor = target[:anchorindex], target[anchorindex:]
+ if not has_explicit_title:
+ title = "PEP " + utils.unescape(title)
try:
- pepnum = int(text)
+ pepnum = int(target)
except ValueError:
- msg = inliner.reporter.error('invalid PEP number %s' % text,
+ msg = inliner.reporter.error('invalid PEP number %s' % target,
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)
+ sn = nodes.strong(title, title)
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, '')]
+ indexnode['entries'] = [('single', 'RFC; RFC %s' % target, targetid, '')]
anchor = ''
- anchorindex = text.find('#')
+ anchorindex = target.find('#')
if anchorindex > 0:
- text, anchor = text[:anchorindex], text[anchorindex:]
+ target, anchor = target[:anchorindex], target[anchorindex:]
+ if not has_explicit_title:
+ title = "RFC " + utils.unescape(title)
try:
- rfcnum = int(text)
+ rfcnum = int(target)
except ValueError:
- msg = inliner.reporter.error('invalid RFC number %s' % text,
+ msg = inliner.reporter.error('invalid RFC number %s' % target,
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)
+ sn = nodes.strong(title, title)
rn = nodes.reference('', '', internal=False, refuri=ref+anchor,
classes=[typ])
rn += sn
@@ -214,6 +236,7 @@ def indexmarkup_role(typ, rawtext, etext, lineno, inliner,
_amp_re = re.compile(r'(?<!&)&(?![&\s])')
+
def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
text = utils.unescape(text)
if typ == 'menuselection':
@@ -239,8 +262,10 @@ def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
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)
@@ -259,14 +284,17 @@ def emph_literal_role(typ, rawtext, text, lineno, inliner,
_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)], []
+ return [addnodes.abbreviation(text, text, **options)], []
abbr = text[:m.start()].strip()
expl = m.group(1)
- return [addnodes.abbreviation(abbr, abbr, explanation=expl)], []
+ options = options.copy()
+ options['explanation'] = expl
+ return [addnodes.abbreviation(abbr, abbr, **options)], []
def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
@@ -302,6 +330,8 @@ specific_docroles = {
'download': XRefRole(nodeclass=addnodes.download_reference),
# links to documents
'doc': XRefRole(warn_dangling=True),
+ # links to anything
+ 'any': AnyXRefRole(warn_dangling=True),
'pep': indexmarkup_role,
'rfc': indexmarkup_role,
@@ -313,5 +343,5 @@ specific_docroles = {
'index': index_role,
}
-for rolename, func in specific_docroles.iteritems():
+for rolename, func in iteritems(specific_docroles):
roles.register_local_role(rolename, func)
diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py
index d57efd9e..58b611a3 100644
--- a/sphinx/search/__init__.py
+++ b/sphinx/search/__init__.py
@@ -8,10 +8,10 @@
: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 six import iteritems, itervalues, text_type, string_types
+from six.moves import cPickle as pickle
from docutils.nodes import raw, comment, title, Text, NodeVisitor, SkipNode
from sphinx.util import jsdump, rpartition
@@ -40,6 +40,7 @@ class SearchLanguage(object):
type, before searching index. Default implementation does nothing.
"""
lang = None
+ language_name = None
stopwords = set()
js_stemmer_code = """
/**
@@ -89,16 +90,49 @@ var Stemmer = function() {
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())))
+ return (
+ len(word) == 0 or 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
+# SearchEnglish imported after SearchLanguage is defined due to circular import
+from sphinx.search.en import SearchEnglish
+
+def parse_stop_word(source):
+ """
+ parse snowball style word list like this:
+
+ * http://snowball.tartarus.org/algorithms/finnish/stop.txt
+ """
+ result = set()
+ for line in source.splitlines():
+ line = line.split('|')[0] # remove comment
+ result.update(line.split())
+ return result
+
+
+# maps language name to module.class or directly a class
languages = {
- 'en': en.SearchEnglish,
- 'ja': ja.SearchJapanese,
+ 'da': 'sphinx.search.da.SearchDanish',
+ 'de': 'sphinx.search.de.SearchGerman',
+ 'en': SearchEnglish,
+ 'es': 'sphinx.search.es.SearchSpanish',
+ 'fi': 'sphinx.search.fi.SearchFinnish',
+ 'fr': 'sphinx.search.fr.SearchFrench',
+ 'hu': 'sphinx.search.hu.SearchHungarian',
+ 'it': 'sphinx.search.it.SearchItalian',
+ 'ja': 'sphinx.search.ja.SearchJapanese',
+ 'nl': 'sphinx.search.nl.SearchDutch',
+ 'no': 'sphinx.search.no.SearchNorwegian',
+ 'pt': 'sphinx.search.pt.SearchPortuguese',
+ 'ro': 'sphinx.search.ro.SearchRomanian',
+ 'ru': 'sphinx.search.ru.SearchRussian',
+ 'sv': 'sphinx.search.sv.SearchSwedish',
+ 'tr': 'sphinx.search.tr.SearchTurkish',
}
@@ -186,7 +220,17 @@ class IndexBuilder(object):
# objtype index -> (domain, type, objname (localized))
self._objnames = {}
# add language-specific SearchLanguage instance
- self.lang = languages[lang](options)
+ lang_class = languages.get(lang)
+ if lang_class is None:
+ self.lang = SearchEnglish(options)
+ elif isinstance(lang_class, str):
+ module, classname = lang_class.rsplit('.', 1)
+ lang_class = getattr(__import__(module, None, None, [classname]),
+ classname)
+ self.lang = lang_class(options)
+ else:
+ # it's directly a class (e.g. added by app.add_search_language)
+ self.lang = lang_class(options)
if scoring:
with open(scoring, 'rb') as fp:
@@ -196,7 +240,7 @@ class IndexBuilder(object):
def load(self, stream, format):
"""Reconstruct from frozen data."""
- if isinstance(format, basestring):
+ if isinstance(format, string_types):
format = self.formats[format]
frozen = format.load(stream)
# if an old index is present, we treat it as not existing.
@@ -208,7 +252,7 @@ class IndexBuilder(object):
def load_terms(mapping):
rv = {}
- for k, v in mapping.iteritems():
+ for k, v in iteritems(mapping):
if isinstance(v, int):
rv[k] = set([index2fn[v]])
else:
@@ -221,7 +265,7 @@ class IndexBuilder(object):
def dump(self, stream, format):
"""Dump the frozen index to a stream."""
- if isinstance(format, basestring):
+ if isinstance(format, string_types):
format = self.formats[format]
format.dump(self.freeze(), stream)
@@ -229,7 +273,7 @@ class IndexBuilder(object):
rv = {}
otypes = self._objtypes
onames = self._objnames
- for domainname, domain in self.env.domains.iteritems():
+ for domainname, domain in iteritems(self.env.domains):
for fullname, dispname, type, docname, anchor, prio in \
domain.get_objects():
# XXX use dispname?
@@ -248,7 +292,7 @@ class IndexBuilder(object):
if otype:
# use unicode() to fire translation proxies
onames[typeindex] = (domainname, type,
- unicode(domain.get_type_name(otype)))
+ text_type(domain.get_type_name(otype)))
else:
onames[typeindex] = (domainname, type, type)
if anchor == fullname:
@@ -263,7 +307,7 @@ class IndexBuilder(object):
def get_terms(self, fn2index):
rvs = {}, {}
for rv, mapping in zip(rvs, (self._mapping, self._title_mapping)):
- for k, v in mapping.iteritems():
+ for k, v in iteritems(mapping):
if len(v) == 1:
fn, = v
if fn in fn2index:
@@ -274,19 +318,22 @@ class IndexBuilder(object):
def freeze(self):
"""Create a usable data structure for serializing."""
- filenames = self._titles.keys()
- titles = self._titles.values()
+ filenames = list(self._titles.keys())
+ titles = list(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())
+ for (k, v) in iteritems(self._objtypes))
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 label(self):
+ return "%s (code: %s)" % (self.lang.language_name, self.lang.lang)
+
def prune(self, filenames):
"""Remove data for all filenames not in the list."""
new_titles = {}
@@ -294,9 +341,9 @@ class IndexBuilder(object):
if filename in self._titles:
new_titles[filename] = self._titles[filename]
self._titles = new_titles
- for wordnames in self._mapping.itervalues():
+ for wordnames in itervalues(self._mapping):
wordnames.intersection_update(filenames)
- for wordnames in self._title_mapping.itervalues():
+ for wordnames in itervalues(self._title_mapping):
wordnames.intersection_update(filenames)
def feed(self, filename, title, doctree):
diff --git a/sphinx/search/da.py b/sphinx/search/da.py
new file mode 100644
index 00000000..755122b5
--- /dev/null
+++ b/sphinx/search/da.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.da
+ ~~~~~~~~~~~~~~~~
+
+ Danish search language: includes the JS Danish stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+danish_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/danish/stop.txt
+og | and
+i | in
+jeg | I
+det | that (dem. pronoun)/it (pers. pronoun)
+at | that (in front of a sentence)/to (with infinitive)
+en | a/an
+den | it (pers. pronoun)/that (dem. pronoun)
+til | to/at/for/until/against/by/of/into, more
+er | present tense of "to be"
+som | who, as
+på | on/upon/in/on/at/to/after/of/with/for, on
+de | they
+med | with/by/in, along
+han | he
+af | of/by/from/off/for/in/with/on, off
+for | at/for/to/from/by/of/ago, in front/before, because
+ikke | not
+der | who/which, there/those
+var | past tense of "to be"
+mig | me/myself
+sig | oneself/himself/herself/itself/themselves
+men | but
+et | a/an/one, one (number), someone/somebody/one
+har | present tense of "to have"
+om | round/about/for/in/a, about/around/down, if
+vi | we
+min | my
+havde | past tense of "to have"
+ham | him
+hun | she
+nu | now
+over | over/above/across/by/beyond/past/on/about, over/past
+da | then, when/as/since
+fra | from/off/since, off, since
+du | you
+ud | out
+sin | his/her/its/one's
+dem | them
+os | us/ourselves
+op | up
+man | you/one
+hans | his
+hvor | where
+eller | or
+hvad | what
+skal | must/shall etc.
+selv | myself/youself/herself/ourselves etc., even
+her | here
+alle | all/everyone/everybody etc.
+vil | will (verb)
+blev | past tense of "to stay/to remain/to get/to become"
+kunne | could
+ind | in
+når | when
+være | present tense of "to be"
+dog | however/yet/after all
+noget | something
+ville | would
+jo | you know/you see (adv), yes
+deres | their/theirs
+efter | after/behind/according to/for/by/from, later/afterwards
+ned | down
+skulle | should
+denne | this
+end | than
+dette | this
+mit | my/mine
+også | also
+under | under/beneath/below/during, below/underneath
+have | have
+dig | you
+anden | other
+hende | her
+mine | my
+alt | everything
+meget | much/very, plenty of
+sit | his, her, its, one's
+sine | his, her, its, one's
+vor | our
+mod | against
+disse | these
+hvis | if
+din | your/yours
+nogle | some
+hos | by/at
+blive | be/become
+mange | many
+ad | by/through
+bliver | present tense of "to be/to become"
+hendes | her/hers
+været | be
+thi | for (conj)
+jer | you
+sådan | such, like this/like that
+''')
+
+js_stemmer = u"""
+var JSX={};(function(g){function j(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function I(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function i(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function J(a,b,c){return a[b]=a[b]/c|0}var E=parseInt;var D=parseFloat;function K(a){return a!==a}var A=isFinite;var z=encodeURIComponent;var y=decodeURIComponent;var x=encodeURI;var w=decodeURI;var u=Object.prototype.toString;var C=Object.prototype.hasOwnProperty;function f(){}g.require=function(b){var a=p[b];return a!==undefined?a:null};g.profilerIsRunning=function(){return f.getResults!=null};g.getProfileResults=function(){return(f.getResults||function(){return{}})()};g.postProfileResults=function(a,b){if(f.postResults==null)throw new Error('profiler has not been turned on');return f.postResults(a,b)};g.resetProfileResults=function(){if(f.resetResults==null)throw new Error('profiler has not been turned on');return f.resetResults()};g.DEBUG=false;function t(){};j([t],Error);function b(a,b,c){this.G=a.length;this.S=a;this.V=b;this.J=c;this.I=null;this.W=null};j([b],Object);function l(){};j([l],Object);function d(){var a;var b;var c;this.F={};a=this.D='';b=this._=0;c=this.A=a.length;this.B=0;this.C=b;this.E=c};j([d],l);function v(a,b){a.D=b.D;a._=b._;a.A=b.A;a.B=b.B;a.C=b.C;a.E=b.E};function n(b,d,c,e){var a;if(b._>=b.A){return false}a=b.D.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function m(b,d,c,e){var a;if(b._<=b.B){return false}a=b.D.charCodeAt(b._-1);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._--;return true};function r(a,d,c,e){var b;if(a._>=a.A){return false}b=a.D.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function q(a,d,c,e){var b;if(a._<=a.B){return false}b=a.D.charCodeAt(a._-1);if(b>e||b<c){a._--;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._--;return true}return false};function h(a,b,d){var c;if(a._-a.B<b){return false}if(a.D.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function e(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.B;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.G-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.D.charCodeAt(e-1-c)-a.S.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.G){d._=e-a.G|0;if(a.I==null){return a.J}o=a.I(d);d._=e-a.G|0;if(o){return a.J}}b=a.V;if(b<0){return 0}}return-1};function s(a,b,d,e){var c;c=e.length-(d-b);a.D=a.D.slice(0,b)+e+a.D.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function c(a,f){var b;var c;var d;var e;b=false;if((c=a.C)<0||c>(d=a.E)||d>(e=a.A)||e>a.D.length?false:true){s(a,a.C,a.E,f);b=true}return b};function o(a,f){var b;var c;var d;var e;b='';if((c=a.C)<0||c>(d=a.E)||d>(e=a.A)||e>a.D.length?false:true){b=a.D.slice(a.C,a.E)}return b};d.prototype.H=function(){return false};d.prototype.T=function(b){var a;var c;var d;var e;a=this.F['.'+b];if(a==null){c=this.D=b;d=this._=0;e=this.A=c.length;this.B=0;this.C=d;this.E=e;this.H();a=this.D;this.F['.'+b]=a}return a};d.prototype.stemWord=d.prototype.T;d.prototype.U=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.F['.'+c];if(a==null){f=this.D=c;g=this._=0;h=this.A=f.length;this.B=0;this.C=g;this.E=h;this.H();a=this.D;this.F['.'+c]=a}d.push(a)}return d};d.prototype.stemWords=d.prototype.U;function a(){d.call(this);this.I_x=0;this.I_p1=0;this.S_ch=''};j([a],d);a.prototype.K=function(a){this.I_x=a.I_x;this.I_p1=a.I_p1;this.S_ch=a.S_ch;v(this,a)};a.prototype.copy_from=a.prototype.K;a.prototype.P=function(){var g;var d;var b;var e;var c;var f;var i;var j;var k;var h;this.I_p1=j=this.A;g=i=this._;b=i+3|0;if(0>b||b>j){return false}h=this._=b;this.I_x=h;this._=g;a:while(true){d=this._;e=true;b:while(e===true){e=false;if(!n(this,a.g_v,97,248)){break b}this._=d;break a}k=this._=d;if(k>=this.A){return false}this._++}a:while(true){c=true;b:while(c===true){c=false;if(!r(this,a.g_v,97,248)){break b}break a}if(this._>=this.A){return false}this._++}this.I_p1=this._;f=true;a:while(f===true){f=false;if(!(this.I_p1<this.I_x)){break a}this.I_p1=this.I_x}return true};a.prototype.r_mark_regions=a.prototype.P;function G(b){var h;var e;var c;var f;var d;var g;var j;var k;var l;var i;b.I_p1=k=b.A;h=j=b._;c=j+3|0;if(0>c||c>k){return false}i=b._=c;b.I_x=i;b._=h;a:while(true){e=b._;f=true;b:while(f===true){f=false;if(!n(b,a.g_v,97,248)){break b}b._=e;break a}l=b._=e;if(l>=b.A){return false}b._++}a:while(true){d=true;b:while(d===true){d=false;if(!r(b,a.g_v,97,248)){break b}break a}if(b._>=b.A){return false}b._++}b.I_p1=b._;g=true;a:while(g===true){g=false;if(!(b.I_p1<b.I_x)){break a}b.I_p1=b.I_x}return true};a.prototype.O=function(){var b;var f;var d;var g;var h;var i;f=this.A-(g=this._);if(g<this.I_p1){return false}h=this._=this.I_p1;d=this.B;this.B=h;i=this._=this.A-f;this.E=i;b=e(this,a.a_0,32);if(b===0){this.B=d;return false}this.C=this._;this.B=d;switch(b){case 0:return false;case 1:if(!c(this,'')){return false}break;case 2:if(!m(this,a.g_s_ending,97,229)){return false}if(!c(this,'')){return false}break}return true};a.prototype.r_main_suffix=a.prototype.O;function H(b){var d;var g;var f;var h;var i;var j;g=b.A-(h=b._);if(h<b.I_p1){return false}i=b._=b.I_p1;f=b.B;b.B=i;j=b._=b.A-g;b.E=j;d=e(b,a.a_0,32);if(d===0){b.B=f;return false}b.C=b._;b.B=f;switch(d){case 0:return false;case 1:if(!c(b,'')){return false}break;case 2:if(!m(b,a.g_s_ending,97,229)){return false}if(!c(b,'')){return false}break}return true};a.prototype.N=function(){var f;var g;var b;var h;var d;var i;var j;var k;var l;f=(h=this.A)-(d=this._);g=h-d;if(d<this.I_p1){return false}i=this._=this.I_p1;b=this.B;this.B=i;j=this._=this.A-g;this.E=j;if(e(this,a.a_1,4)===0){this.B=b;return false}this.C=this._;l=this.B=b;k=this._=this.A-f;if(k<=l){return false}this._--;this.C=this._;return!c(this,'')?false:true};a.prototype.r_consonant_pair=a.prototype.N;function k(b){var i;var j;var d;var g;var f;var k;var l;var m;var h;i=(g=b.A)-(f=b._);j=g-f;if(f<b.I_p1){return false}k=b._=b.I_p1;d=b.B;b.B=k;l=b._=b.A-j;b.E=l;if(e(b,a.a_1,4)===0){b.B=d;return false}b.C=b._;h=b.B=d;m=b._=b.A-i;if(m<=h){return false}b._--;b.C=b._;return!c(b,'')?false:true};a.prototype.Q=function(){var f;var l;var m;var d;var j;var b;var g;var n;var i;var p;var o;l=this.A-this._;b=true;a:while(b===true){b=false;this.E=this._;if(!h(this,2,'st')){break a}this.C=this._;if(!h(this,2,'ig')){break a}if(!c(this,'')){return false}}i=this._=(n=this.A)-l;m=n-i;if(i<this.I_p1){return false}p=this._=this.I_p1;d=this.B;this.B=p;o=this._=this.A-m;this.E=o;f=e(this,a.a_2,5);if(f===0){this.B=d;return false}this.C=this._;this.B=d;switch(f){case 0:return false;case 1:if(!c(this,'')){return false}j=this.A-this._;g=true;a:while(g===true){g=false;if(!k(this)){break a}}this._=this.A-j;break;case 2:if(!c(this,'løs')){return false}break}return true};a.prototype.r_other_suffix=a.prototype.Q;function F(b){var d;var p;var m;var f;var l;var g;var i;var o;var j;var q;var n;p=b.A-b._;g=true;a:while(g===true){g=false;b.E=b._;if(!h(b,2,'st')){break a}b.C=b._;if(!h(b,2,'ig')){break a}if(!c(b,'')){return false}}j=b._=(o=b.A)-p;m=o-j;if(j<b.I_p1){return false}q=b._=b.I_p1;f=b.B;b.B=q;n=b._=b.A-m;b.E=n;d=e(b,a.a_2,5);if(d===0){b.B=f;return false}b.C=b._;b.B=f;switch(d){case 0:return false;case 1:if(!c(b,'')){return false}l=b.A-b._;i=true;a:while(i===true){i=false;if(!k(b)){break a}}b._=b.A-l;break;case 2:if(!c(b,'løs')){return false}break}return true};a.prototype.R=function(){var e;var b;var d;var f;var g;var i;var j;e=this.A-(f=this._);if(f<this.I_p1){return false}g=this._=this.I_p1;b=this.B;this.B=g;i=this._=this.A-e;this.E=i;if(!q(this,a.g_v,97,248)){this.B=b;return false}this.C=this._;j=this.S_ch=o(this,this.S_ch);if(j===''){return false}this.B=b;return!(d=this.S_ch,h(this,d.length,d))?false:!c(this,'')?false:true};a.prototype.r_undouble=a.prototype.R;function B(b){var f;var d;var e;var g;var i;var j;var k;f=b.A-(g=b._);if(g<b.I_p1){return false}i=b._=b.I_p1;d=b.B;b.B=i;j=b._=b.A-f;b.E=j;if(!q(b,a.g_v,97,248)){b.B=d;return false}b.C=b._;k=b.S_ch=o(b,b.S_ch);if(k===''){return false}b.B=d;return!(e=b.S_ch,h(b,e.length,e))?false:!c(b,'')?false:true};a.prototype.H=function(){var i;var g;var h;var j;var b;var c;var d;var a;var e;var l;var m;var n;var o;var p;var q;var f;i=this._;b=true;a:while(b===true){b=false;if(!G(this)){break a}}l=this._=i;this.B=l;n=this._=m=this.A;g=m-n;c=true;a:while(c===true){c=false;if(!H(this)){break a}}p=this._=(o=this.A)-g;h=o-p;d=true;a:while(d===true){d=false;if(!k(this)){break a}}f=this._=(q=this.A)-h;j=q-f;a=true;a:while(a===true){a=false;if(!F(this)){break a}}this._=this.A-j;e=true;a:while(e===true){e=false;if(!B(this)){break a}}this._=this.B;return true};a.prototype.stem=a.prototype.H;a.prototype.L=function(b){return b instanceof a};a.prototype.equals=a.prototype.L;a.prototype.M=function(){var c;var a;var b;var d;c='DanishStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};a.prototype.hashCode=a.prototype.M;a.serialVersionUID=1;i(a,'methodObject',function(){return new a});i(a,'a_0',function(){return[new b('hed',-1,1),new b('ethed',0,1),new b('ered',-1,1),new b('e',-1,1),new b('erede',3,1),new b('ende',3,1),new b('erende',5,1),new b('ene',3,1),new b('erne',3,1),new b('ere',3,1),new b('en',-1,1),new b('heden',10,1),new b('eren',10,1),new b('er',-1,1),new b('heder',13,1),new b('erer',13,1),new b('s',-1,2),new b('heds',16,1),new b('es',16,1),new b('endes',18,1),new b('erendes',19,1),new b('enes',18,1),new b('ernes',18,1),new b('eres',18,1),new b('ens',16,1),new b('hedens',24,1),new b('erens',24,1),new b('ers',16,1),new b('ets',16,1),new b('erets',28,1),new b('et',-1,1),new b('eret',30,1)]});i(a,'a_1',function(){return[new b('gd',-1,-1),new b('dt',-1,-1),new b('gt',-1,-1),new b('kt',-1,-1)]});i(a,'a_2',function(){return[new b('ig',-1,1),new b('lig',0,1),new b('elig',1,1),new b('els',-1,1),new b('løst',-1,2)]});i(a,'g_v',function(){return[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128]});i(a,'g_s_ending',function(){return[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16]});var p={'src/stemmer.jsx':{Stemmer:l},'src/danish-stemmer.jsx':{DanishStemmer:a}}}(JSX))
+var Stemmer = JSX.require("src/danish-stemmer.jsx").DanishStemmer;
+"""
+
+
+class SearchDanish(SearchLanguage):
+ lang = 'da'
+ language_name = 'Danish'
+ js_stemmer_code = js_stemmer
+ stopwords = danish_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('danish')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/de.py b/sphinx/search/de.py
new file mode 100644
index 00000000..b46c7dd3
--- /dev/null
+++ b/sphinx/search/de.py
@@ -0,0 +1,313 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.de
+ ~~~~~~~~~~~~~~~~
+
+ German search language: includes the JS German stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+german_stopwords = parse_stop_word(u'''
+|source: http://snowball.tartarus.org/algorithms/german/stop.txt
+aber | but
+
+alle | all
+allem
+allen
+aller
+alles
+
+als | than, as
+also | so
+am | an + dem
+an | at
+
+ander | other
+andere
+anderem
+anderen
+anderer
+anderes
+anderm
+andern
+anderr
+anders
+
+auch | also
+auf | on
+aus | out of
+bei | by
+bin | am
+bis | until
+bist | art
+da | there
+damit | with it
+dann | then
+
+der | the
+den
+des
+dem
+die
+das
+
+daß | that
+
+derselbe | the same
+derselben
+denselben
+desselben
+demselben
+dieselbe
+dieselben
+dasselbe
+
+dazu | to that
+
+dein | thy
+deine
+deinem
+deinen
+deiner
+deines
+
+denn | because
+
+derer | of those
+dessen | of him
+
+dich | thee
+dir | to thee
+du | thou
+
+dies | this
+diese
+diesem
+diesen
+dieser
+dieses
+
+
+doch | (several meanings)
+dort | (over) there
+
+
+durch | through
+
+ein | a
+eine
+einem
+einen
+einer
+eines
+
+einig | some
+einige
+einigem
+einigen
+einiger
+einiges
+
+einmal | once
+
+er | he
+ihn | him
+ihm | to him
+
+es | it
+etwas | something
+
+euer | your
+eure
+eurem
+euren
+eurer
+eures
+
+für | for
+gegen | towards
+gewesen | p.p. of sein
+hab | have
+habe | have
+haben | have
+hat | has
+hatte | had
+hatten | had
+hier | here
+hin | there
+hinter | behind
+
+ich | I
+mich | me
+mir | to me
+
+
+ihr | you, to her
+ihre
+ihrem
+ihren
+ihrer
+ihres
+euch | to you
+
+im | in + dem
+in | in
+indem | while
+ins | in + das
+ist | is
+
+jede | each, every
+jedem
+jeden
+jeder
+jedes
+
+jene | that
+jenem
+jenen
+jener
+jenes
+
+jetzt | now
+kann | can
+
+kein | no
+keine
+keinem
+keinen
+keiner
+keines
+
+können | can
+könnte | could
+machen | do
+man | one
+
+manche | some, many a
+manchem
+manchen
+mancher
+manches
+
+mein | my
+meine
+meinem
+meinen
+meiner
+meines
+
+mit | with
+muss | must
+musste | had to
+nach | to(wards)
+nicht | not
+nichts | nothing
+noch | still, yet
+nun | now
+nur | only
+ob | whether
+oder | or
+ohne | without
+sehr | very
+
+sein | his
+seine
+seinem
+seinen
+seiner
+seines
+
+selbst | self
+sich | herself
+
+sie | they, she
+ihnen | to them
+
+sind | are
+so | so
+
+solche | such
+solchem
+solchen
+solcher
+solches
+
+soll | shall
+sollte | should
+sondern | but
+sonst | else
+über | over
+um | about, around
+und | and
+
+uns | us
+unse
+unsem
+unsen
+unser
+unses
+
+unter | under
+viel | much
+vom | von + dem
+von | from
+vor | before
+während | while
+war | was
+waren | were
+warst | wast
+was | what
+weg | away, off
+weil | because
+weiter | further
+
+welche | which
+welchem
+welchen
+welcher
+welches
+
+wenn | when
+werde | will
+werden | will
+wie | how
+wieder | again
+will | want
+wir | we
+wird | will
+wirst | willst
+wo | where
+wollen | want
+wollte | wanted
+würde | would
+würden | would
+zu | to
+zum | zu + dem
+zur | zu + der
+zwar | indeed
+zwischen | between
+''')
+
+js_stemmer = u"""
+var JSX={};(function(j){function l(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function H(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function g(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function I(a,b,c){return a[b]=a[b]/c|0}var C=parseInt;var r=parseFloat;function J(a){return a!==a}var z=isFinite;var y=encodeURIComponent;var x=decodeURIComponent;var w=encodeURI;var u=decodeURI;var t=Object.prototype.toString;var B=Object.prototype.hasOwnProperty;function i(){}j.require=function(b){var a=q[b];return a!==undefined?a:null};j.profilerIsRunning=function(){return i.getResults!=null};j.getProfileResults=function(){return(i.getResults||function(){return{}})()};j.postProfileResults=function(a,b){if(i.postResults==null)throw new Error('profiler has not been turned on');return i.postResults(a,b)};j.resetProfileResults=function(){if(i.resetResults==null)throw new Error('profiler has not been turned on');return i.resetResults()};j.DEBUG=false;function s(){};l([s],Error);function c(a,b,c){this.F=a.length;this.K=a;this.L=b;this.I=c;this.H=null;this.P=null};l([c],Object);function o(){};l([o],Object);function e(){var a;var b;var c;this.G={};a=this.D='';b=this._=0;c=this.A=a.length;this.E=0;this.C=b;this.B=c};l([e],o);function v(a,b){a.D=b.D;a._=b._;a.A=b.A;a.E=b.E;a.C=b.C;a.B=b.B};function f(b,d,c,e){var a;if(b._>=b.A){return false}a=b.D.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function m(b,d,c,e){var a;if(b._<=b.E){return false}a=b.D.charCodeAt(b._-1);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._--;return true};function n(a,d,c,e){var b;if(a._>=a.A){return false}b=a.D.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function k(a,b,d){var c;if(a.A-a._<b){return false}if(a.D.slice(c=a._,c+b)!==d){return false}a._+=b;return true};function d(a,b,d){var c;if(a._-a.E<b){return false}if(a.D.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function p(f,m,p){var b;var d;var e;var n;var g;var k;var l;var i;var h;var c;var a;var j;var o;b=0;d=p;e=f._;n=f.A;g=0;k=0;l=false;while(true){i=b+(d-b>>>1);h=0;c=g<k?g:k;a=m[i];for(j=c;j<a.F;j++){if(e+c===n){h=-1;break}h=f.D.charCodeAt(e+c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){d=i;k=c}else{b=i;g=c}if(d-b<=1){if(b>0){break}if(d===b){break}if(l){break}l=true}}while(true){a=m[b];if(g>=a.F){f._=e+a.F|0;if(a.H==null){return a.I}o=a.H(a.P);f._=e+a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function h(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.E;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.F-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.D.charCodeAt(e-1-c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.F){d._=e-a.F|0;if(a.H==null){return a.I}o=a.H(d);d._=e-a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function D(a,b,d,e){var c;c=e.length-(d-b);a.D=a.D.slice(0,b)+e+a.D.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function b(a,f){var b;var c;var d;var e;b=false;if((c=a.C)<0||c>(d=a.B)||d>(e=a.A)||e>a.D.length?false:true){D(a,a.C,a.B,f);b=true}return b};e.prototype.J=function(){return false};e.prototype.W=function(b){var a;var c;var d;var e;a=this.G['.'+b];if(a==null){c=this.D=b;d=this._=0;e=this.A=c.length;this.E=0;this.C=d;this.B=e;this.J();a=this.D;this.G['.'+b]=a}return a};e.prototype.stemWord=e.prototype.W;e.prototype.X=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.G['.'+c];if(a==null){f=this.D=c;g=this._=0;h=this.A=f.length;this.E=0;this.C=g;this.B=h;this.J();a=this.D;this.G['.'+c]=a}d.push(a)}return d};e.prototype.stemWords=e.prototype.X;function a(){e.call(this);this.I_x=0;this.I_p2=0;this.I_p1=0};l([a],e);a.prototype.M=function(a){this.I_x=a.I_x;this.I_p2=a.I_p2;this.I_p1=a.I_p1;v(this,a)};a.prototype.copy_from=a.prototype.M;a.prototype.U=function(){var m;var r;var n;var o;var d;var q;var e;var c;var g;var h;var i;var j;var l;var s;var p;m=this._;a:while(true){r=this._;e=true;b:while(e===true){e=false;c=true;c:while(c===true){c=false;n=this._;g=true;d:while(g===true){g=false;this.C=this._;if(!k(this,1,'ß')){break d}this.B=this._;if(!b(this,'ss')){return false}break c}s=this._=n;if(s>=this.A){break b}this._++}continue a}this._=r;break a}this._=m;b:while(true){o=this._;h=true;d:while(h===true){h=false;e:while(true){d=this._;i=true;a:while(i===true){i=false;if(!f(this,a.g_v,97,252)){break a}this.C=this._;j=true;f:while(j===true){j=false;q=this._;l=true;c:while(l===true){l=false;if(!k(this,1,'u')){break c}this.B=this._;if(!f(this,a.g_v,97,252)){break c}if(!b(this,'U')){return false}break f}this._=q;if(!k(this,1,'y')){break a}this.B=this._;if(!f(this,a.g_v,97,252)){break a}if(!b(this,'Y')){return false}}this._=d;break e}p=this._=d;if(p>=this.A){break d}this._++}continue b}this._=o;break b}return true};a.prototype.r_prelude=a.prototype.U;function G(c){var s;var n;var o;var p;var e;var r;var d;var g;var h;var i;var j;var l;var m;var t;var q;s=c._;a:while(true){n=c._;d=true;b:while(d===true){d=false;g=true;c:while(g===true){g=false;o=c._;h=true;d:while(h===true){h=false;c.C=c._;if(!k(c,1,'ß')){break d}c.B=c._;if(!b(c,'ss')){return false}break c}t=c._=o;if(t>=c.A){break b}c._++}continue a}c._=n;break a}c._=s;b:while(true){p=c._;i=true;d:while(i===true){i=false;e:while(true){e=c._;j=true;a:while(j===true){j=false;if(!f(c,a.g_v,97,252)){break a}c.C=c._;l=true;f:while(l===true){l=false;r=c._;m=true;c:while(m===true){m=false;if(!k(c,1,'u')){break c}c.B=c._;if(!f(c,a.g_v,97,252)){break c}if(!b(c,'U')){return false}break f}c._=r;if(!k(c,1,'y')){break a}c.B=c._;if(!f(c,a.g_v,97,252)){break a}if(!b(c,'Y')){return false}}c._=e;break e}q=c._=e;if(q>=c.A){break d}c._++}continue b}c._=p;break b}return true};a.prototype.S=function(){var j;var b;var d;var e;var c;var g;var h;var i;var l;var k;this.I_p1=i=this.A;this.I_p2=i;j=l=this._;b=l+3|0;if(0>b||b>i){return false}k=this._=b;this.I_x=k;this._=j;a:while(true){d=true;b:while(d===true){d=false;if(!f(this,a.g_v,97,252)){break b}break a}if(this._>=this.A){return false}this._++}a:while(true){e=true;b:while(e===true){e=false;if(!n(this,a.g_v,97,252)){break b}break a}if(this._>=this.A){return false}this._++}this.I_p1=this._;c=true;a:while(c===true){c=false;if(!(this.I_p1<this.I_x)){break a}this.I_p1=this.I_x}a:while(true){g=true;b:while(g===true){g=false;if(!f(this,a.g_v,97,252)){break b}break a}if(this._>=this.A){return false}this._++}a:while(true){h=true;b:while(h===true){h=false;if(!n(this,a.g_v,97,252)){break b}break a}if(this._>=this.A){return false}this._++}this.I_p2=this._;return true};a.prototype.r_mark_regions=a.prototype.S;function F(b){var k;var c;var e;var g;var d;var h;var i;var j;var m;var l;b.I_p1=j=b.A;b.I_p2=j;k=m=b._;c=m+3|0;if(0>c||c>j){return false}l=b._=c;b.I_x=l;b._=k;a:while(true){e=true;b:while(e===true){e=false;if(!f(b,a.g_v,97,252)){break b}break a}if(b._>=b.A){return false}b._++}a:while(true){g=true;b:while(g===true){g=false;if(!n(b,a.g_v,97,252)){break b}break a}if(b._>=b.A){return false}b._++}b.I_p1=b._;d=true;a:while(d===true){d=false;if(!(b.I_p1<b.I_x)){break a}b.I_p1=b.I_x}a:while(true){h=true;b:while(h===true){h=false;if(!f(b,a.g_v,97,252)){break b}break a}if(b._>=b.A){return false}b._++}a:while(true){i=true;b:while(i===true){i=false;if(!n(b,a.g_v,97,252)){break b}break a}if(b._>=b.A){return false}b._++}b.I_p2=b._;return true};a.prototype.T=function(){var c;var e;var d;b:while(true){e=this._;d=true;a:while(d===true){d=false;this.C=this._;c=p(this,a.a_0,6);if(c===0){break a}this.B=this._;switch(c){case 0:break a;case 1:if(!b(this,'y')){return false}break;case 2:if(!b(this,'u')){return false}break;case 3:if(!b(this,'a')){return false}break;case 4:if(!b(this,'o')){return false}break;case 5:if(!b(this,'u')){return false}break;case 6:if(this._>=this.A){break a}this._++;break}continue b}this._=e;break b}return true};a.prototype.r_postlude=a.prototype.T;function E(c){var d;var f;var e;b:while(true){f=c._;e=true;a:while(e===true){e=false;c.C=c._;d=p(c,a.a_0,6);if(d===0){break a}c.B=c._;switch(d){case 0:break a;case 1:if(!b(c,'y')){return false}break;case 2:if(!b(c,'u')){return false}break;case 3:if(!b(c,'a')){return false}break;case 4:if(!b(c,'o')){return false}break;case 5:if(!b(c,'u')){return false}break;case 6:if(c._>=c.A){break a}c._++;break}continue b}c._=f;break b}return true};a.prototype.Q=function(){return!(this.I_p1<=this._)?false:true};a.prototype.r_R1=a.prototype.Q;a.prototype.R=function(){return!(this.I_p2<=this._)?false:true};a.prototype.r_R2=a.prototype.R;a.prototype.V=function(){var c;var z;var n;var x;var y;var f;var A;var B;var p;var w;var g;var j;var k;var l;var e;var o;var i;var q;var r;var s;var t;var u;var v;var D;var E;var F;var G;var H;var I;var J;var K;var L;var M;var C;z=this.A-this._;j=true;a:while(j===true){j=false;this.B=this._;c=h(this,a.a_1,7);if(c===0){break a}this.C=D=this._;if(!(!(this.I_p1<=D)?false:true)){break a}switch(c){case 0:break a;case 1:if(!b(this,'')){return false}break;case 2:if(!b(this,'')){return false}n=this.A-this._;k=true;b:while(k===true){k=false;this.B=this._;if(!d(this,1,'s')){this._=this.A-n;break b}this.C=this._;if(!d(this,3,'nis')){this._=this.A-n;break b}if(!b(this,'')){return false}}break;case 3:if(!m(this,a.g_s_ending,98,116)){break a}if(!b(this,'')){return false}break}}G=this._=(F=this.A)-z;x=F-G;l=true;a:while(l===true){l=false;this.B=this._;c=h(this,a.a_2,4);if(c===0){break a}this.C=E=this._;if(!(!(this.I_p1<=E)?false:true)){break a}switch(c){case 0:break a;case 1:if(!b(this,'')){return false}break;case 2:if(!m(this,a.g_st_ending,98,116)){break a}e=this._-3|0;if(this.E>e||e>this.A){break a}this._=e;if(!b(this,'')){return false}break}}C=this._=(M=this.A)-x;y=M-C;o=true;a:while(o===true){o=false;this.B=this._;c=h(this,a.a_4,8);if(c===0){break a}this.C=H=this._;if(!(!(this.I_p2<=H)?false:true)){break a}switch(c){case 0:break a;case 1:if(!b(this,'')){return false}f=this.A-this._;i=true;b:while(i===true){i=false;this.B=this._;if(!d(this,2,'ig')){this._=this.A-f;break b}this.C=I=this._;A=this.A-I;q=true;c:while(q===true){q=false;if(!d(this,1,'e')){break c}this._=this.A-f;break b}J=this._=this.A-A;if(!(!(this.I_p2<=J)?false:true)){this._=this.A-f;break b}if(!b(this,'')){return false}}break;case 2:B=this.A-this._;r=true;b:while(r===true){r=false;if(!d(this,1,'e')){break b}break a}this._=this.A-B;if(!b(this,'')){return false}break;case 3:if(!b(this,'')){return false}p=this.A-this._;s=true;b:while(s===true){s=false;this.B=this._;t=true;c:while(t===true){t=false;w=this.A-this._;u=true;d:while(u===true){u=false;if(!d(this,2,'er')){break d}break c}this._=this.A-w;if(!d(this,2,'en')){this._=this.A-p;break b}}this.C=K=this._;if(!(!(this.I_p1<=K)?false:true)){this._=this.A-p;break b}if(!b(this,'')){return false}}break;case 4:if(!b(this,'')){return false}g=this.A-this._;v=true;b:while(v===true){v=false;this.B=this._;c=h(this,a.a_3,2);if(c===0){this._=this.A-g;break b}this.C=L=this._;if(!(!(this.I_p2<=L)?false:true)){this._=this.A-g;break b}switch(c){case 0:this._=this.A-g;break b;case 1:if(!b(this,'')){return false}break}}break}}this._=this.A-y;return true};a.prototype.r_standard_suffix=a.prototype.V;function A(c){var e;var A;var j;var y;var z;var g;var B;var C;var q;var x;var i;var k;var l;var n;var f;var p;var o;var r;var s;var t;var u;var v;var w;var E;var F;var G;var H;var I;var J;var K;var L;var M;var N;var D;A=c.A-c._;k=true;a:while(k===true){k=false;c.B=c._;e=h(c,a.a_1,7);if(e===0){break a}c.C=E=c._;if(!(!(c.I_p1<=E)?false:true)){break a}switch(e){case 0:break a;case 1:if(!b(c,'')){return false}break;case 2:if(!b(c,'')){return false}j=c.A-c._;l=true;b:while(l===true){l=false;c.B=c._;if(!d(c,1,'s')){c._=c.A-j;break b}c.C=c._;if(!d(c,3,'nis')){c._=c.A-j;break b}if(!b(c,'')){return false}}break;case 3:if(!m(c,a.g_s_ending,98,116)){break a}if(!b(c,'')){return false}break}}H=c._=(G=c.A)-A;y=G-H;n=true;a:while(n===true){n=false;c.B=c._;e=h(c,a.a_2,4);if(e===0){break a}c.C=F=c._;if(!(!(c.I_p1<=F)?false:true)){break a}switch(e){case 0:break a;case 1:if(!b(c,'')){return false}break;case 2:if(!m(c,a.g_st_ending,98,116)){break a}f=c._-3|0;if(c.E>f||f>c.A){break a}c._=f;if(!b(c,'')){return false}break}}D=c._=(N=c.A)-y;z=N-D;p=true;a:while(p===true){p=false;c.B=c._;e=h(c,a.a_4,8);if(e===0){break a}c.C=I=c._;if(!(!(c.I_p2<=I)?false:true)){break a}switch(e){case 0:break a;case 1:if(!b(c,'')){return false}g=c.A-c._;o=true;b:while(o===true){o=false;c.B=c._;if(!d(c,2,'ig')){c._=c.A-g;break b}c.C=J=c._;B=c.A-J;r=true;c:while(r===true){r=false;if(!d(c,1,'e')){break c}c._=c.A-g;break b}K=c._=c.A-B;if(!(!(c.I_p2<=K)?false:true)){c._=c.A-g;break b}if(!b(c,'')){return false}}break;case 2:C=c.A-c._;s=true;b:while(s===true){s=false;if(!d(c,1,'e')){break b}break a}c._=c.A-C;if(!b(c,'')){return false}break;case 3:if(!b(c,'')){return false}q=c.A-c._;t=true;b:while(t===true){t=false;c.B=c._;u=true;c:while(u===true){u=false;x=c.A-c._;v=true;d:while(v===true){v=false;if(!d(c,2,'er')){break d}break c}c._=c.A-x;if(!d(c,2,'en')){c._=c.A-q;break b}}c.C=L=c._;if(!(!(c.I_p1<=L)?false:true)){c._=c.A-q;break b}if(!b(c,'')){return false}}break;case 4:if(!b(c,'')){return false}i=c.A-c._;w=true;b:while(w===true){w=false;c.B=c._;e=h(c,a.a_3,2);if(e===0){c._=c.A-i;break b}c.C=M=c._;if(!(!(c.I_p2<=M)?false:true)){c._=c.A-i;break b}switch(e){case 0:c._=c.A-i;break b;case 1:if(!b(c,'')){return false}break}}break}}c._=c.A-z;return true};a.prototype.J=function(){var f;var g;var h;var b;var a;var c;var d;var i;var j;var e;f=this._;b=true;a:while(b===true){b=false;if(!G(this)){break a}}i=this._=f;g=i;a=true;a:while(a===true){a=false;if(!F(this)){break a}}j=this._=g;this.E=j;this._=this.A;c=true;a:while(c===true){c=false;if(!A(this)){break a}}e=this._=this.E;h=e;d=true;a:while(d===true){d=false;if(!E(this)){break a}}this._=h;return true};a.prototype.stem=a.prototype.J;a.prototype.N=function(b){return b instanceof a};a.prototype.equals=a.prototype.N;a.prototype.O=function(){var c;var a;var b;var d;c='GermanStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};a.prototype.hashCode=a.prototype.O;a.serialVersionUID=1;g(a,'methodObject',function(){return new a});g(a,'a_0',function(){return[new c('',-1,6),new c('U',0,2),new c('Y',0,1),new c('ä',0,3),new c('ö',0,4),new c('ü',0,5)]});g(a,'a_1',function(){return[new c('e',-1,2),new c('em',-1,1),new c('en',-1,2),new c('ern',-1,1),new c('er',-1,1),new c('s',-1,3),new c('es',5,2)]});g(a,'a_2',function(){return[new c('en',-1,1),new c('er',-1,1),new c('st',-1,2),new c('est',2,1)]});g(a,'a_3',function(){return[new c('ig',-1,1),new c('lich',-1,1)]});g(a,'a_4',function(){return[new c('end',-1,1),new c('ig',-1,2),new c('ung',-1,1),new c('lich',-1,3),new c('isch',-1,2),new c('ik',-1,2),new c('heit',-1,3),new c('keit',-1,4)]});g(a,'g_v',function(){return[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8]});g(a,'g_s_ending',function(){return[117,30,5]});g(a,'g_st_ending',function(){return[117,30,4]});var q={'src/stemmer.jsx':{Stemmer:o},'src/german-stemmer.jsx':{GermanStemmer:a}}}(JSX))
+var Stemmer = JSX.require("src/german-stemmer.jsx").GermanStemmer;
+"""
+
+
+class SearchGerman(SearchLanguage):
+ lang = 'de'
+ language_name = 'German'
+ js_stemmer_code = js_stemmer
+ stopwords = german_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('german')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/en.py b/sphinx/search/en.py
index 33e81770..3e7aadd3 100644
--- a/sphinx/search/en.py
+++ b/sphinx/search/en.py
@@ -15,10 +15,15 @@ try:
# http://bitbucket.org/methane/porterstemmer/
from porterstemmer import Stemmer as CStemmer
CSTEMMER = True
+ PYSTEMMER = False
except ImportError:
- from sphinx.util.stemmer import PorterStemmer
CSTEMMER = False
-
+ try:
+ from Stemmer import Stemmer as PyStemmer
+ PYSTEMMER = True
+ except ImportError:
+ from sphinx.util.stemmer import PorterStemmer
+ PYSTEMMER = False
english_stopwords = set("""
a and are as at
@@ -221,6 +226,7 @@ iti|ous|ive|ize)$/;
class SearchEnglish(SearchLanguage):
lang = 'en'
+ language_name = 'English'
js_stemmer_code = js_porter_stemmer
stopwords = english_stopwords
@@ -229,6 +235,13 @@ class SearchEnglish(SearchLanguage):
class Stemmer(CStemmer):
def stem(self, word):
return self(word.lower())
+ elif PYSTEMMER:
+ class Stemmer(object):
+ def __init__(self):
+ self.stemmer = PyStemmer('porter')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
else:
class Stemmer(PorterStemmer):
"""All those porter stemmer implementations look hideous;
diff --git a/sphinx/search/es.py b/sphinx/search/es.py
new file mode 100644
index 00000000..659d00fb
--- /dev/null
+++ b/sphinx/search/es.py
@@ -0,0 +1,373 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.es
+ ~~~~~~~~~~~~~~~~
+
+ Spanish search language: includes the JS Spanish stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+spanish_stopwords = parse_stop_word(u'''
+|source: http://snowball.tartarus.org/algorithms/spanish/stop.txt
+de | from, of
+la | the, her
+que | who, that
+el | the
+en | in
+y | and
+a | to
+los | the, them
+del | de + el
+se | himself, from him etc
+las | the, them
+por | for, by, etc
+un | a
+para | for
+con | with
+no | no
+una | a
+su | his, her
+al | a + el
+ | es from SER
+lo | him
+como | how
+más | more
+pero | pero
+sus | su plural
+le | to him, her
+ya | already
+o | or
+ | fue from SER
+este | this
+ | ha from HABER
+sí | himself etc
+porque | because
+esta | this
+ | son from SER
+entre | between
+ | está from ESTAR
+cuando | when
+muy | very
+sin | without
+sobre | on
+ | ser from SER
+ | tiene from TENER
+también | also
+me | me
+hasta | until
+hay | there is/are
+donde | where
+ | han from HABER
+quien | whom, that
+ | están from ESTAR
+ | estado from ESTAR
+desde | from
+todo | all
+nos | us
+durante | during
+ | estados from ESTAR
+todos | all
+uno | a
+les | to them
+ni | nor
+contra | against
+otros | other
+ | fueron from SER
+ese | that
+eso | that
+ | había from HABER
+ante | before
+ellos | they
+e | and (variant of y)
+esto | this
+mí | me
+antes | before
+algunos | some
+qué | what?
+unos | a
+yo | I
+otro | other
+otras | other
+otra | other
+él | he
+tanto | so much, many
+esa | that
+estos | these
+mucho | much, many
+quienes | who
+nada | nothing
+muchos | many
+cual | who
+ | sea from SER
+poco | few
+ella | she
+estar | to be
+ | haber from HABER
+estas | these
+ | estaba from ESTAR
+ | estamos from ESTAR
+algunas | some
+algo | something
+nosotros | we
+
+ | other forms
+
+mi | me
+mis | mi plural
+tú | thou
+te | thee
+ti | thee
+tu | thy
+tus | tu plural
+ellas | they
+nosotras | we
+vosotros | you
+vosotras | you
+os | you
+mío | mine
+mía |
+míos |
+mías |
+tuyo | thine
+tuya |
+tuyos |
+tuyas |
+suyo | his, hers, theirs
+suya |
+suyos |
+suyas |
+nuestro | ours
+nuestra |
+nuestros |
+nuestras |
+vuestro | yours
+vuestra |
+vuestros |
+vuestras |
+esos | those
+esas | those
+
+ | forms of estar, to be (not including the infinitive):
+estoy
+estás
+está
+estamos
+estáis
+están
+esté
+estés
+estemos
+estéis
+estén
+estaré
+estarás
+estará
+estaremos
+estaréis
+estarán
+estaría
+estarías
+estaríamos
+estaríais
+estarían
+estaba
+estabas
+estábamos
+estabais
+estaban
+estuve
+estuviste
+estuvo
+estuvimos
+estuvisteis
+estuvieron
+estuviera
+estuvieras
+estuviéramos
+estuvierais
+estuvieran
+estuviese
+estuvieses
+estuviésemos
+estuvieseis
+estuviesen
+estando
+estado
+estada
+estados
+estadas
+estad
+
+ | forms of haber, to have (not including the infinitive):
+he
+has
+ha
+hemos
+habéis
+han
+haya
+hayas
+hayamos
+hayáis
+hayan
+habré
+habrás
+habrá
+habremos
+habréis
+habrán
+habría
+habrías
+habríamos
+habríais
+habrían
+había
+habías
+habíamos
+habíais
+habían
+hube
+hubiste
+hubo
+hubimos
+hubisteis
+hubieron
+hubiera
+hubieras
+hubiéramos
+hubierais
+hubieran
+hubiese
+hubieses
+hubiésemos
+hubieseis
+hubiesen
+habiendo
+habido
+habida
+habidos
+habidas
+
+ | forms of ser, to be (not including the infinitive):
+soy
+eres
+es
+somos
+sois
+son
+sea
+seas
+seamos
+seáis
+sean
+seré
+serás
+será
+seremos
+seréis
+serán
+sería
+serías
+seríamos
+seríais
+serían
+era
+eras
+éramos
+erais
+eran
+fui
+fuiste
+fue
+fuimos
+fuisteis
+fueron
+fuera
+fueras
+fuéramos
+fuerais
+fueran
+fuese
+fueses
+fuésemos
+fueseis
+fuesen
+siendo
+sido
+ | sed also means 'thirst'
+
+ | forms of tener, to have (not including the infinitive):
+tengo
+tienes
+tiene
+tenemos
+tenéis
+tienen
+tenga
+tengas
+tengamos
+tengáis
+tengan
+tendré
+tendrás
+tendrá
+tendremos
+tendréis
+tendrán
+tendría
+tendrías
+tendríamos
+tendríais
+tendrían
+tenía
+tenías
+teníamos
+teníais
+tenían
+tuve
+tuviste
+tuvo
+tuvimos
+tuvisteis
+tuvieron
+tuviera
+tuvieras
+tuviéramos
+tuvierais
+tuvieran
+tuviese
+tuvieses
+tuviésemos
+tuvieseis
+tuviesen
+teniendo
+tenido
+tenida
+tenidos
+tenidas
+tened
+''')
+
+js_stemmer = u"""
+var JSX={};(function(k){function l(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function I(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function g(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function J(a,b,c){return a[b]=a[b]/c|0}var p=parseInt;var z=parseFloat;function K(a){return a!==a}var x=isFinite;var w=encodeURIComponent;var u=decodeURIComponent;var t=encodeURI;var s=decodeURI;var A=Object.prototype.toString;var q=Object.prototype.hasOwnProperty;function j(){}k.require=function(b){var a=o[b];return a!==undefined?a:null};k.profilerIsRunning=function(){return j.getResults!=null};k.getProfileResults=function(){return(j.getResults||function(){return{}})()};k.postProfileResults=function(a,b){if(j.postResults==null)throw new Error('profiler has not been turned on');return j.postResults(a,b)};k.resetProfileResults=function(){if(j.resetResults==null)throw new Error('profiler has not been turned on');return j.resetResults()};k.DEBUG=false;function r(){};l([r],Error);function a(a,b,c){this.F=a.length;this.K=a;this.L=b;this.I=c;this.H=null;this.P=null};l([a],Object);function m(){};l([m],Object);function i(){var a;var b;var c;this.G={};a=this.E='';b=this._=0;c=this.A=a.length;this.D=0;this.B=b;this.C=c};l([i],m);function v(a,b){a.E=b.E;a._=b._;a.A=b.A;a.D=b.D;a.B=b.B;a.C=b.C};function f(b,d,c,e){var a;if(b._>=b.A){return false}a=b.E.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function h(a,d,c,e){var b;if(a._>=a.A){return false}b=a.E.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function d(a,b,d){var c;if(a._-a.D<b){return false}if(a.E.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function n(f,m,p){var b;var d;var e;var n;var g;var k;var l;var i;var h;var c;var a;var j;var o;b=0;d=p;e=f._;n=f.A;g=0;k=0;l=false;while(true){i=b+(d-b>>>1);h=0;c=g<k?g:k;a=m[i];for(j=c;j<a.F;j++){if(e+c===n){h=-1;break}h=f.E.charCodeAt(e+c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){d=i;k=c}else{b=i;g=c}if(d-b<=1){if(b>0){break}if(d===b){break}if(l){break}l=true}}while(true){a=m[b];if(g>=a.F){f._=e+a.F|0;if(a.H==null){return a.I}o=a.H(a.P);f._=e+a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function e(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.D;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.F-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.E.charCodeAt(e-1-c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.F){d._=e-a.F|0;if(a.H==null){return a.I}o=a.H(d);d._=e-a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function B(a,b,d,e){var c;c=e.length-(d-b);a.E=a.E.slice(0,b)+e+a.E.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function c(a,f){var b;var c;var d;var e;b=false;if((c=a.B)<0||c>(d=a.C)||d>(e=a.A)||e>a.E.length?false:true){B(a,a.B,a.C,f);b=true}return b};i.prototype.J=function(){return false};i.prototype.a=function(b){var a;var c;var d;var e;a=this.G['.'+b];if(a==null){c=this.E=b;d=this._=0;e=this.A=c.length;this.D=0;this.B=d;this.C=e;this.J();a=this.E;this.G['.'+b]=a}return a};i.prototype.stemWord=i.prototype.a;i.prototype.b=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.G['.'+c];if(a==null){f=this.E=c;g=this._=0;h=this.A=f.length;this.D=0;this.B=g;this.C=h;this.J();a=this.E;this.G['.'+c]=a}d.push(a)}return d};i.prototype.stemWords=i.prototype.b;function b(){i.call(this);this.I_p2=0;this.I_p1=0;this.I_pV=0};l([b],i);b.prototype.M=function(a){this.I_p2=a.I_p2;this.I_p1=a.I_p1;this.I_pV=a.I_pV;v(this,a)};b.prototype.copy_from=b.prototype.M;b.prototype.U=function(){var u;var w;var x;var y;var t;var l;var d;var e;var g;var i;var c;var j;var k;var a;var m;var n;var o;var p;var q;var r;var s;var v;this.I_pV=s=this.A;this.I_p1=s;this.I_p2=s;u=this._;l=true;a:while(l===true){l=false;d=true;g:while(d===true){d=false;w=this._;e=true;b:while(e===true){e=false;if(!f(this,b.g_v,97,252)){break b}g=true;f:while(g===true){g=false;x=this._;i=true;c:while(i===true){i=false;if(!h(this,b.g_v,97,252)){break c}d:while(true){c=true;e:while(c===true){c=false;if(!f(this,b.g_v,97,252)){break e}break d}if(this._>=this.A){break c}this._++}break f}this._=x;if(!f(this,b.g_v,97,252)){break b}c:while(true){j=true;d:while(j===true){j=false;if(!h(this,b.g_v,97,252)){break d}break c}if(this._>=this.A){break b}this._++}}break g}this._=w;if(!h(this,b.g_v,97,252)){break a}k=true;c:while(k===true){k=false;y=this._;a=true;b:while(a===true){a=false;if(!h(this,b.g_v,97,252)){break b}e:while(true){m=true;d:while(m===true){m=false;if(!f(this,b.g_v,97,252)){break d}break e}if(this._>=this.A){break b}this._++}break c}this._=y;if(!f(this,b.g_v,97,252)){break a}if(this._>=this.A){break a}this._++}}this.I_pV=this._}v=this._=u;t=v;n=true;a:while(n===true){n=false;b:while(true){o=true;c:while(o===true){o=false;if(!f(this,b.g_v,97,252)){break c}break b}if(this._>=this.A){break a}this._++}b:while(true){p=true;c:while(p===true){p=false;if(!h(this,b.g_v,97,252)){break c}break b}if(this._>=this.A){break a}this._++}this.I_p1=this._;b:while(true){q=true;c:while(q===true){q=false;if(!f(this,b.g_v,97,252)){break c}break b}if(this._>=this.A){break a}this._++}c:while(true){r=true;b:while(r===true){r=false;if(!h(this,b.g_v,97,252)){break b}break c}if(this._>=this.A){break a}this._++}this.I_p2=this._}this._=t;return true};b.prototype.r_mark_regions=b.prototype.U;function E(a){var x;var y;var z;var u;var v;var l;var d;var e;var g;var i;var j;var k;var c;var m;var n;var o;var p;var q;var r;var s;var t;var w;a.I_pV=t=a.A;a.I_p1=t;a.I_p2=t;x=a._;l=true;a:while(l===true){l=false;d=true;g:while(d===true){d=false;y=a._;e=true;b:while(e===true){e=false;if(!f(a,b.g_v,97,252)){break b}g=true;f:while(g===true){g=false;z=a._;i=true;c:while(i===true){i=false;if(!h(a,b.g_v,97,252)){break c}d:while(true){j=true;e:while(j===true){j=false;if(!f(a,b.g_v,97,252)){break e}break d}if(a._>=a.A){break c}a._++}break f}a._=z;if(!f(a,b.g_v,97,252)){break b}c:while(true){k=true;d:while(k===true){k=false;if(!h(a,b.g_v,97,252)){break d}break c}if(a._>=a.A){break b}a._++}}break g}a._=y;if(!h(a,b.g_v,97,252)){break a}c=true;c:while(c===true){c=false;u=a._;m=true;b:while(m===true){m=false;if(!h(a,b.g_v,97,252)){break b}e:while(true){n=true;d:while(n===true){n=false;if(!f(a,b.g_v,97,252)){break d}break e}if(a._>=a.A){break b}a._++}break c}a._=u;if(!f(a,b.g_v,97,252)){break a}if(a._>=a.A){break a}a._++}}a.I_pV=a._}w=a._=x;v=w;o=true;a:while(o===true){o=false;b:while(true){p=true;c:while(p===true){p=false;if(!f(a,b.g_v,97,252)){break c}break b}if(a._>=a.A){break a}a._++}b:while(true){q=true;c:while(q===true){q=false;if(!h(a,b.g_v,97,252)){break c}break b}if(a._>=a.A){break a}a._++}a.I_p1=a._;b:while(true){r=true;c:while(r===true){r=false;if(!f(a,b.g_v,97,252)){break c}break b}if(a._>=a.A){break a}a._++}c:while(true){s=true;b:while(s===true){s=false;if(!h(a,b.g_v,97,252)){break b}break c}if(a._>=a.A){break a}a._++}a.I_p2=a._}a._=v;return true};b.prototype.V=function(){var a;var e;var d;b:while(true){e=this._;d=true;a:while(d===true){d=false;this.B=this._;a=n(this,b.a_0,6);if(a===0){break a}this.C=this._;switch(a){case 0:break a;case 1:if(!c(this,'a')){return false}break;case 2:if(!c(this,'e')){return false}break;case 3:if(!c(this,'i')){return false}break;case 4:if(!c(this,'o')){return false}break;case 5:if(!c(this,'u')){return false}break;case 6:if(this._>=this.A){break a}this._++;break}continue b}this._=e;break b}return true};b.prototype.r_postlude=b.prototype.V;function F(a){var d;var f;var e;b:while(true){f=a._;e=true;a:while(e===true){e=false;a.B=a._;d=n(a,b.a_0,6);if(d===0){break a}a.C=a._;switch(d){case 0:break a;case 1:if(!c(a,'a')){return false}break;case 2:if(!c(a,'e')){return false}break;case 3:if(!c(a,'i')){return false}break;case 4:if(!c(a,'o')){return false}break;case 5:if(!c(a,'u')){return false}break;case 6:if(a._>=a.A){break a}a._++;break}continue b}a._=f;break b}return true};b.prototype.S=function(){return!(this.I_pV<=this._)?false:true};b.prototype.r_RV=b.prototype.S;b.prototype.Q=function(){return!(this.I_p1<=this._)?false:true};b.prototype.r_R1=b.prototype.Q;b.prototype.R=function(){return!(this.I_p2<=this._)?false:true};b.prototype.r_R2=b.prototype.R;b.prototype.T=function(){var a;this.C=this._;if(e(this,b.a_1,13)===0){return false}this.B=this._;a=e(this,b.a_2,11);if(a===0){return false}if(!(!(this.I_pV<=this._)?false:true)){return false}switch(a){case 0:return false;case 1:this.B=this._;if(!c(this,'iendo')){return false}break;case 2:this.B=this._;if(!c(this,'ando')){return false}break;case 3:this.B=this._;if(!c(this,'ar')){return false}break;case 4:this.B=this._;if(!c(this,'er')){return false}break;case 5:this.B=this._;if(!c(this,'ir')){return false}break;case 6:if(!c(this,'')){return false}break;case 7:if(!d(this,1,'u')){return false}if(!c(this,'')){return false}break}return true};b.prototype.r_attached_pronoun=b.prototype.T;function G(a){var f;a.C=a._;if(e(a,b.a_1,13)===0){return false}a.B=a._;f=e(a,b.a_2,11);if(f===0){return false}if(!(!(a.I_pV<=a._)?false:true)){return false}switch(f){case 0:return false;case 1:a.B=a._;if(!c(a,'iendo')){return false}break;case 2:a.B=a._;if(!c(a,'ando')){return false}break;case 3:a.B=a._;if(!c(a,'ar')){return false}break;case 4:a.B=a._;if(!c(a,'er')){return false}break;case 5:a.B=a._;if(!c(a,'ir')){return false}break;case 6:if(!c(a,'')){return false}break;case 7:if(!d(a,1,'u')){return false}if(!c(a,'')){return false}break}return true};b.prototype.X=function(){var a;var j;var f;var g;var h;var i;var k;var l;var m;var n;var o;var q;var r;var s;var p;this.C=this._;a=e(this,b.a_6,46);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}break;case 2:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}j=this.A-this._;k=true;a:while(k===true){k=false;this.C=this._;if(!d(this,2,'ic')){this._=this.A-j;break a}this.B=q=this._;if(!(!(this.I_p2<=q)?false:true)){this._=this.A-j;break a}if(!c(this,'')){return false}}break;case 3:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'log')){return false}break;case 4:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'u')){return false}break;case 5:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'ente')){return false}break;case 6:if(!(!(this.I_p1<=this._)?false:true)){return false}if(!c(this,'')){return false}f=this.A-this._;l=true;a:while(l===true){l=false;this.C=this._;a=e(this,b.a_3,4);if(a===0){this._=this.A-f;break a}this.B=r=this._;if(!(!(this.I_p2<=r)?false:true)){this._=this.A-f;break a}if(!c(this,'')){return false}switch(a){case 0:this._=this.A-f;break a;case 1:this.C=this._;if(!d(this,2,'at')){this._=this.A-f;break a}this.B=s=this._;if(!(!(this.I_p2<=s)?false:true)){this._=this.A-f;break a}if(!c(this,'')){return false}break}}break;case 7:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}g=this.A-this._;m=true;a:while(m===true){m=false;this.C=this._;a=e(this,b.a_4,3);if(a===0){this._=this.A-g;break a}this.B=this._;switch(a){case 0:this._=this.A-g;break a;case 1:if(!(!(this.I_p2<=this._)?false:true)){this._=this.A-g;break a}if(!c(this,'')){return false}break}}break;case 8:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}h=this.A-this._;n=true;a:while(n===true){n=false;this.C=this._;a=e(this,b.a_5,3);if(a===0){this._=this.A-h;break a}this.B=this._;switch(a){case 0:this._=this.A-h;break a;case 1:if(!(!(this.I_p2<=this._)?false:true)){this._=this.A-h;break a}if(!c(this,'')){return false}break}}break;case 9:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}i=this.A-this._;o=true;a:while(o===true){o=false;this.C=this._;if(!d(this,2,'at')){this._=this.A-i;break a}this.B=p=this._;if(!(!(this.I_p2<=p)?false:true)){this._=this.A-i;break a}if(!c(this,'')){return false}}break}return true};b.prototype.r_standard_suffix=b.prototype.X;function H(a){var f;var k;var g;var h;var i;var j;var l;var m;var n;var o;var p;var r;var s;var t;var q;a.C=a._;f=e(a,b.a_6,46);if(f===0){return false}a.B=a._;switch(f){case 0:return false;case 1:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}break;case 2:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}k=a.A-a._;l=true;a:while(l===true){l=false;a.C=a._;if(!d(a,2,'ic')){a._=a.A-k;break a}a.B=r=a._;if(!(!(a.I_p2<=r)?false:true)){a._=a.A-k;break a}if(!c(a,'')){return false}}break;case 3:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'log')){return false}break;case 4:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'u')){return false}break;case 5:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'ente')){return false}break;case 6:if(!(!(a.I_p1<=a._)?false:true)){return false}if(!c(a,'')){return false}g=a.A-a._;m=true;a:while(m===true){m=false;a.C=a._;f=e(a,b.a_3,4);if(f===0){a._=a.A-g;break a}a.B=s=a._;if(!(!(a.I_p2<=s)?false:true)){a._=a.A-g;break a}if(!c(a,'')){return false}switch(f){case 0:a._=a.A-g;break a;case 1:a.C=a._;if(!d(a,2,'at')){a._=a.A-g;break a}a.B=t=a._;if(!(!(a.I_p2<=t)?false:true)){a._=a.A-g;break a}if(!c(a,'')){return false}break}}break;case 7:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}h=a.A-a._;n=true;a:while(n===true){n=false;a.C=a._;f=e(a,b.a_4,3);if(f===0){a._=a.A-h;break a}a.B=a._;switch(f){case 0:a._=a.A-h;break a;case 1:if(!(!(a.I_p2<=a._)?false:true)){a._=a.A-h;break a}if(!c(a,'')){return false}break}}break;case 8:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}i=a.A-a._;o=true;a:while(o===true){o=false;a.C=a._;f=e(a,b.a_5,3);if(f===0){a._=a.A-i;break a}a.B=a._;switch(f){case 0:a._=a.A-i;break a;case 1:if(!(!(a.I_p2<=a._)?false:true)){a._=a.A-i;break a}if(!c(a,'')){return false}break}}break;case 9:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}j=a.A-a._;p=true;a:while(p===true){p=false;a.C=a._;if(!d(a,2,'at')){a._=a.A-j;break a}a.B=q=a._;if(!(!(a.I_p2<=q)?false:true)){a._=a.A-j;break a}if(!c(a,'')){return false}}break}return true};b.prototype.Z=function(){var a;var g;var f;var h;var i;var j;g=this.A-(h=this._);if(h<this.I_pV){return false}i=this._=this.I_pV;f=this.D;this.D=i;j=this._=this.A-g;this.C=j;a=e(this,b.a_7,12);if(a===0){this.D=f;return false}this.B=this._;this.D=f;switch(a){case 0:return false;case 1:if(!d(this,1,'u')){return false}if(!c(this,'')){return false}break}return true};b.prototype.r_y_verb_suffix=b.prototype.Z;function D(a){var f;var h;var g;var i;var j;var k;h=a.A-(i=a._);if(i<a.I_pV){return false}j=a._=a.I_pV;g=a.D;a.D=j;k=a._=a.A-h;a.C=k;f=e(a,b.a_7,12);if(f===0){a.D=g;return false}a.B=a._;a.D=g;switch(f){case 0:return false;case 1:if(!d(a,1,'u')){return false}if(!c(a,'')){return false}break}return true};b.prototype.Y=function(){var a;var i;var f;var g;var j;var h;var k;var l;var m;i=this.A-(k=this._);if(k<this.I_pV){return false}l=this._=this.I_pV;f=this.D;this.D=l;m=this._=this.A-i;this.C=m;a=e(this,b.a_8,96);if(a===0){this.D=f;return false}this.B=this._;this.D=f;switch(a){case 0:return false;case 1:g=this.A-this._;h=true;a:while(h===true){h=false;if(!d(this,1,'u')){this._=this.A-g;break a}j=this.A-this._;if(!d(this,1,'g')){this._=this.A-g;break a}this._=this.A-j}this.B=this._;if(!c(this,'')){return false}break;case 2:if(!c(this,'')){return false}break}return true};b.prototype.r_verb_suffix=b.prototype.Y;function C(a){var g;var j;var h;var f;var k;var i;var m;var n;var l;j=a.A-(m=a._);if(m<a.I_pV){return false}n=a._=a.I_pV;h=a.D;a.D=n;l=a._=a.A-j;a.C=l;g=e(a,b.a_8,96);if(g===0){a.D=h;return false}a.B=a._;a.D=h;switch(g){case 0:return false;case 1:f=a.A-a._;i=true;a:while(i===true){i=false;if(!d(a,1,'u')){a._=a.A-f;break a}k=a.A-a._;if(!d(a,1,'g')){a._=a.A-f;break a}a._=a.A-k}a.B=a._;if(!c(a,'')){return false}break;case 2:if(!c(a,'')){return false}break}return true};b.prototype.W=function(){var f;var a;var h;var g;var i;var j;this.C=this._;f=e(this,b.a_9,8);if(f===0){return false}this.B=this._;switch(f){case 0:return false;case 1:if(!(!(this.I_pV<=this._)?false:true)){return false}if(!c(this,'')){return false}break;case 2:if(!(!(this.I_pV<=this._)?false:true)){return false}if(!c(this,'')){return false}a=this.A-this._;g=true;a:while(g===true){g=false;this.C=this._;if(!d(this,1,'u')){this._=this.A-a;break a}this.B=i=this._;h=this.A-i;if(!d(this,1,'g')){this._=this.A-a;break a}j=this._=this.A-h;if(!(!(this.I_pV<=j)?false:true)){this._=this.A-a;break a}if(!c(this,'')){return false}}break}return true};b.prototype.r_residual_suffix=b.prototype.W;function y(a){var g;var f;var i;var h;var j;var k;a.C=a._;g=e(a,b.a_9,8);if(g===0){return false}a.B=a._;switch(g){case 0:return false;case 1:if(!(!(a.I_pV<=a._)?false:true)){return false}if(!c(a,'')){return false}break;case 2:if(!(!(a.I_pV<=a._)?false:true)){return false}if(!c(a,'')){return false}f=a.A-a._;h=true;a:while(h===true){h=false;a.C=a._;if(!d(a,1,'u')){a._=a.A-f;break a}a.B=j=a._;i=a.A-j;if(!d(a,1,'g')){a._=a.A-f;break a}k=a._=a.A-i;if(!(!(a.I_pV<=k)?false:true)){a._=a.A-f;break a}if(!c(a,'')){return false}}break}return true};b.prototype.J=function(){var k;var l;var m;var b;var j;var c;var d;var e;var f;var a;var g;var h;var i;var o;var p;var q;var r;var s;var n;k=this._;c=true;a:while(c===true){c=false;if(!E(this)){break a}}o=this._=k;this.D=o;q=this._=p=this.A;l=p-q;d=true;a:while(d===true){d=false;if(!G(this)){break a}}s=this._=(r=this.A)-l;m=r-s;e=true;b:while(e===true){e=false;f=true;a:while(f===true){f=false;b=this.A-this._;a=true;c:while(a===true){a=false;if(!H(this)){break c}break a}this._=this.A-b;g=true;c:while(g===true){g=false;if(!D(this)){break c}break a}this._=this.A-b;if(!C(this)){break b}}}this._=this.A-m;h=true;a:while(h===true){h=false;if(!y(this)){break a}}n=this._=this.D;j=n;i=true;a:while(i===true){i=false;if(!F(this)){break a}}this._=j;return true};b.prototype.stem=b.prototype.J;b.prototype.N=function(a){return a instanceof b};b.prototype.equals=b.prototype.N;b.prototype.O=function(){var c;var a;var b;var d;c='SpanishStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};b.prototype.hashCode=b.prototype.O;b.serialVersionUID=1;g(b,'methodObject',function(){return new b});g(b,'a_0',function(){return[new a('',-1,6),new a('á',0,1),new a('é',0,2),new a('í',0,3),new a('ó',0,4),new a('ú',0,5)]});g(b,'a_1',function(){return[new a('la',-1,-1),new a('sela',0,-1),new a('le',-1,-1),new a('me',-1,-1),new a('se',-1,-1),new a('lo',-1,-1),new a('selo',5,-1),new a('las',-1,-1),new a('selas',7,-1),new a('les',-1,-1),new a('los',-1,-1),new a('selos',10,-1),new a('nos',-1,-1)]});g(b,'a_2',function(){return[new a('ando',-1,6),new a('iendo',-1,6),new a('yendo',-1,7),new a('ándo',-1,2),new a('iéndo',-1,1),new a('ar',-1,6),new a('er',-1,6),new a('ir',-1,6),new a('ár',-1,3),new a('ér',-1,4),new a('ír',-1,5)]});g(b,'a_3',function(){return[new a('ic',-1,-1),new a('ad',-1,-1),new a('os',-1,-1),new a('iv',-1,1)]});g(b,'a_4',function(){return[new a('able',-1,1),new a('ible',-1,1),new a('ante',-1,1)]});g(b,'a_5',function(){return[new a('ic',-1,1),new a('abil',-1,1),new a('iv',-1,1)]});g(b,'a_6',function(){return[new a('ica',-1,1),new a('ancia',-1,2),new a('encia',-1,5),new a('adora',-1,2),new a('osa',-1,1),new a('ista',-1,1),new a('iva',-1,9),new a('anza',-1,1),new a('logía',-1,3),new a('idad',-1,8),new a('able',-1,1),new a('ible',-1,1),new a('ante',-1,2),new a('mente',-1,7),new a('amente',13,6),new a('ación',-1,2),new a('ución',-1,4),new a('ico',-1,1),new a('ismo',-1,1),new a('oso',-1,1),new a('amiento',-1,1),new a('imiento',-1,1),new a('ivo',-1,9),new a('ador',-1,2),new a('icas',-1,1),new a('ancias',-1,2),new a('encias',-1,5),new a('adoras',-1,2),new a('osas',-1,1),new a('istas',-1,1),new a('ivas',-1,9),new a('anzas',-1,1),new a('logías',-1,3),new a('idades',-1,8),new a('ables',-1,1),new a('ibles',-1,1),new a('aciones',-1,2),new a('uciones',-1,4),new a('adores',-1,2),new a('antes',-1,2),new a('icos',-1,1),new a('ismos',-1,1),new a('osos',-1,1),new a('amientos',-1,1),new a('imientos',-1,1),new a('ivos',-1,9)]});g(b,'a_7',function(){return[new a('ya',-1,1),new a('ye',-1,1),new a('yan',-1,1),new a('yen',-1,1),new a('yeron',-1,1),new a('yendo',-1,1),new a('yo',-1,1),new a('yas',-1,1),new a('yes',-1,1),new a('yais',-1,1),new a('yamos',-1,1),new a('yó',-1,1)]});g(b,'a_8',function(){return[new a('aba',-1,2),new a('ada',-1,2),new a('ida',-1,2),new a('ara',-1,2),new a('iera',-1,2),new a('ía',-1,2),new a('aría',5,2),new a('ería',5,2),new a('iría',5,2),new a('ad',-1,2),new a('ed',-1,2),new a('id',-1,2),new a('ase',-1,2),new a('iese',-1,2),new a('aste',-1,2),new a('iste',-1,2),new a('an',-1,2),new a('aban',16,2),new a('aran',16,2),new a('ieran',16,2),new a('ían',16,2),new a('arían',20,2),new a('erían',20,2),new a('irían',20,2),new a('en',-1,1),new a('asen',24,2),new a('iesen',24,2),new a('aron',-1,2),new a('ieron',-1,2),new a('arán',-1,2),new a('erán',-1,2),new a('irán',-1,2),new a('ado',-1,2),new a('ido',-1,2),new a('ando',-1,2),new a('iendo',-1,2),new a('ar',-1,2),new a('er',-1,2),new a('ir',-1,2),new a('as',-1,2),new a('abas',39,2),new a('adas',39,2),new a('idas',39,2),new a('aras',39,2),new a('ieras',39,2),new a('ías',39,2),new a('arías',45,2),new a('erías',45,2),new a('irías',45,2),new a('es',-1,1),new a('ases',49,2),new a('ieses',49,2),new a('abais',-1,2),new a('arais',-1,2),new a('ierais',-1,2),new a('íais',-1,2),new a('aríais',55,2),new a('eríais',55,2),new a('iríais',55,2),new a('aseis',-1,2),new a('ieseis',-1,2),new a('asteis',-1,2),new a('isteis',-1,2),new a('áis',-1,2),new a('éis',-1,1),new a('aréis',64,2),new a('eréis',64,2),new a('iréis',64,2),new a('ados',-1,2),new a('idos',-1,2),new a('amos',-1,2),new a('ábamos',70,2),new a('áramos',70,2),new a('iéramos',70,2),new a('íamos',70,2),new a('aríamos',74,2),new a('eríamos',74,2),new a('iríamos',74,2),new a('emos',-1,1),new a('aremos',78,2),new a('eremos',78,2),new a('iremos',78,2),new a('ásemos',78,2),new a('iésemos',78,2),new a('imos',-1,2),new a('arás',-1,2),new a('erás',-1,2),new a('irás',-1,2),new a('ís',-1,2),new a('ará',-1,2),new a('erá',-1,2),new a('irá',-1,2),new a('aré',-1,2),new a('eré',-1,2),new a('iré',-1,2),new a('ió',-1,2)]});g(b,'a_9',function(){return[new a('a',-1,1),new a('e',-1,2),new a('o',-1,1),new a('os',-1,1),new a('á',-1,1),new a('é',-1,2),new a('í',-1,1),new a('ó',-1,1)]});g(b,'g_v',function(){return[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,4,10]});var o={'src/stemmer.jsx':{Stemmer:m},'src/spanish-stemmer.jsx':{SpanishStemmer:b}}}(JSX))
+var Stemmer = JSX.require("src/spanish-stemmer.jsx").SpanishStemmer;
+"""
+
+
+class SearchSpanish(SearchLanguage):
+ lang = 'es'
+ language_name = 'Spanish'
+ js_stemmer_code = js_stemmer
+ stopwords = spanish_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('spanish')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/fi.py b/sphinx/search/fi.py
new file mode 100644
index 00000000..7350d88f
--- /dev/null
+++ b/sphinx/search/fi.py
@@ -0,0 +1,123 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.fi
+ ~~~~~~~~~~~~~~~~
+
+ Finnish search language: includes the JS Finnish stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+finnish_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/finnish/stop.txt
+| forms of BE
+
+olla
+olen
+olet
+on
+olemme
+olette
+ovat
+ole | negative form
+
+oli
+olisi
+olisit
+olisin
+olisimme
+olisitte
+olisivat
+olit
+olin
+olimme
+olitte
+olivat
+ollut
+olleet
+
+en | negation
+et
+ei
+emme
+ette
+eivät
+
+|Nom Gen Acc Part Iness Elat Illat Adess Ablat Allat Ess Trans
+minä minun minut minua minussa minusta minuun minulla minulta minulle | I
+sinä sinun sinut sinua sinussa sinusta sinuun sinulla sinulta sinulle | you
+hän hänen hänet häntä hänessä hänestä häneen hänellä häneltä hänelle | he she
+me meidän meidät meitä meissä meistä meihin meillä meiltä meille | we
+te teidän teidät teitä teissä teistä teihin teillä teiltä teille | you
+he heidän heidät heitä heissä heistä heihin heillä heiltä heille | they
+
+tämä tämän tätä tässä tästä tähän tällä tältä tälle tänä täksi | this
+tuo tuon tuota tuossa tuosta tuohon tuolla tuolta tuolle tuona tuoksi | that
+se sen sitä siinä siitä siihen sillä siltä sille sinä siksi | it
+nämä näiden näitä näissä näistä näihin näillä näiltä näille näinä näiksi | these
+nuo noiden noita noissa noista noihin noilla noilta noille noina noiksi | those
+ne niiden niitä niissä niistä niihin niillä niiltä niille niinä niiksi | they
+
+kuka kenen kenet ketä kenessä kenestä keneen kenellä keneltä kenelle kenenä keneksi| who
+ketkä keiden ketkä keitä keissä keistä keihin keillä keiltä keille keinä keiksi | (pl)
+mikä minkä minkä mitä missä mistä mihin millä miltä mille minä miksi | which what
+mitkä | (pl)
+
+joka jonka jota jossa josta johon jolla jolta jolle jona joksi | who which
+jotka joiden joita joissa joista joihin joilla joilta joille joina joiksi | (pl)
+
+| conjunctions
+
+että | that
+ja | and
+jos | if
+koska | because
+kuin | than
+mutta | but
+niin | so
+sekä | and
+sillä | for
+tai | or
+vaan | but
+vai | or
+vaikka | although
+
+
+| prepositions
+
+kanssa | with
+mukaan | according to
+noin | about
+poikki | across
+yli | over, across
+
+| other
+
+kun | when
+niin | so
+nyt | now
+itse | self
+''')
+
+js_stemmer = u"""
+var JSX={};(function(j){function l(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function M(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function f(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function N(a,b,c){return a[b]=a[b]/c|0}var s=parseInt;var C=parseFloat;function O(a){return a!==a}var A=isFinite;var z=encodeURIComponent;var y=decodeURIComponent;var x=encodeURI;var v=decodeURI;var u=Object.prototype.toString;var E=Object.prototype.hasOwnProperty;function k(){}j.require=function(b){var a=q[b];return a!==undefined?a:null};j.profilerIsRunning=function(){return k.getResults!=null};j.getProfileResults=function(){return(k.getResults||function(){return{}})()};j.postProfileResults=function(a,b){if(k.postResults==null)throw new Error('profiler has not been turned on');return k.postResults(a,b)};j.resetProfileResults=function(){if(k.resetResults==null)throw new Error('profiler has not been turned on');return k.resetResults()};j.DEBUG=false;function t(){};l([t],Error);function b(a,b,c){this.F=a.length;this.M=a;this.N=b;this.H=c;this.G=null;this.S=null};function m(a,b,c,d,e){this.F=a.length;this.M=a;this.N=b;this.H=c;this.G=d;this.S=e};l([b,m],Object);function p(){};l([p],Object);function g(){var a;var b;var c;this.I={};a=this.E='';b=this._=0;c=this.A=a.length;this.B=0;this.C=b;this.D=c};l([g],p);function w(a,b){a.E=b.E;a._=b._;a.A=b.A;a.B=b.B;a.C=b.C;a.D=b.D};function n(b,d,c,e){var a;if(b._>=b.A){return false}a=b.E.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};g.prototype.L=function(c,b,d){var a;if(this._<=this.B){return false}a=this.E.charCodeAt(this._-1);if(a>d||a<b){return false}a-=b;if((c[a>>>3]&1<<(a&7))===0){return false}this._--;return true};function h(b,d,c,e){var a;if(b._<=b.B){return false}a=b.E.charCodeAt(b._-1);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._--;return true};function o(a,d,c,e){var b;if(a._>=a.A){return false}b=a.E.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function i(a,d,c,e){var b;if(a._<=a.B){return false}b=a.E.charCodeAt(a._-1);if(b>e||b<c){a._--;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._--;return true}return false};g.prototype.K=function(a,c){var b;if(this._-this.B<a){return false}if(this.E.slice((b=this._)-a,b)!==c){return false}this._-=a;return true};function c(a,b,d){var c;if(a._-a.B<b){return false}if(a.E.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};g.prototype.Q=function(l,o){var b;var d;var e;var m;var f;var j;var k;var h;var g;var c;var a;var i;var n;b=0;d=o;e=this._;m=this.B;f=0;j=0;k=false;while(true){h=b+(d-b>>1);g=0;c=f<j?f:j;a=l[h];for(i=a.F-1-c;i>=0;i--){if(e-c===m){g=-1;break}g=this.E.charCodeAt(e-1-c)-a.M.charCodeAt(i);if(g!==0){break}c++}if(g<0){d=h;j=c}else{b=h;f=c}if(d-b<=1){if(b>0){break}if(d===b){break}if(k){break}k=true}}while(true){a=l[b];if(f>=a.F){this._=e-a.F|0;if(a.G==null){return a.H}n=a.G(this);this._=e-a.F|0;if(n){return a.H}}b=a.N;if(b<0){return 0}}return-1};function e(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.B;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.F-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.E.charCodeAt(e-1-c)-a.M.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.F){d._=e-a.F|0;if(a.G==null){return a.H}o=a.G(d);d._=e-a.F|0;if(o){return a.H}}b=a.N;if(b<0){return 0}}return-1};function D(a,b,d,e){var c;c=e.length-(d-b);a.E=a.E.slice(0,b)+e+a.E.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function d(a,f){var b;var c;var d;var e;b=false;if((c=a.C)<0||c>(d=a.D)||d>(e=a.A)||e>a.E.length?false:true){D(a,a.C,a.D,f);b=true}return b};function r(a,f){var b;var c;var d;var e;b='';if((c=a.C)<0||c>(d=a.D)||d>(e=a.A)||e>a.E.length?false:true){b=a.E.slice(a.C,a.D)}return b};g.prototype.J=function(){return false};g.prototype.e=function(b){var a;var c;var d;var e;a=this.I['.'+b];if(a==null){c=this.E=b;d=this._=0;e=this.A=c.length;this.B=0;this.C=d;this.D=e;this.J();a=this.E;this.I['.'+b]=a}return a};g.prototype.stemWord=g.prototype.e;g.prototype.f=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.I['.'+c];if(a==null){f=this.E=c;g=this._=0;h=this.A=f.length;this.B=0;this.C=g;this.D=h;this.J();a=this.E;this.I['.'+c]=a}d.push(a)}return d};g.prototype.stemWords=g.prototype.f;function a(){g.call(this);this.B_ending_removed=false;this.S_x='';this.I_p2=0;this.I_p1=0};l([a],g);a.prototype.O=function(a){this.B_ending_removed=a.B_ending_removed;this.S_x=a.S_x;this.I_p2=a.I_p2;this.I_p1=a.I_p1;w(this,a)};a.prototype.copy_from=a.prototype.O;a.prototype.Y=function(){var b;var c;var d;var e;var f;var g;var h;var i;var j;this.I_p1=i=this.A;this.I_p2=i;a:while(true){b=this._;d=true;b:while(d===true){d=false;if(!n(this,a.g_V1,97,246)){break b}this._=b;break a}h=this._=b;if(h>=this.A){return false}this._++}a:while(true){e=true;b:while(e===true){e=false;if(!o(this,a.g_V1,97,246)){break b}break a}if(this._>=this.A){return false}this._++}this.I_p1=this._;a:while(true){c=this._;f=true;b:while(f===true){f=false;if(!n(this,a.g_V1,97,246)){break b}this._=c;break a}j=this._=c;if(j>=this.A){return false}this._++}a:while(true){g=true;b:while(g===true){g=false;if(!o(this,a.g_V1,97,246)){break b}break a}if(this._>=this.A){return false}this._++}this.I_p2=this._;return true};a.prototype.r_mark_regions=a.prototype.Y;function H(b){var d;var e;var f;var c;var g;var h;var j;var k;var i;b.I_p1=k=b.A;b.I_p2=k;a:while(true){d=b._;f=true;b:while(f===true){f=false;if(!n(b,a.g_V1,97,246)){break b}b._=d;break a}j=b._=d;if(j>=b.A){return false}b._++}a:while(true){c=true;b:while(c===true){c=false;if(!o(b,a.g_V1,97,246)){break b}break a}if(b._>=b.A){return false}b._++}b.I_p1=b._;a:while(true){e=b._;g=true;b:while(g===true){g=false;if(!n(b,a.g_V1,97,246)){break b}b._=e;break a}i=b._=e;if(i>=b.A){return false}b._++}a:while(true){h=true;b:while(h===true){h=false;if(!o(b,a.g_V1,97,246)){break b}break a}if(b._>=b.A){return false}b._++}b.I_p2=b._;return true};a.prototype.U=function(){return!(this.I_p2<=this._)?false:true};a.prototype.r_R2=a.prototype.U;a.prototype.a=function(){var b;var f;var c;var g;var i;var j;f=this.A-(g=this._);if(g<this.I_p1){return false}i=this._=this.I_p1;c=this.B;this.B=i;j=this._=this.A-f;this.D=j;b=e(this,a.a_0,10);if(b===0){this.B=c;return false}this.C=this._;this.B=c;switch(b){case 0:return false;case 1:if(!h(this,a.g_particle_end,97,246)){return false}break;case 2:if(!(!(this.I_p2<=this._)?false:true)){return false}break}return!d(this,'')?false:true};a.prototype.r_particle_etc=a.prototype.a;function I(b){var c;var g;var f;var i;var j;var k;g=b.A-(i=b._);if(i<b.I_p1){return false}j=b._=b.I_p1;f=b.B;b.B=j;k=b._=b.A-g;b.D=k;c=e(b,a.a_0,10);if(c===0){b.B=f;return false}b.C=b._;b.B=f;switch(c){case 0:return false;case 1:if(!h(b,a.g_particle_end,97,246)){return false}break;case 2:if(!(!(b.I_p2<=b._)?false:true)){return false}break}return!d(b,'')?false:true};a.prototype.b=function(){var b;var h;var f;var i;var g;var j;var k;var l;h=this.A-(j=this._);if(j<this.I_p1){return false}k=this._=this.I_p1;f=this.B;this.B=k;l=this._=this.A-h;this.D=l;b=e(this,a.a_4,9);if(b===0){this.B=f;return false}this.C=this._;this.B=f;switch(b){case 0:return false;case 1:i=this.A-this._;g=true;a:while(g===true){g=false;if(!c(this,1,'k')){break a}return false}this._=this.A-i;if(!d(this,'')){return false}break;case 2:if(!d(this,'')){return false}this.D=this._;if(!c(this,3,'kse')){return false}this.C=this._;if(!d(this,'ksi')){return false}break;case 3:if(!d(this,'')){return false}break;case 4:if(e(this,a.a_1,6)===0){return false}if(!d(this,'')){return false}break;case 5:if(e(this,a.a_2,6)===0){return false}if(!d(this,'')){return false}break;case 6:if(e(this,a.a_3,2)===0){return false}if(!d(this,'')){return false}break}return true};a.prototype.r_possessive=a.prototype.b;function J(b){var f;var i;var g;var j;var h;var k;var l;var m;i=b.A-(k=b._);if(k<b.I_p1){return false}l=b._=b.I_p1;g=b.B;b.B=l;m=b._=b.A-i;b.D=m;f=e(b,a.a_4,9);if(f===0){b.B=g;return false}b.C=b._;b.B=g;switch(f){case 0:return false;case 1:j=b.A-b._;h=true;a:while(h===true){h=false;if(!c(b,1,'k')){break a}return false}b._=b.A-j;if(!d(b,'')){return false}break;case 2:if(!d(b,'')){return false}b.D=b._;if(!c(b,3,'kse')){return false}b.C=b._;if(!d(b,'ksi')){return false}break;case 3:if(!d(b,'')){return false}break;case 4:if(e(b,a.a_1,6)===0){return false}if(!d(b,'')){return false}break;case 5:if(e(b,a.a_2,6)===0){return false}if(!d(b,'')){return false}break;case 6:if(e(b,a.a_3,2)===0){return false}if(!d(b,'')){return false}break}return true};a.prototype.T=function(){return e(this,a.a_5,7)===0?false:true};a.prototype.r_LONG=a.prototype.T;a.prototype.V=function(){return!c(this,1,'i')?false:!h(this,a.g_V2,97,246)?false:true};a.prototype.r_VI=a.prototype.V;a.prototype.W=function(){var j;var o;var f;var g;var p;var m;var b;var k;var l;var q;var r;var s;var n;o=this.A-(q=this._);if(q<this.I_p1){return false}r=this._=this.I_p1;f=this.B;this.B=r;s=this._=this.A-o;this.D=s;j=e(this,a.a_6,30);if(j===0){this.B=f;return false}this.C=this._;this.B=f;switch(j){case 0:return false;case 1:if(!c(this,1,'a')){return false}break;case 2:if(!c(this,1,'e')){return false}break;case 3:if(!c(this,1,'i')){return false}break;case 4:if(!c(this,1,'o')){return false}break;case 5:if(!c(this,1,'ä')){return false}break;case 6:if(!c(this,1,'ö')){return false}break;case 7:g=this.A-this._;b=true;a:while(b===true){b=false;p=this.A-this._;k=true;b:while(k===true){k=false;m=this.A-this._;l=true;c:while(l===true){l=false;if(!(e(this,a.a_5,7)===0?false:true)){break c}break b}this._=this.A-m;if(!c(this,2,'ie')){this._=this.A-g;break a}}n=this._=this.A-p;if(n<=this.B){this._=this.A-g;break a}this._--;this.C=this._}break;case 8:if(!h(this,a.g_V1,97,246)){return false}if(!i(this,a.g_V1,97,246)){return false}break;case 9:if(!c(this,1,'e')){return false}break}if(!d(this,'')){return false}this.B_ending_removed=true;return true};a.prototype.r_case_ending=a.prototype.W;function K(b){var f;var o;var g;var j;var p;var n;var k;var l;var m;var r;var s;var t;var q;o=b.A-(r=b._);if(r<b.I_p1){return false}s=b._=b.I_p1;g=b.B;b.B=s;t=b._=b.A-o;b.D=t;f=e(b,a.a_6,30);if(f===0){b.B=g;return false}b.C=b._;b.B=g;switch(f){case 0:return false;case 1:if(!c(b,1,'a')){return false}break;case 2:if(!c(b,1,'e')){return false}break;case 3:if(!c(b,1,'i')){return false}break;case 4:if(!c(b,1,'o')){return false}break;case 5:if(!c(b,1,'ä')){return false}break;case 6:if(!c(b,1,'ö')){return false}break;case 7:j=b.A-b._;k=true;a:while(k===true){k=false;p=b.A-b._;l=true;b:while(l===true){l=false;n=b.A-b._;m=true;c:while(m===true){m=false;if(!(e(b,a.a_5,7)===0?false:true)){break c}break b}b._=b.A-n;if(!c(b,2,'ie')){b._=b.A-j;break a}}q=b._=b.A-p;if(q<=b.B){b._=b.A-j;break a}b._--;b.C=b._}break;case 8:if(!h(b,a.g_V1,97,246)){return false}if(!i(b,a.g_V1,97,246)){return false}break;case 9:if(!c(b,1,'e')){return false}break}if(!d(b,'')){return false}b.B_ending_removed=true;return true};a.prototype.Z=function(){var b;var h;var f;var i;var g;var j;var k;var l;h=this.A-(j=this._);if(j<this.I_p2){return false}k=this._=this.I_p2;f=this.B;this.B=k;l=this._=this.A-h;this.D=l;b=e(this,a.a_7,14);if(b===0){this.B=f;return false}this.C=this._;this.B=f;switch(b){case 0:return false;case 1:i=this.A-this._;g=true;a:while(g===true){g=false;if(!c(this,2,'po')){break a}return false}this._=this.A-i;break}return!d(this,'')?false:true};a.prototype.r_other_endings=a.prototype.Z;function L(b){var f;var i;var g;var j;var h;var k;var l;var m;i=b.A-(k=b._);if(k<b.I_p2){return false}l=b._=b.I_p2;g=b.B;b.B=l;m=b._=b.A-i;b.D=m;f=e(b,a.a_7,14);if(f===0){b.B=g;return false}b.C=b._;b.B=g;switch(f){case 0:return false;case 1:j=b.A-b._;h=true;a:while(h===true){h=false;if(!c(b,2,'po')){break a}return false}b._=b.A-j;break}return!d(b,'')?false:true};a.prototype.X=function(){var c;var b;var f;var g;var h;c=this.A-(f=this._);if(f<this.I_p1){return false}g=this._=this.I_p1;b=this.B;this.B=g;h=this._=this.A-c;this.D=h;if(e(this,a.a_8,2)===0){this.B=b;return false}this.C=this._;this.B=b;return!d(this,'')?false:true};a.prototype.r_i_plural=a.prototype.X;function G(b){var f;var c;var g;var h;var i;f=b.A-(g=b._);if(g<b.I_p1){return false}h=b._=b.I_p1;c=b.B;b.B=h;i=b._=b.A-f;b.D=i;if(e(b,a.a_8,2)===0){b.B=c;return false}b.C=b._;b.B=c;return!d(b,'')?false:true};a.prototype.c=function(){var i;var l;var b;var j;var k;var g;var m;var f;var o;var p;var q;var r;var s;var t;var n;l=this.A-(o=this._);if(o<this.I_p1){return false}p=this._=this.I_p1;b=this.B;this.B=p;q=this._=this.A-l;this.D=q;if(!c(this,1,'t')){this.B=b;return false}this.C=r=this._;j=this.A-r;if(!h(this,a.g_V1,97,246)){this.B=b;return false}this._=this.A-j;if(!d(this,'')){return false}this.B=b;k=this.A-(s=this._);if(s<this.I_p2){return false}t=this._=this.I_p2;g=this.B;this.B=t;n=this._=this.A-k;this.D=n;i=e(this,a.a_9,2);if(i===0){this.B=g;return false}this.C=this._;this.B=g;switch(i){case 0:return false;case 1:m=this.A-this._;f=true;a:while(f===true){f=false;if(!c(this,2,'po')){break a}return false}this._=this.A-m;break}return!d(this,'')?false:true};a.prototype.r_t_plural=a.prototype.c;function F(b){var g;var m;var f;var o;var l;var i;var k;var j;var p;var q;var r;var s;var t;var u;var n;m=b.A-(p=b._);if(p<b.I_p1){return false}q=b._=b.I_p1;f=b.B;b.B=q;r=b._=b.A-m;b.D=r;if(!c(b,1,'t')){b.B=f;return false}b.C=s=b._;o=b.A-s;if(!h(b,a.g_V1,97,246)){b.B=f;return false}b._=b.A-o;if(!d(b,'')){return false}b.B=f;l=b.A-(t=b._);if(t<b.I_p2){return false}u=b._=b.I_p2;i=b.B;b.B=u;n=b._=b.A-l;b.D=n;g=e(b,a.a_9,2);if(g===0){b.B=i;return false}b.C=b._;b.B=i;switch(g){case 0:return false;case 1:k=b.A-b._;j=true;a:while(j===true){j=false;if(!c(b,2,'po')){break a}return false}b._=b.A-k;break}return!d(b,'')?false:true};a.prototype.d=function(){var x;var q;var s;var t;var u;var v;var w;var y;var f;var g;var j;var k;var l;var m;var n;var b;var o;var z;var p;var B;var C;var D;var E;var F;var G;var H;var I;var J;var K;var L;var A;x=this.A-(z=this._);if(z<this.I_p1){return false}B=this._=this.I_p1;q=this.B;this.B=B;D=this._=(C=this.A)-x;s=C-D;g=true;a:while(g===true){g=false;t=this.A-this._;if(!(e(this,a.a_5,7)===0?false:true)){break a}p=this._=this.A-t;this.D=p;if(p<=this.B){break a}this._--;this.C=this._;if(!d(this,'')){return false}}F=this._=(E=this.A)-s;u=E-F;j=true;a:while(j===true){j=false;this.D=this._;if(!h(this,a.g_AEI,97,228)){break a}this.C=this._;if(!i(this,a.g_V1,97,246)){break a}if(!d(this,'')){return false}}H=this._=(G=this.A)-u;v=G-H;k=true;a:while(k===true){k=false;this.D=this._;if(!c(this,1,'j')){break a}this.C=this._;l=true;b:while(l===true){l=false;w=this.A-this._;m=true;c:while(m===true){m=false;if(!c(this,1,'o')){break c}break b}this._=this.A-w;if(!c(this,1,'u')){break a}}if(!d(this,'')){return false}}J=this._=(I=this.A)-v;y=I-J;n=true;a:while(n===true){n=false;this.D=this._;if(!c(this,1,'o')){break a}this.C=this._;if(!c(this,1,'j')){break a}if(!d(this,'')){return false}}this._=this.A-y;this.B=q;a:while(true){f=this.A-this._;b=true;b:while(b===true){b=false;if(!i(this,a.g_V1,97,246)){break b}this._=this.A-f;break a}K=this._=this.A-f;if(K<=this.B){return false}this._--}this.D=L=this._;if(L<=this.B){return false}this._--;this.C=this._;A=this.S_x=r(this,this.S_x);return A===''?false:!(o=this.S_x,c(this,o.length,o))?false:!d(this,'')?false:true};a.prototype.r_tidy=a.prototype.d;function B(b){var s;var t;var u;var v;var w;var x;var y;var z;var l;var g;var j;var k;var f;var m;var n;var o;var p;var A;var q;var C;var D;var E;var F;var G;var H;var I;var J;var K;var L;var M;var B;s=b.A-(A=b._);if(A<b.I_p1){return false}C=b._=b.I_p1;t=b.B;b.B=C;E=b._=(D=b.A)-s;u=D-E;g=true;a:while(g===true){g=false;v=b.A-b._;if(!(e(b,a.a_5,7)===0?false:true)){break a}q=b._=b.A-v;b.D=q;if(q<=b.B){break a}b._--;b.C=b._;if(!d(b,'')){return false}}G=b._=(F=b.A)-u;w=F-G;j=true;a:while(j===true){j=false;b.D=b._;if(!h(b,a.g_AEI,97,228)){break a}b.C=b._;if(!i(b,a.g_V1,97,246)){break a}if(!d(b,'')){return false}}I=b._=(H=b.A)-w;x=H-I;k=true;a:while(k===true){k=false;b.D=b._;if(!c(b,1,'j')){break a}b.C=b._;f=true;b:while(f===true){f=false;y=b.A-b._;m=true;c:while(m===true){m=false;if(!c(b,1,'o')){break c}break b}b._=b.A-y;if(!c(b,1,'u')){break a}}if(!d(b,'')){return false}}K=b._=(J=b.A)-x;z=J-K;n=true;a:while(n===true){n=false;b.D=b._;if(!c(b,1,'o')){break a}b.C=b._;if(!c(b,1,'j')){break a}if(!d(b,'')){return false}}b._=b.A-z;b.B=t;a:while(true){l=b.A-b._;o=true;b:while(o===true){o=false;if(!i(b,a.g_V1,97,246)){break b}b._=b.A-l;break a}L=b._=b.A-l;if(L<=b.B){return false}b._--}b.D=M=b._;if(M<=b.B){return false}b._--;b.C=b._;B=b.S_x=r(b,b.S_x);return B===''?false:!(p=b.S_x,c(b,p.length,p))?false:!d(b,'')?false:true};a.prototype.J=function(){var p;var k;var l;var m;var n;var o;var q;var r;var b;var c;var d;var e;var f;var g;var a;var h;var i;var j;var t;var u;var v;var w;var x;var y;var z;var A;var C;var D;var s;p=this._;b=true;a:while(b===true){b=false;if(!H(this)){break a}}t=this._=p;this.B_ending_removed=false;this.B=t;v=this._=u=this.A;k=u-v;c=true;a:while(c===true){c=false;if(!I(this)){break a}}x=this._=(w=this.A)-k;l=w-x;d=true;a:while(d===true){d=false;if(!J(this)){break a}}z=this._=(y=this.A)-l;m=y-z;e=true;a:while(e===true){e=false;if(!K(this)){break a}}C=this._=(A=this.A)-m;n=A-C;f=true;a:while(f===true){f=false;if(!L(this)){break a}}this._=this.A-n;g=true;a:while(g===true){g=false;o=this.A-this._;a=true;b:while(a===true){a=false;if(!this.B_ending_removed){break b}q=this.A-this._;h=true;c:while(h===true){h=false;if(!G(this)){break c}}this._=this.A-q;break a}s=this._=(D=this.A)-o;r=D-s;i=true;b:while(i===true){i=false;if(!F(this)){break b}}this._=this.A-r}j=true;a:while(j===true){j=false;if(!B(this)){break a}}this._=this.B;return true};a.prototype.stem=a.prototype.J;a.prototype.P=function(b){return b instanceof a};a.prototype.equals=a.prototype.P;a.prototype.R=function(){var c;var a;var b;var d;c='FinnishStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};a.prototype.hashCode=a.prototype.R;a.serialVersionUID=1;f(a,'methodObject',function(){return new a});f(a,'a_0',function(){return[new b('pa',-1,1),new b('sti',-1,2),new b('kaan',-1,1),new b('han',-1,1),new b('kin',-1,1),new b('hän',-1,1),new b('kään',-1,1),new b('ko',-1,1),new b('pä',-1,1),new b('kö',-1,1)]});f(a,'a_1',function(){return[new b('lla',-1,-1),new b('na',-1,-1),new b('ssa',-1,-1),new b('ta',-1,-1),new b('lta',3,-1),new b('sta',3,-1)]});f(a,'a_2',function(){return[new b('llä',-1,-1),new b('nä',-1,-1),new b('ssä',-1,-1),new b('tä',-1,-1),new b('ltä',3,-1),new b('stä',3,-1)]});f(a,'a_3',function(){return[new b('lle',-1,-1),new b('ine',-1,-1)]});f(a,'a_4',function(){return[new b('nsa',-1,3),new b('mme',-1,3),new b('nne',-1,3),new b('ni',-1,2),new b('si',-1,1),new b('an',-1,4),new b('en',-1,6),new b('än',-1,5),new b('nsä',-1,3)]});f(a,'a_5',function(){return[new b('aa',-1,-1),new b('ee',-1,-1),new b('ii',-1,-1),new b('oo',-1,-1),new b('uu',-1,-1),new b('ää',-1,-1),new b('öö',-1,-1)]});f(a,'a_6',function(){return[new b('a',-1,8),new b('lla',0,-1),new b('na',0,-1),new b('ssa',0,-1),new b('ta',0,-1),new b('lta',4,-1),new b('sta',4,-1),new b('tta',4,9),new b('lle',-1,-1),new b('ine',-1,-1),new b('ksi',-1,-1),new b('n',-1,7),new b('han',11,1),new m('den',11,-1,function(c){var b;b=c;return!b.K(1,'i')?false:!b.L(a.g_V2,97,246)?false:true},a.methodObject),new m('seen',11,-1,function(c){var b;b=c;return b.Q(a.a_5,7)===0?false:true},a.methodObject),new b('hen',11,2),new m('tten',11,-1,function(c){var b;b=c;return!b.K(1,'i')?false:!b.L(a.g_V2,97,246)?false:true},a.methodObject),new b('hin',11,3),new m('siin',11,-1,function(c){var b;b=c;return!b.K(1,'i')?false:!b.L(a.g_V2,97,246)?false:true},a.methodObject),new b('hon',11,4),new b('hän',11,5),new b('hön',11,6),new b('ä',-1,8),new b('llä',22,-1),new b('nä',22,-1),new b('ssä',22,-1),new b('tä',22,-1),new b('ltä',26,-1),new b('stä',26,-1),new b('ttä',26,9)]});f(a,'a_7',function(){return[new b('eja',-1,-1),new b('mma',-1,1),new b('imma',1,-1),new b('mpa',-1,1),new b('impa',3,-1),new b('mmi',-1,1),new b('immi',5,-1),new b('mpi',-1,1),new b('impi',7,-1),new b('ejä',-1,-1),new b('mmä',-1,1),new b('immä',10,-1),new b('mpä',-1,1),new b('impä',12,-1)]});f(a,'a_8',function(){return[new b('i',-1,-1),new b('j',-1,-1)]});f(a,'a_9',function(){return[new b('mma',-1,1),new b('imma',0,-1)]});f(a,'g_AEI',function(){return[17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8]});f(a,'g_V1',function(){return[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32]});f(a,'g_V2',function(){return[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32]});f(a,'g_particle_end',function(){return[17,97,24,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32]});var q={'src/stemmer.jsx':{Stemmer:p},'src/finnish-stemmer.jsx':{FinnishStemmer:a}}}(JSX))
+var Stemmer = JSX.require("src/finnish-stemmer.jsx").FinnishStemmer;
+"""
+
+
+class SearchFinnish(SearchLanguage):
+ lang = 'fi'
+ language_name = 'Finnish'
+ js_stemmer_code = js_stemmer
+ stopwords = finnish_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('finnish')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/fr.py b/sphinx/search/fr.py
new file mode 100644
index 00000000..9ae61339
--- /dev/null
+++ b/sphinx/search/fr.py
@@ -0,0 +1,209 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.fr
+ ~~~~~~~~~~~~~~~~
+
+ French search language: includes the JS French stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+french_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/french/stop.txt
+au | a + le
+aux | a + les
+avec | with
+ce | this
+ces | these
+dans | with
+de | of
+des | de + les
+du | de + le
+elle | she
+en | `of them' etc
+et | and
+eux | them
+il | he
+je | I
+la | the
+le | the
+leur | their
+lui | him
+ma | my (fem)
+mais | but
+me | me
+même | same; as in moi-même (myself) etc
+mes | me (pl)
+moi | me
+mon | my (masc)
+ne | not
+nos | our (pl)
+notre | our
+nous | we
+on | one
+ou | where
+par | by
+pas | not
+pour | for
+qu | que before vowel
+que | that
+qui | who
+sa | his, her (fem)
+se | oneself
+ses | his (pl)
+son | his, her (masc)
+sur | on
+ta | thy (fem)
+te | thee
+tes | thy (pl)
+toi | thee
+ton | thy (masc)
+tu | thou
+un | a
+une | a
+vos | your (pl)
+votre | your
+vous | you
+
+ | single letter forms
+
+c | c'
+d | d'
+j | j'
+l | l'
+à | to, at
+m | m'
+n | n'
+s | s'
+t | t'
+y | there
+
+ | forms of être (not including the infinitive):
+été
+étée
+étées
+étés
+étant
+suis
+es
+est
+sommes
+êtes
+sont
+serai
+seras
+sera
+serons
+serez
+seront
+serais
+serait
+serions
+seriez
+seraient
+étais
+était
+étions
+étiez
+étaient
+fus
+fut
+fûmes
+fûtes
+furent
+sois
+soit
+soyons
+soyez
+soient
+fusse
+fusses
+fût
+fussions
+fussiez
+fussent
+
+ | forms of avoir (not including the infinitive):
+ayant
+eu
+eue
+eues
+eus
+ai
+as
+avons
+avez
+ont
+aurai
+auras
+aura
+aurons
+aurez
+auront
+aurais
+aurait
+aurions
+auriez
+auraient
+avais
+avait
+avions
+aviez
+avaient
+eut
+eûmes
+eûtes
+eurent
+aie
+aies
+ait
+ayons
+ayez
+aient
+eusse
+eusses
+eût
+eussions
+eussiez
+eussent
+
+ | Later additions (from Jean-Christophe Deschamps)
+ceci | this
+cela | that (added 11 Apr 2012. Omission reported by Adrien Grand)
+celà | that (incorrect, though common)
+cet | this
+cette | this
+ici | here
+ils | they
+les | the (pl)
+leurs | their (pl)
+quel | which
+quels | which
+quelle | which
+quelles | which
+sans | without
+soi | oneself
+''')
+
+js_stemmer = u"""
+var JSX={};(function(l){function m(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function P(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function g(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function O(a,b,c){return a[b]=a[b]/c|0}var u=parseInt;var v=parseFloat;function N(a){return a!==a}var x=isFinite;var y=encodeURIComponent;var z=decodeURIComponent;var A=encodeURI;var B=decodeURI;var C=Object.prototype.toString;var D=Object.prototype.hasOwnProperty;function k(){}l.require=function(b){var a=q[b];return a!==undefined?a:null};l.profilerIsRunning=function(){return k.getResults!=null};l.getProfileResults=function(){return(k.getResults||function(){return{}})()};l.postProfileResults=function(a,b){if(k.postResults==null)throw new Error('profiler has not been turned on');return k.postResults(a,b)};l.resetProfileResults=function(){if(k.resetResults==null)throw new Error('profiler has not been turned on');return k.resetResults()};l.DEBUG=false;function G(){};m([G],Error);function a(a,b,c){this.F=a.length;this.K=a;this.L=b;this.I=c;this.H=null;this.P=null};m([a],Object);function p(){};m([p],Object);function i(){var a;var b;var c;this.G={};a=this.E='';b=this._=0;c=this.A=a.length;this.B=0;this.D=b;this.C=c};m([i],p);function s(a,b){a.E=b.E;a._=b._;a.A=b.A;a.B=b.B;a.D=b.D;a.C=b.C};function e(b,d,c,e){var a;if(b._>=b.A){return false}a=b.E.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function r(b,d,c,e){var a;if(b._<=b.B){return false}a=b.E.charCodeAt(b._-1);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._--;return true};function o(a,d,c,e){var b;if(a._>=a.A){return false}b=a.E.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function j(a,d,c,e){var b;if(a._<=a.B){return false}b=a.E.charCodeAt(a._-1);if(b>e||b<c){a._--;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._--;return true}return false};function h(a,b,d){var c;if(a.A-a._<b){return false}if(a.E.slice(c=a._,c+b)!==d){return false}a._+=b;return true};function d(a,b,d){var c;if(a._-a.B<b){return false}if(a.E.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function n(f,m,p){var b;var d;var e;var n;var g;var k;var l;var i;var h;var c;var a;var j;var o;b=0;d=p;e=f._;n=f.A;g=0;k=0;l=false;while(true){i=b+(d-b>>>1);h=0;c=g<k?g:k;a=m[i];for(j=c;j<a.F;j++){if(e+c===n){h=-1;break}h=f.E.charCodeAt(e+c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){d=i;k=c}else{b=i;g=c}if(d-b<=1){if(b>0){break}if(d===b){break}if(l){break}l=true}}while(true){a=m[b];if(g>=a.F){f._=e+a.F|0;if(a.H==null){return a.I}o=a.H(a.P);f._=e+a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function f(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.B;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.F-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.E.charCodeAt(e-1-c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.F){d._=e-a.F|0;if(a.H==null){return a.I}o=a.H(d);d._=e-a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function E(a,b,d,e){var c;c=e.length-(d-b);a.E=a.E.slice(0,b)+e+a.E.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function c(a,f){var b;var c;var d;var e;b=false;if((c=a.D)<0||c>(d=a.C)||d>(e=a.A)||e>a.E.length?false:true){E(a,a.D,a.C,f);b=true}return b};i.prototype.J=function(){return false};i.prototype.c=function(b){var a;var c;var d;var e;a=this.G['.'+b];if(a==null){c=this.E=b;d=this._=0;e=this.A=c.length;this.B=0;this.D=d;this.C=e;this.J();a=this.E;this.G['.'+b]=a}return a};i.prototype.stemWord=i.prototype.c;i.prototype.d=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.G['.'+c];if(a==null){f=this.E=c;g=this._=0;h=this.A=f.length;this.B=0;this.D=g;this.C=h;this.J();a=this.E;this.G['.'+c]=a}d.push(a)}return d};i.prototype.stemWords=i.prototype.d;function b(){i.call(this);this.I_p2=0;this.I_p1=0;this.I_pV=0};m([b],i);b.prototype.M=function(a){this.I_p2=a.I_p2;this.I_p1=a.I_p1;this.I_pV=a.I_pV;s(this,a)};b.prototype.copy_from=b.prototype.M;b.prototype.W=function(){var p;var j;var f;var g;var i;var a;var d;var k;var l;var m;var n;var o;var q;a:while(true){p=this._;i=true;g:while(i===true){i=false;h:while(true){j=this._;a=true;b:while(a===true){a=false;d=true;c:while(d===true){d=false;f=this._;k=true;d:while(k===true){k=false;if(!e(this,b.g_v,97,251)){break d}this.D=this._;l=true;e:while(l===true){l=false;g=this._;m=true;f:while(m===true){m=false;if(!h(this,1,'u')){break f}this.C=this._;if(!e(this,b.g_v,97,251)){break f}if(!c(this,'U')){return false}break e}this._=g;n=true;f:while(n===true){n=false;if(!h(this,1,'i')){break f}this.C=this._;if(!e(this,b.g_v,97,251)){break f}if(!c(this,'I')){return false}break e}this._=g;if(!h(this,1,'y')){break d}this.C=this._;if(!c(this,'Y')){return false}}break c}this._=f;o=true;d:while(o===true){o=false;this.D=this._;if(!h(this,1,'y')){break d}this.C=this._;if(!e(this,b.g_v,97,251)){break d}if(!c(this,'Y')){return false}break c}this._=f;if(!h(this,1,'q')){break b}this.D=this._;if(!h(this,1,'u')){break b}this.C=this._;if(!c(this,'U')){return false}}this._=j;break h}q=this._=j;if(q>=this.A){break g}this._++}continue a}this._=p;break a}return true};b.prototype.r_prelude=b.prototype.W;function H(a){var q;var k;var f;var g;var i;var j;var d;var l;var m;var n;var o;var p;var r;a:while(true){q=a._;i=true;g:while(i===true){i=false;h:while(true){k=a._;j=true;b:while(j===true){j=false;d=true;c:while(d===true){d=false;f=a._;l=true;d:while(l===true){l=false;if(!e(a,b.g_v,97,251)){break d}a.D=a._;m=true;e:while(m===true){m=false;g=a._;n=true;f:while(n===true){n=false;if(!h(a,1,'u')){break f}a.C=a._;if(!e(a,b.g_v,97,251)){break f}if(!c(a,'U')){return false}break e}a._=g;o=true;f:while(o===true){o=false;if(!h(a,1,'i')){break f}a.C=a._;if(!e(a,b.g_v,97,251)){break f}if(!c(a,'I')){return false}break e}a._=g;if(!h(a,1,'y')){break d}a.C=a._;if(!c(a,'Y')){return false}}break c}a._=f;p=true;d:while(p===true){p=false;a.D=a._;if(!h(a,1,'y')){break d}a.C=a._;if(!e(a,b.g_v,97,251)){break d}if(!c(a,'Y')){return false}break c}a._=f;if(!h(a,1,'q')){break b}a.D=a._;if(!h(a,1,'u')){break b}a.C=a._;if(!c(a,'U')){return false}}a._=k;break h}r=a._=k;if(r>=a.A){break g}a._++}continue a}a._=q;break a}return true};b.prototype.U=function(){var t;var i;var r;var d;var f;var g;var h;var c;var a;var j;var k;var l;var m;var s;var p;var q;this.I_pV=p=this.A;this.I_p1=p;this.I_p2=p;t=this._;d=true;b:while(d===true){d=false;f=true;c:while(f===true){f=false;i=this._;g=true;a:while(g===true){g=false;if(!e(this,b.g_v,97,251)){break a}if(!e(this,b.g_v,97,251)){break a}if(this._>=this.A){break a}this._++;break c}this._=i;h=true;a:while(h===true){h=false;if(n(this,b.a_0,3)===0){break a}break c}s=this._=i;if(s>=this.A){break b}this._++;a:while(true){c=true;d:while(c===true){c=false;if(!e(this,b.g_v,97,251)){break d}break a}if(this._>=this.A){break b}this._++}}this.I_pV=this._}q=this._=t;r=q;a=true;a:while(a===true){a=false;c:while(true){j=true;b:while(j===true){j=false;if(!e(this,b.g_v,97,251)){break b}break c}if(this._>=this.A){break a}this._++}b:while(true){k=true;c:while(k===true){k=false;if(!o(this,b.g_v,97,251)){break c}break b}if(this._>=this.A){break a}this._++}this.I_p1=this._;b:while(true){l=true;c:while(l===true){l=false;if(!e(this,b.g_v,97,251)){break c}break b}if(this._>=this.A){break a}this._++}c:while(true){m=true;b:while(m===true){m=false;if(!o(this,b.g_v,97,251)){break b}break c}if(this._>=this.A){break a}this._++}this.I_p2=this._}this._=r;return true};b.prototype.r_mark_regions=b.prototype.U;function I(a){var s;var i;var r;var d;var f;var g;var h;var c;var j;var k;var l;var m;var p;var t;var q;var u;a.I_pV=q=a.A;a.I_p1=q;a.I_p2=q;s=a._;d=true;b:while(d===true){d=false;f=true;c:while(f===true){f=false;i=a._;g=true;a:while(g===true){g=false;if(!e(a,b.g_v,97,251)){break a}if(!e(a,b.g_v,97,251)){break a}if(a._>=a.A){break a}a._++;break c}a._=i;h=true;a:while(h===true){h=false;if(n(a,b.a_0,3)===0){break a}break c}t=a._=i;if(t>=a.A){break b}a._++;a:while(true){c=true;d:while(c===true){c=false;if(!e(a,b.g_v,97,251)){break d}break a}if(a._>=a.A){break b}a._++}}a.I_pV=a._}u=a._=s;r=u;j=true;a:while(j===true){j=false;c:while(true){k=true;b:while(k===true){k=false;if(!e(a,b.g_v,97,251)){break b}break c}if(a._>=a.A){break a}a._++}b:while(true){l=true;c:while(l===true){l=false;if(!o(a,b.g_v,97,251)){break c}break b}if(a._>=a.A){break a}a._++}a.I_p1=a._;b:while(true){m=true;c:while(m===true){m=false;if(!e(a,b.g_v,97,251)){break c}break b}if(a._>=a.A){break a}a._++}c:while(true){p=true;b:while(p===true){p=false;if(!o(a,b.g_v,97,251)){break b}break c}if(a._>=a.A){break a}a._++}a.I_p2=a._}a._=r;return true};b.prototype.V=function(){var a;var e;var d;b:while(true){e=this._;d=true;a:while(d===true){d=false;this.D=this._;a=n(this,b.a_1,4);if(a===0){break a}this.C=this._;switch(a){case 0:break a;case 1:if(!c(this,'i')){return false}break;case 2:if(!c(this,'u')){return false}break;case 3:if(!c(this,'y')){return false}break;case 4:if(this._>=this.A){break a}this._++;break}continue b}this._=e;break b}return true};b.prototype.r_postlude=b.prototype.V;function J(a){var d;var f;var e;b:while(true){f=a._;e=true;a:while(e===true){e=false;a.D=a._;d=n(a,b.a_1,4);if(d===0){break a}a.C=a._;switch(d){case 0:break a;case 1:if(!c(a,'i')){return false}break;case 2:if(!c(a,'u')){return false}break;case 3:if(!c(a,'y')){return false}break;case 4:if(a._>=a.A){break a}a._++;break}continue b}a._=f;break b}return true};b.prototype.S=function(){return!(this.I_pV<=this._)?false:true};b.prototype.r_RV=b.prototype.S;b.prototype.Q=function(){return!(this.I_p1<=this._)?false:true};b.prototype.r_R1=b.prototype.Q;b.prototype.R=function(){return!(this.I_p2<=this._)?false:true};b.prototype.r_R2=b.prototype.R;b.prototype.Y=function(){var a;var E;var H;var e;var D;var g;var F;var G;var h;var I;var A;var B;var p;var k;var l;var m;var n;var o;var i;var q;var s;var t;var u;var v;var w;var x;var y;var z;var J;var K;var L;var C;this.C=this._;a=f(this,b.a_4,43);if(a===0){return false}this.D=this._;switch(a){case 0:return false;case 1:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}break;case 2:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}E=this.A-this._;p=true;c:while(p===true){p=false;this.C=this._;if(!d(this,2,'ic')){this._=this.A-E;break c}this.D=this._;k=true;b:while(k===true){k=false;H=this.A-this._;l=true;a:while(l===true){l=false;if(!(!(this.I_p2<=this._)?false:true)){break a}if(!c(this,'')){return false}break b}this._=this.A-H;if(!c(this,'iqU')){return false}}}break;case 3:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'log')){return false}break;case 4:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'u')){return false}break;case 5:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'ent')){return false}break;case 6:if(!(!(this.I_pV<=this._)?false:true)){return false}if(!c(this,'')){return false}e=this.A-this._;m=true;a:while(m===true){m=false;this.C=this._;a=f(this,b.a_2,6);if(a===0){this._=this.A-e;break a}this.D=this._;switch(a){case 0:this._=this.A-e;break a;case 1:if(!(!(this.I_p2<=this._)?false:true)){this._=this.A-e;break a}if(!c(this,'')){return false}this.C=this._;if(!d(this,2,'at')){this._=this.A-e;break a}this.D=J=this._;if(!(!(this.I_p2<=J)?false:true)){this._=this.A-e;break a}if(!c(this,'')){return false}break;case 2:n=true;b:while(n===true){n=false;D=this.A-this._;o=true;c:while(o===true){o=false;if(!(!(this.I_p2<=this._)?false:true)){break c}if(!c(this,'')){return false}break b}K=this._=this.A-D;if(!(!(this.I_p1<=K)?false:true)){this._=this.A-e;break a}if(!c(this,'eux')){return false}}break;case 3:if(!(!(this.I_p2<=this._)?false:true)){this._=this.A-e;break a}if(!c(this,'')){return false}break;case 4:if(!(!(this.I_pV<=this._)?false:true)){this._=this.A-e;break a}if(!c(this,'i')){return false}break}}break;case 7:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}g=this.A-this._;i=true;a:while(i===true){i=false;this.C=this._;a=f(this,b.a_3,3);if(a===0){this._=this.A-g;break a}this.D=this._;switch(a){case 0:this._=this.A-g;break a;case 1:q=true;c:while(q===true){q=false;F=this.A-this._;s=true;b:while(s===true){s=false;if(!(!(this.I_p2<=this._)?false:true)){break b}if(!c(this,'')){return false}break c}this._=this.A-F;if(!c(this,'abl')){return false}}break;case 2:t=true;b:while(t===true){t=false;G=this.A-this._;u=true;c:while(u===true){u=false;if(!(!(this.I_p2<=this._)?false:true)){break c}if(!c(this,'')){return false}break b}this._=this.A-G;if(!c(this,'iqU')){return false}}break;case 3:if(!(!(this.I_p2<=this._)?false:true)){this._=this.A-g;break a}if(!c(this,'')){return false}break}}break;case 8:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}h=this.A-this._;v=true;a:while(v===true){v=false;this.C=this._;if(!d(this,2,'at')){this._=this.A-h;break a}this.D=L=this._;if(!(!(this.I_p2<=L)?false:true)){this._=this.A-h;break a}if(!c(this,'')){return false}this.C=this._;if(!d(this,2,'ic')){this._=this.A-h;break a}this.D=this._;w=true;b:while(w===true){w=false;I=this.A-this._;x=true;c:while(x===true){x=false;if(!(!(this.I_p2<=this._)?false:true)){break c}if(!c(this,'')){return false}break b}this._=this.A-I;if(!c(this,'iqU')){return false}}}break;case 9:if(!c(this,'eau')){return false}break;case 10:if(!(!(this.I_p1<=this._)?false:true)){return false}if(!c(this,'al')){return false}break;case 11:y=true;a:while(y===true){y=false;A=this.A-this._;z=true;b:while(z===true){z=false;if(!(!(this.I_p2<=this._)?false:true)){break b}if(!c(this,'')){return false}break a}C=this._=this.A-A;if(!(!(this.I_p1<=C)?false:true)){return false}if(!c(this,'eux')){return false}}break;case 12:if(!(!(this.I_p1<=this._)?false:true)){return false}if(!j(this,b.g_v,97,251)){return false}if(!c(this,'')){return false}break;case 13:if(!(!(this.I_pV<=this._)?false:true)){return false}if(!c(this,'ant')){return false}return false;case 14:if(!(!(this.I_pV<=this._)?false:true)){return false}if(!c(this,'ent')){return false}return false;case 15:B=this.A-this._;if(!r(this,b.g_v,97,251)){return false}if(!(!(this.I_pV<=this._)?false:true)){return false}this._=this.A-B;if(!c(this,'')){return false}return false}return true};b.prototype.r_standard_suffix=b.prototype.Y;function K(a){var g;var F;var I;var e;var E;var h;var G;var H;var i;var J;var B;var C;var p;var l;var m;var n;var o;var k;var q;var s;var t;var u;var v;var w;var x;var y;var z;var A;var K;var L;var M;var D;a.C=a._;g=f(a,b.a_4,43);if(g===0){return false}a.D=a._;switch(g){case 0:return false;case 1:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}break;case 2:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}F=a.A-a._;p=true;c:while(p===true){p=false;a.C=a._;if(!d(a,2,'ic')){a._=a.A-F;break c}a.D=a._;l=true;b:while(l===true){l=false;I=a.A-a._;m=true;a:while(m===true){m=false;if(!(!(a.I_p2<=a._)?false:true)){break a}if(!c(a,'')){return false}break b}a._=a.A-I;if(!c(a,'iqU')){return false}}}break;case 3:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'log')){return false}break;case 4:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'u')){return false}break;case 5:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'ent')){return false}break;case 6:if(!(!(a.I_pV<=a._)?false:true)){return false}if(!c(a,'')){return false}e=a.A-a._;n=true;a:while(n===true){n=false;a.C=a._;g=f(a,b.a_2,6);if(g===0){a._=a.A-e;break a}a.D=a._;switch(g){case 0:a._=a.A-e;break a;case 1:if(!(!(a.I_p2<=a._)?false:true)){a._=a.A-e;break a}if(!c(a,'')){return false}a.C=a._;if(!d(a,2,'at')){a._=a.A-e;break a}a.D=K=a._;if(!(!(a.I_p2<=K)?false:true)){a._=a.A-e;break a}if(!c(a,'')){return false}break;case 2:o=true;b:while(o===true){o=false;E=a.A-a._;k=true;c:while(k===true){k=false;if(!(!(a.I_p2<=a._)?false:true)){break c}if(!c(a,'')){return false}break b}L=a._=a.A-E;if(!(!(a.I_p1<=L)?false:true)){a._=a.A-e;break a}if(!c(a,'eux')){return false}}break;case 3:if(!(!(a.I_p2<=a._)?false:true)){a._=a.A-e;break a}if(!c(a,'')){return false}break;case 4:if(!(!(a.I_pV<=a._)?false:true)){a._=a.A-e;break a}if(!c(a,'i')){return false}break}}break;case 7:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}h=a.A-a._;q=true;a:while(q===true){q=false;a.C=a._;g=f(a,b.a_3,3);if(g===0){a._=a.A-h;break a}a.D=a._;switch(g){case 0:a._=a.A-h;break a;case 1:s=true;c:while(s===true){s=false;G=a.A-a._;t=true;b:while(t===true){t=false;if(!(!(a.I_p2<=a._)?false:true)){break b}if(!c(a,'')){return false}break c}a._=a.A-G;if(!c(a,'abl')){return false}}break;case 2:u=true;b:while(u===true){u=false;H=a.A-a._;v=true;c:while(v===true){v=false;if(!(!(a.I_p2<=a._)?false:true)){break c}if(!c(a,'')){return false}break b}a._=a.A-H;if(!c(a,'iqU')){return false}}break;case 3:if(!(!(a.I_p2<=a._)?false:true)){a._=a.A-h;break a}if(!c(a,'')){return false}break}}break;case 8:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}i=a.A-a._;w=true;a:while(w===true){w=false;a.C=a._;if(!d(a,2,'at')){a._=a.A-i;break a}a.D=M=a._;if(!(!(a.I_p2<=M)?false:true)){a._=a.A-i;break a}if(!c(a,'')){return false}a.C=a._;if(!d(a,2,'ic')){a._=a.A-i;break a}a.D=a._;x=true;b:while(x===true){x=false;J=a.A-a._;y=true;c:while(y===true){y=false;if(!(!(a.I_p2<=a._)?false:true)){break c}if(!c(a,'')){return false}break b}a._=a.A-J;if(!c(a,'iqU')){return false}}}break;case 9:if(!c(a,'eau')){return false}break;case 10:if(!(!(a.I_p1<=a._)?false:true)){return false}if(!c(a,'al')){return false}break;case 11:z=true;a:while(z===true){z=false;B=a.A-a._;A=true;b:while(A===true){A=false;if(!(!(a.I_p2<=a._)?false:true)){break b}if(!c(a,'')){return false}break a}D=a._=a.A-B;if(!(!(a.I_p1<=D)?false:true)){return false}if(!c(a,'eux')){return false}}break;case 12:if(!(!(a.I_p1<=a._)?false:true)){return false}if(!j(a,b.g_v,97,251)){return false}if(!c(a,'')){return false}break;case 13:if(!(!(a.I_pV<=a._)?false:true)){return false}if(!c(a,'ant')){return false}return false;case 14:if(!(!(a.I_pV<=a._)?false:true)){return false}if(!c(a,'ent')){return false}return false;case 15:C=a.A-a._;if(!r(a,b.g_v,97,251)){return false}if(!(!(a.I_pV<=a._)?false:true)){return false}a._=a.A-C;if(!c(a,'')){return false}return false}return true};b.prototype.T=function(){var d;var e;var a;var g;var h;var i;e=this.A-(g=this._);if(g<this.I_pV){return false}h=this._=this.I_pV;a=this.B;this.B=h;i=this._=this.A-e;this.C=i;d=f(this,b.a_5,35);if(d===0){this.B=a;return false}this.D=this._;switch(d){case 0:this.B=a;return false;case 1:if(!j(this,b.g_v,97,251)){this.B=a;return false}if(!c(this,'')){return false}break}this.B=a;return true};b.prototype.r_i_verb_suffix=b.prototype.T;function L(a){var e;var g;var d;var h;var i;var k;g=a.A-(h=a._);if(h<a.I_pV){return false}i=a._=a.I_pV;d=a.B;a.B=i;k=a._=a.A-g;a.C=k;e=f(a,b.a_5,35);if(e===0){a.B=d;return false}a.D=a._;switch(e){case 0:a.B=d;return false;case 1:if(!j(a,b.g_v,97,251)){a.B=d;return false}if(!c(a,'')){return false}break}a.B=d;return true};b.prototype.b=function(){var e;var h;var a;var i;var g;var j;var k;var l;h=this.A-(j=this._);if(j<this.I_pV){return false}k=this._=this.I_pV;a=this.B;this.B=k;l=this._=this.A-h;this.C=l;e=f(this,b.a_6,38);if(e===0){this.B=a;return false}this.D=this._;switch(e){case 0:this.B=a;return false;case 1:if(!(!(this.I_p2<=this._)?false:true)){this.B=a;return false}if(!c(this,'')){return false}break;case 2:if(!c(this,'')){return false}break;case 3:if(!c(this,'')){return false}i=this.A-this._;g=true;a:while(g===true){g=false;this.C=this._;if(!d(this,1,'e')){this._=this.A-i;break a}this.D=this._;if(!c(this,'')){return false}}break}this.B=a;return true};b.prototype.r_verb_suffix=b.prototype.b;function M(a){var g;var i;var e;var j;var h;var k;var l;var m;i=a.A-(k=a._);if(k<a.I_pV){return false}l=a._=a.I_pV;e=a.B;a.B=l;m=a._=a.A-i;a.C=m;g=f(a,b.a_6,38);if(g===0){a.B=e;return false}a.D=a._;switch(g){case 0:a.B=e;return false;case 1:if(!(!(a.I_p2<=a._)?false:true)){a.B=e;return false}if(!c(a,'')){return false}break;case 2:if(!c(a,'')){return false}break;case 3:if(!c(a,'')){return false}j=a.A-a._;h=true;a:while(h===true){h=false;a.C=a._;if(!d(a,1,'e')){a._=a.A-j;break a}a.D=a._;if(!c(a,'')){return false}}break}a.B=e;return true};b.prototype.X=function(){var h;var g;var m;var n;var a;var l;var e;var i;var k;var p;var q;var r;var o;g=this.A-this._;e=true;a:while(e===true){e=false;this.C=this._;if(!d(this,1,'s')){this._=this.A-g;break a}this.D=p=this._;m=this.A-p;if(!j(this,b.g_keep_with_s,97,232)){this._=this.A-g;break a}this._=this.A-m;if(!c(this,'')){return false}}n=this.A-(q=this._);if(q<this.I_pV){return false}r=this._=this.I_pV;a=this.B;this.B=r;o=this._=this.A-n;this.C=o;h=f(this,b.a_7,7);if(h===0){this.B=a;return false}this.D=this._;switch(h){case 0:this.B=a;return false;case 1:if(!(!(this.I_p2<=this._)?false:true)){this.B=a;return false}i=true;a:while(i===true){i=false;l=this.A-this._;k=true;b:while(k===true){k=false;if(!d(this,1,'s')){break b}break a}this._=this.A-l;if(!d(this,1,'t')){this.B=a;return false}}if(!c(this,'')){return false}break;case 2:if(!c(this,'i')){return false}break;case 3:if(!c(this,'')){return false}break;case 4:if(!d(this,2,'gu')){this.B=a;return false}if(!c(this,'')){return false}break}this.B=a;return true};b.prototype.r_residual_suffix=b.prototype.X;function w(a){var g;var h;var p;var n;var e;var m;var i;var k;var l;var q;var r;var s;var o;h=a.A-a._;i=true;a:while(i===true){i=false;a.C=a._;if(!d(a,1,'s')){a._=a.A-h;break a}a.D=q=a._;p=a.A-q;if(!j(a,b.g_keep_with_s,97,232)){a._=a.A-h;break a}a._=a.A-p;if(!c(a,'')){return false}}n=a.A-(r=a._);if(r<a.I_pV){return false}s=a._=a.I_pV;e=a.B;a.B=s;o=a._=a.A-n;a.C=o;g=f(a,b.a_7,7);if(g===0){a.B=e;return false}a.D=a._;switch(g){case 0:a.B=e;return false;case 1:if(!(!(a.I_p2<=a._)?false:true)){a.B=e;return false}k=true;a:while(k===true){k=false;m=a.A-a._;l=true;b:while(l===true){l=false;if(!d(a,1,'s')){break b}break a}a._=a.A-m;if(!d(a,1,'t')){a.B=e;return false}}if(!c(a,'')){return false}break;case 2:if(!c(a,'i')){return false}break;case 3:if(!c(a,'')){return false}break;case 4:if(!d(a,2,'gu')){a.B=e;return false}if(!c(a,'')){return false}break}a.B=e;return true};b.prototype.a=function(){var d;var a;d=this.A-this._;if(f(this,b.a_8,5)===0){return false}a=this._=this.A-d;this.C=a;if(a<=this.B){return false}this._--;this.D=this._;return!c(this,'')?false:true};b.prototype.r_un_double=b.prototype.a;function t(a){var e;var d;e=a.A-a._;if(f(a,b.a_8,5)===0){return false}d=a._=a.A-e;a.C=d;if(d<=a.B){return false}a._--;a.D=a._;return!c(a,'')?false:true};b.prototype.Z=function(){var h;var a;var e;var f;var g;a=1;a:while(true){e=true;b:while(e===true){e=false;if(!j(this,b.g_v,97,251)){break b}a--;continue a}break a}if(a>0){return false}this.C=this._;f=true;a:while(f===true){f=false;h=this.A-this._;g=true;b:while(g===true){g=false;if(!d(this,1,'é')){break b}break a}this._=this.A-h;if(!d(this,1,'è')){return false}}this.D=this._;return!c(this,'e')?false:true};b.prototype.r_un_accent=b.prototype.Z;function F(a){var i;var e;var f;var g;var h;e=1;a:while(true){f=true;b:while(f===true){f=false;if(!j(a,b.g_v,97,251)){break b}e--;continue a}break a}if(e>0){return false}a.C=a._;g=true;a:while(g===true){g=false;i=a.A-a._;h=true;b:while(h===true){h=false;if(!d(a,1,'é')){break b}break a}a._=a.A-i;if(!d(a,1,'è')){return false}}a.D=a._;return!c(a,'e')?false:true};b.prototype.J=function(){var u;var z;var A;var B;var C;var j;var s;var v;var x;var y;var e;var f;var g;var h;var i;var a;var b;var k;var l;var m;var n;var o;var p;var q;var D;var E;var G;var N;var O;var P;var Q;var R;var r;u=this._;e=true;a:while(e===true){e=false;if(!H(this)){break a}}D=this._=u;z=D;f=true;a:while(f===true){f=false;if(!I(this)){break a}}N=this._=z;this.B=N;P=this._=O=this.A;A=O-P;g=true;c:while(g===true){g=false;h=true;d:while(h===true){h=false;B=this.A-this._;i=true;e:while(i===true){i=false;C=this.A-this._;a=true;a:while(a===true){a=false;j=this.A-this._;b=true;b:while(b===true){b=false;if(!K(this)){break b}break a}this._=this.A-j;k=true;b:while(k===true){k=false;if(!L(this)){break b}break a}this._=this.A-j;if(!M(this)){break e}}G=this._=(E=this.A)-C;s=E-G;l=true;a:while(l===true){l=false;this.C=this._;m=true;b:while(m===true){m=false;v=this.A-this._;n=true;f:while(n===true){n=false;if(!d(this,1,'Y')){break f}this.D=this._;if(!c(this,'i')){return false}break b}this._=this.A-v;if(!d(this,1,'ç')){this._=this.A-s;break a}this.D=this._;if(!c(this,'c')){return false}}}break d}this._=this.A-B;if(!w(this)){break c}}}R=this._=(Q=this.A)-A;x=Q-R;o=true;a:while(o===true){o=false;if(!t(this)){break a}}this._=this.A-x;p=true;a:while(p===true){p=false;if(!F(this)){break a}}r=this._=this.B;y=r;q=true;a:while(q===true){q=false;if(!J(this)){break a}}this._=y;return true};b.prototype.stem=b.prototype.J;b.prototype.N=function(a){return a instanceof b};b.prototype.equals=b.prototype.N;b.prototype.O=function(){var c;var a;var b;var d;c='FrenchStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};b.prototype.hashCode=b.prototype.O;b.serialVersionUID=1;g(b,'methodObject',function(){return new b});g(b,'a_0',function(){return[new a('col',-1,-1),new a('par',-1,-1),new a('tap',-1,-1)]});g(b,'a_1',function(){return[new a('',-1,4),new a('I',0,1),new a('U',0,2),new a('Y',0,3)]});g(b,'a_2',function(){return[new a('iqU',-1,3),new a('abl',-1,3),new a('Ièr',-1,4),new a('ièr',-1,4),new a('eus',-1,2),new a('iv',-1,1)]});g(b,'a_3',function(){return[new a('ic',-1,2),new a('abil',-1,1),new a('iv',-1,3)]});g(b,'a_4',function(){return[new a('iqUe',-1,1),new a('atrice',-1,2),new a('ance',-1,1),new a('ence',-1,5),new a('logie',-1,3),new a('able',-1,1),new a('isme',-1,1),new a('euse',-1,11),new a('iste',-1,1),new a('ive',-1,8),new a('if',-1,8),new a('usion',-1,4),new a('ation',-1,2),new a('ution',-1,4),new a('ateur',-1,2),new a('iqUes',-1,1),new a('atrices',-1,2),new a('ances',-1,1),new a('ences',-1,5),new a('logies',-1,3),new a('ables',-1,1),new a('ismes',-1,1),new a('euses',-1,11),new a('istes',-1,1),new a('ives',-1,8),new a('ifs',-1,8),new a('usions',-1,4),new a('ations',-1,2),new a('utions',-1,4),new a('ateurs',-1,2),new a('ments',-1,15),new a('ements',30,6),new a('issements',31,12),new a('ités',-1,7),new a('ment',-1,15),new a('ement',34,6),new a('issement',35,12),new a('amment',34,13),new a('emment',34,14),new a('aux',-1,10),new a('eaux',39,9),new a('eux',-1,1),new a('ité',-1,7)]});g(b,'a_5',function(){return[new a('ira',-1,1),new a('ie',-1,1),new a('isse',-1,1),new a('issante',-1,1),new a('i',-1,1),new a('irai',4,1),new a('ir',-1,1),new a('iras',-1,1),new a('ies',-1,1),new a('îmes',-1,1),new a('isses',-1,1),new a('issantes',-1,1),new a('îtes',-1,1),new a('is',-1,1),new a('irais',13,1),new a('issais',13,1),new a('irions',-1,1),new a('issions',-1,1),new a('irons',-1,1),new a('issons',-1,1),new a('issants',-1,1),new a('it',-1,1),new a('irait',21,1),new a('issait',21,1),new a('issant',-1,1),new a('iraIent',-1,1),new a('issaIent',-1,1),new a('irent',-1,1),new a('issent',-1,1),new a('iront',-1,1),new a('ît',-1,1),new a('iriez',-1,1),new a('issiez',-1,1),new a('irez',-1,1),new a('issez',-1,1)]});g(b,'a_6',function(){return[new a('a',-1,3),new a('era',0,2),new a('asse',-1,3),new a('ante',-1,3),new a('ée',-1,2),new a('ai',-1,3),new a('erai',5,2),new a('er',-1,2),new a('as',-1,3),new a('eras',8,2),new a('âmes',-1,3),new a('asses',-1,3),new a('antes',-1,3),new a('âtes',-1,3),new a('ées',-1,2),new a('ais',-1,3),new a('erais',15,2),new a('ions',-1,1),new a('erions',17,2),new a('assions',17,3),new a('erons',-1,2),new a('ants',-1,3),new a('és',-1,2),new a('ait',-1,3),new a('erait',23,2),new a('ant',-1,3),new a('aIent',-1,3),new a('eraIent',26,2),new a('èrent',-1,2),new a('assent',-1,3),new a('eront',-1,2),new a('ât',-1,3),new a('ez',-1,2),new a('iez',32,2),new a('eriez',33,2),new a('assiez',33,3),new a('erez',32,2),new a('é',-1,2)]});g(b,'a_7',function(){return[new a('e',-1,3),new a('Ière',0,2),new a('ière',0,2),new a('ion',-1,1),new a('Ier',-1,2),new a('ier',-1,2),new a('ë',-1,4)]});g(b,'a_8',function(){return[new a('ell',-1,-1),new a('eill',-1,-1),new a('enn',-1,-1),new a('onn',-1,-1),new a('ett',-1,-1)]});g(b,'g_v',function(){return[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,128,130,103,8,5]});g(b,'g_keep_with_s',function(){return[1,65,20,0,0,0,0,0,0,0,0,0,0,0,0,0,128]});var q={'src/stemmer.jsx':{Stemmer:p},'src/french-stemmer.jsx':{FrenchStemmer:b}}}(JSX))
+var Stemmer = JSX.require("src/french-stemmer.jsx").FrenchStemmer;
+"""
+
+
+class SearchFrench(SearchLanguage):
+ lang = 'fr'
+ language_name = 'French'
+ js_stemmer_code = js_stemmer
+ stopwords = french_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('french')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/hu.py b/sphinx/search/hu.py
new file mode 100644
index 00000000..003a98ae
--- /dev/null
+++ b/sphinx/search/hu.py
@@ -0,0 +1,237 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.hu
+ ~~~~~~~~~~~~~~~~
+
+ Hungarian search language: includes the JS Hungarian stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+hungarian_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/hungarian/stop.txt
+| prepared by Anna Tordai
+a
+ahogy
+ahol
+aki
+akik
+akkor
+alatt
+által
+általában
+amely
+amelyek
+amelyekben
+amelyeket
+amelyet
+amelynek
+ami
+amit
+amolyan
+amíg
+amikor
+át
+abban
+ahhoz
+annak
+arra
+arról
+az
+azok
+azon
+azt
+azzal
+azért
+aztán
+azután
+azonban
+bár
+be
+belül
+benne
+cikk
+cikkek
+cikkeket
+csak
+de
+e
+eddig
+egész
+egy
+egyes
+egyetlen
+egyéb
+egyik
+egyre
+ekkor
+el
+elég
+ellen
+elő
+először
+előtt
+első
+én
+éppen
+ebben
+ehhez
+emilyen
+ennek
+erre
+ez
+ezt
+ezek
+ezen
+ezzel
+ezért
+és
+fel
+felé
+hanem
+hiszen
+hogy
+hogyan
+igen
+így
+illetve
+ill.
+ill
+ilyen
+ilyenkor
+ison
+ismét
+itt
+jó
+jól
+jobban
+kell
+kellett
+keresztül
+keressünk
+ki
+kívül
+között
+közül
+legalább
+lehet
+lehetett
+legyen
+lenne
+lenni
+lesz
+lett
+maga
+magát
+majd
+majd
+már
+más
+másik
+meg
+még
+mellett
+mert
+mely
+melyek
+mi
+mit
+míg
+miért
+milyen
+mikor
+minden
+mindent
+mindenki
+mindig
+mint
+mintha
+mivel
+most
+nagy
+nagyobb
+nagyon
+ne
+néha
+nekem
+neki
+nem
+néhány
+nélkül
+nincs
+olyan
+ott
+össze
+Å‘
+Å‘k
+Å‘ket
+pedig
+persze
+rá
+s
+saját
+sem
+semmi
+sok
+sokat
+sokkal
+számára
+szemben
+szerint
+szinte
+talán
+tehát
+teljes
+tovább
+továbbá
+több
+úgy
+ugyanis
+új
+újabb
+újra
+után
+utána
+utolsó
+vagy
+vagyis
+valaki
+valami
+valamint
+való
+vagyok
+van
+vannak
+volt
+voltam
+voltak
+voltunk
+vissza
+vele
+viszont
+volna
+''')
+
+js_stemmer = u"""
+
+var JSX={};(function(h){function j(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function P(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function e(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function O(a,b,c){return a[b]=a[b]/c|0}var u=parseInt;var v=parseFloat;function N(a){return a!==a}var x=isFinite;var y=encodeURIComponent;var z=decodeURIComponent;var B=encodeURI;var C=decodeURI;var E=Object.prototype.toString;var F=Object.prototype.hasOwnProperty;function i(){}h.require=function(b){var a=q[b];return a!==undefined?a:null};h.profilerIsRunning=function(){return i.getResults!=null};h.getProfileResults=function(){return(i.getResults||function(){return{}})()};h.postProfileResults=function(a,b){if(i.postResults==null)throw new Error('profiler has not been turned on');return i.postResults(a,b)};h.resetProfileResults=function(){if(i.resetResults==null)throw new Error('profiler has not been turned on');return i.resetResults()};h.DEBUG=false;function r(){};j([r],Error);function a(a,b,c){this.F=a.length;this.K=a;this.L=b;this.I=c;this.H=null;this.P=null};j([a],Object);function n(){};j([n],Object);function f(){var a;var b;var c;this.G={};a=this.D='';b=this._=0;c=this.A=a.length;this.E=0;this.B=b;this.C=c};j([f],n);function s(a,b){a.D=b.D;a._=b._;a.A=b.A;a.E=b.E;a.B=b.B;a.C=b.C};function k(b,d,c,e){var a;if(b._>=b.A){return false}a=b.D.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function l(a,d,c,e){var b;if(a._>=a.A){return false}b=a.D.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function o(f,m,p){var b;var d;var e;var n;var g;var k;var l;var i;var h;var c;var a;var j;var o;b=0;d=p;e=f._;n=f.A;g=0;k=0;l=false;while(true){i=b+(d-b>>>1);h=0;c=g<k?g:k;a=m[i];for(j=c;j<a.F;j++){if(e+c===n){h=-1;break}h=f.D.charCodeAt(e+c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){d=i;k=c}else{b=i;g=c}if(d-b<=1){if(b>0){break}if(d===b){break}if(l){break}l=true}}while(true){a=m[b];if(g>=a.F){f._=e+a.F|0;if(a.H==null){return a.I}o=a.H(a.P);f._=e+a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function d(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.E;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.F-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.D.charCodeAt(e-1-c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.F){d._=e-a.F|0;if(a.H==null){return a.I}o=a.H(d);d._=e-a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function A(a,b,d,e){var c;c=e.length-(d-b);a.D=a.D.slice(0,b)+e+a.D.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function b(a,f){var b;var c;var d;var e;b=false;if((c=a.B)<0||c>(d=a.C)||d>(e=a.A)||e>a.D.length?false:true){A(a,a.B,a.C,f);b=true}return b};f.prototype.J=function(){return false};f.prototype.e=function(b){var a;var c;var d;var e;a=this.G['.'+b];if(a==null){c=this.D=b;d=this._=0;e=this.A=c.length;this.E=0;this.B=d;this.C=e;this.J();a=this.D;this.G['.'+b]=a}return a};f.prototype.stemWord=f.prototype.e;f.prototype.f=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.G['.'+c];if(a==null){f=this.D=c;g=this._=0;h=this.A=f.length;this.E=0;this.B=g;this.C=h;this.J();a=this.D;this.G['.'+c]=a}d.push(a)}return d};f.prototype.stemWords=f.prototype.f;function c(){f.call(this);this.I_p1=0};j([c],f);c.prototype.M=function(a){this.I_p1=a.I_p1;s(this,a)};c.prototype.copy_from=c.prototype.M;c.prototype.X=function(){var m;var b;var j;var d;var e;var a;var f;var g;var h;var n;var i;this.I_p1=this.A;d=true;b:while(d===true){d=false;m=this._;e=true;a:while(e===true){e=false;if(!k(this,c.g_v,97,252)){break a}c:while(true){b=this._;a=true;d:while(a===true){a=false;if(!l(this,c.g_v,97,252)){break d}this._=b;break c}n=this._=b;if(n>=this.A){break a}this._++}f=true;c:while(f===true){f=false;j=this._;g=true;d:while(g===true){g=false;if(o(this,c.a_0,8)===0){break d}break c}i=this._=j;if(i>=this.A){break a}this._++}this.I_p1=this._;break b}this._=m;if(!l(this,c.g_v,97,252)){return false}a:while(true){h=true;c:while(h===true){h=false;if(!k(this,c.g_v,97,252)){break c}break a}if(this._>=this.A){return false}this._++}this.I_p1=this._}return true};c.prototype.r_mark_regions=c.prototype.X;function D(a){var j;var d;var n;var e;var b;var f;var g;var h;var i;var p;var m;a.I_p1=a.A;e=true;b:while(e===true){e=false;j=a._;b=true;a:while(b===true){b=false;if(!k(a,c.g_v,97,252)){break a}c:while(true){d=a._;f=true;d:while(f===true){f=false;if(!l(a,c.g_v,97,252)){break d}a._=d;break c}p=a._=d;if(p>=a.A){break a}a._++}g=true;c:while(g===true){g=false;n=a._;h=true;d:while(h===true){h=false;if(o(a,c.a_0,8)===0){break d}break c}m=a._=n;if(m>=a.A){break a}a._++}a.I_p1=a._;break b}a._=j;if(!l(a,c.g_v,97,252)){return false}a:while(true){i=true;c:while(i===true){i=false;if(!k(a,c.g_v,97,252)){break c}break a}if(a._>=a.A){return false}a._++}a.I_p1=a._}return true};c.prototype.Q=function(){return!(this.I_p1<=this._)?false:true};c.prototype.r_R1=c.prototype.Q;c.prototype.d=function(){var a;var e;this.C=this._;a=d(this,c.a_1,2);if(a===0){return false}this.B=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}switch(a){case 0:return false;case 1:if(!b(this,'a')){return false}break;case 2:if(!b(this,'e')){return false}break}return true};c.prototype.r_v_ending=c.prototype.d;function p(a){var e;var f;a.C=a._;e=d(a,c.a_1,2);if(e===0){return false}a.B=f=a._;if(!(!(a.I_p1<=f)?false:true)){return false}switch(e){case 0:return false;case 1:if(!b(a,'a')){return false}break;case 2:if(!b(a,'e')){return false}break}return true};c.prototype.U=function(){var a;a=this.A-this._;if(d(this,c.a_2,23)===0){return false}this._=this.A-a;return true};c.prototype.r_double=c.prototype.U;function g(a){var b;b=a.A-a._;if(d(a,c.a_2,23)===0){return false}a._=a.A-b;return true};c.prototype.c=function(){var a;var c;var d;if(this._<=this.E){return false}this._--;this.C=c=this._;a=c-1|0;if(this.E>a||a>this.A){return false}d=this._=a;this.B=d;return!b(this,'')?false:true};c.prototype.r_undouble=c.prototype.c;function m(a){var c;var d;var e;if(a._<=a.E){return false}a._--;a.C=d=a._;c=d-1|0;if(a.E>c||c>a.A){return false}e=a._=c;a.B=e;return!b(a,'')?false:true};c.prototype.W=function(){var a;var e;this.C=this._;a=d(this,c.a_3,2);if(a===0){return false}this.B=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}switch(a){case 0:return false;case 1:if(!g(this)){return false}break;case 2:if(!g(this)){return false}break}return!b(this,'')?false:!m(this)?false:true};c.prototype.r_instrum=c.prototype.W;function H(a){var e;var f;a.C=a._;e=d(a,c.a_3,2);if(e===0){return false}a.B=f=a._;if(!(!(a.I_p1<=f)?false:true)){return false}switch(e){case 0:return false;case 1:if(!g(a)){return false}break;case 2:if(!g(a)){return false}break}return!b(a,'')?false:!m(a)?false:true};c.prototype.R=function(){var a;this.C=this._;if(d(this,c.a_4,44)===0){return false}this.B=a=this._;return!(!(this.I_p1<=a)?false:true)?false:!b(this,'')?false:!p(this)?false:true};c.prototype.r_case=c.prototype.R;function I(a){var e;a.C=a._;if(d(a,c.a_4,44)===0){return false}a.B=e=a._;return!(!(a.I_p1<=e)?false:true)?false:!b(a,'')?false:!p(a)?false:true};c.prototype.T=function(){var a;var e;this.C=this._;a=d(this,c.a_5,3);if(a===0){return false}this.B=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}switch(a){case 0:return false;case 1:if(!b(this,'e')){return false}break;case 2:if(!b(this,'a')){return false}break;case 3:if(!b(this,'a')){return false}break}return true};c.prototype.r_case_special=c.prototype.T;function J(a){var e;var f;a.C=a._;e=d(a,c.a_5,3);if(e===0){return false}a.B=f=a._;if(!(!(a.I_p1<=f)?false:true)){return false}switch(e){case 0:return false;case 1:if(!b(a,'e')){return false}break;case 2:if(!b(a,'a')){return false}break;case 3:if(!b(a,'a')){return false}break}return true};c.prototype.S=function(){var a;var e;this.C=this._;a=d(this,c.a_6,6);if(a===0){return false}this.B=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}switch(a){case 0:return false;case 1:if(!b(this,'')){return false}break;case 2:if(!b(this,'')){return false}break;case 3:if(!b(this,'a')){return false}break;case 4:if(!b(this,'e')){return false}break}return true};c.prototype.r_case_other=c.prototype.S;function K(a){var e;var f;a.C=a._;e=d(a,c.a_6,6);if(e===0){return false}a.B=f=a._;if(!(!(a.I_p1<=f)?false:true)){return false}switch(e){case 0:return false;case 1:if(!b(a,'')){return false}break;case 2:if(!b(a,'')){return false}break;case 3:if(!b(a,'a')){return false}break;case 4:if(!b(a,'e')){return false}break}return true};c.prototype.V=function(){var a;var e;this.C=this._;a=d(this,c.a_7,2);if(a===0){return false}this.B=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}switch(a){case 0:return false;case 1:if(!g(this)){return false}break;case 2:if(!g(this)){return false}break}return!b(this,'')?false:!m(this)?false:true};c.prototype.r_factive=c.prototype.V;function L(a){var e;var f;a.C=a._;e=d(a,c.a_7,2);if(e===0){return false}a.B=f=a._;if(!(!(a.I_p1<=f)?false:true)){return false}switch(e){case 0:return false;case 1:if(!g(a)){return false}break;case 2:if(!g(a)){return false}break}return!b(a,'')?false:!m(a)?false:true};c.prototype.a=function(){var a;var e;this.C=this._;a=d(this,c.a_8,7);if(a===0){return false}this.B=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}switch(a){case 0:return false;case 1:if(!b(this,'a')){return false}break;case 2:if(!b(this,'e')){return false}break;case 3:if(!b(this,'')){return false}break;case 4:if(!b(this,'')){return false}break;case 5:if(!b(this,'')){return false}break;case 6:if(!b(this,'')){return false}break;case 7:if(!b(this,'')){return false}break}return true};c.prototype.r_plural=c.prototype.a;function M(a){var e;var f;a.C=a._;e=d(a,c.a_8,7);if(e===0){return false}a.B=f=a._;if(!(!(a.I_p1<=f)?false:true)){return false}switch(e){case 0:return false;case 1:if(!b(a,'a')){return false}break;case 2:if(!b(a,'e')){return false}break;case 3:if(!b(a,'')){return false}break;case 4:if(!b(a,'')){return false}break;case 5:if(!b(a,'')){return false}break;case 6:if(!b(a,'')){return false}break;case 7:if(!b(a,'')){return false}break}return true};c.prototype.Y=function(){var a;var e;this.C=this._;a=d(this,c.a_9,12);if(a===0){return false}this.B=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}switch(a){case 0:return false;case 1:if(!b(this,'')){return false}break;case 2:if(!b(this,'e')){return false}break;case 3:if(!b(this,'a')){return false}break;case 4:if(!b(this,'')){return false}break;case 5:if(!b(this,'e')){return false}break;case 6:if(!b(this,'a')){return false}break;case 7:if(!b(this,'')){return false}break;case 8:if(!b(this,'e')){return false}break;case 9:if(!b(this,'')){return false}break}return true};c.prototype.r_owned=c.prototype.Y;function w(a){var e;var f;a.C=a._;e=d(a,c.a_9,12);if(e===0){return false}a.B=f=a._;if(!(!(a.I_p1<=f)?false:true)){return false}switch(e){case 0:return false;case 1:if(!b(a,'')){return false}break;case 2:if(!b(a,'e')){return false}break;case 3:if(!b(a,'a')){return false}break;case 4:if(!b(a,'')){return false}break;case 5:if(!b(a,'e')){return false}break;case 6:if(!b(a,'a')){return false}break;case 7:if(!b(a,'')){return false}break;case 8:if(!b(a,'e')){return false}break;case 9:if(!b(a,'')){return false}break}return true};c.prototype.b=function(){var a;var e;this.C=this._;a=d(this,c.a_10,31);if(a===0){return false}this.B=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}switch(a){case 0:return false;case 1:if(!b(this,'')){return false}break;case 2:if(!b(this,'a')){return false}break;case 3:if(!b(this,'e')){return false}break;case 4:if(!b(this,'')){return false}break;case 5:if(!b(this,'a')){return false}break;case 6:if(!b(this,'e')){return false}break;case 7:if(!b(this,'')){return false}break;case 8:if(!b(this,'')){return false}break;case 9:if(!b(this,'')){return false}break;case 10:if(!b(this,'a')){return false}break;case 11:if(!b(this,'e')){return false}break;case 12:if(!b(this,'')){return false}break;case 13:if(!b(this,'')){return false}break;case 14:if(!b(this,'a')){return false}break;case 15:if(!b(this,'e')){return false}break;case 16:if(!b(this,'')){return false}break;case 17:if(!b(this,'')){return false}break;case 18:if(!b(this,'')){return false}break;case 19:if(!b(this,'a')){return false}break;case 20:if(!b(this,'e')){return false}break}return true};c.prototype.r_sing_owner=c.prototype.b;function t(a){var e;var f;a.C=a._;e=d(a,c.a_10,31);if(e===0){return false}a.B=f=a._;if(!(!(a.I_p1<=f)?false:true)){return false}switch(e){case 0:return false;case 1:if(!b(a,'')){return false}break;case 2:if(!b(a,'a')){return false}break;case 3:if(!b(a,'e')){return false}break;case 4:if(!b(a,'')){return false}break;case 5:if(!b(a,'a')){return false}break;case 6:if(!b(a,'e')){return false}break;case 7:if(!b(a,'')){return false}break;case 8:if(!b(a,'')){return false}break;case 9:if(!b(a,'')){return false}break;case 10:if(!b(a,'a')){return false}break;case 11:if(!b(a,'e')){return false}break;case 12:if(!b(a,'')){return false}break;case 13:if(!b(a,'')){return false}break;case 14:if(!b(a,'a')){return false}break;case 15:if(!b(a,'e')){return false}break;case 16:if(!b(a,'')){return false}break;case 17:if(!b(a,'')){return false}break;case 18:if(!b(a,'')){return false}break;case 19:if(!b(a,'a')){return false}break;case 20:if(!b(a,'e')){return false}break}return true};c.prototype.Z=function(){var a;var e;this.C=this._;a=d(this,c.a_11,42);if(a===0){return false}this.B=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}switch(a){case 0:return false;case 1:if(!b(this,'')){return false}break;case 2:if(!b(this,'a')){return false}break;case 3:if(!b(this,'e')){return false}break;case 4:if(!b(this,'')){return false}break;case 5:if(!b(this,'')){return false}break;case 6:if(!b(this,'')){return false}break;case 7:if(!b(this,'a')){return false}break;case 8:if(!b(this,'e')){return false}break;case 9:if(!b(this,'')){return false}break;case 10:if(!b(this,'')){return false}break;case 11:if(!b(this,'')){return false}break;case 12:if(!b(this,'a')){return false}break;case 13:if(!b(this,'e')){return false}break;case 14:if(!b(this,'')){return false}break;case 15:if(!b(this,'')){return false}break;case 16:if(!b(this,'')){return false}break;case 17:if(!b(this,'')){return false}break;case 18:if(!b(this,'a')){return false}break;case 19:if(!b(this,'e')){return false}break;case 20:if(!b(this,'')){return false}break;case 21:if(!b(this,'')){return false}break;case 22:if(!b(this,'a')){return false}break;case 23:if(!b(this,'e')){return false}break;case 24:if(!b(this,'')){return false}break;case 25:if(!b(this,'')){return false}break;case 26:if(!b(this,'')){return false}break;case 27:if(!b(this,'a')){return false}break;case 28:if(!b(this,'e')){return false}break;case 29:if(!b(this,'')){return false}break}return true};c.prototype.r_plur_owner=c.prototype.Z;function G(a){var e;var f;a.C=a._;e=d(a,c.a_11,42);if(e===0){return false}a.B=f=a._;if(!(!(a.I_p1<=f)?false:true)){return false}switch(e){case 0:return false;case 1:if(!b(a,'')){return false}break;case 2:if(!b(a,'a')){return false}break;case 3:if(!b(a,'e')){return false}break;case 4:if(!b(a,'')){return false}break;case 5:if(!b(a,'')){return false}break;case 6:if(!b(a,'')){return false}break;case 7:if(!b(a,'a')){return false}break;case 8:if(!b(a,'e')){return false}break;case 9:if(!b(a,'')){return false}break;case 10:if(!b(a,'')){return false}break;case 11:if(!b(a,'')){return false}break;case 12:if(!b(a,'a')){return false}break;case 13:if(!b(a,'e')){return false}break;case 14:if(!b(a,'')){return false}break;case 15:if(!b(a,'')){return false}break;case 16:if(!b(a,'')){return false}break;case 17:if(!b(a,'')){return false}break;case 18:if(!b(a,'a')){return false}break;case 19:if(!b(a,'e')){return false}break;case 20:if(!b(a,'')){return false}break;case 21:if(!b(a,'')){return false}break;case 22:if(!b(a,'a')){return false}break;case 23:if(!b(a,'e')){return false}break;case 24:if(!b(a,'')){return false}break;case 25:if(!b(a,'')){return false}break;case 26:if(!b(a,'')){return false}break;case 27:if(!b(a,'a')){return false}break;case 28:if(!b(a,'e')){return false}break;case 29:if(!b(a,'')){return false}break}return true};c.prototype.J=function(){var s;var l;var m;var n;var o;var p;var q;var r;var u;var b;var c;var d;var e;var f;var g;var h;var i;var a;var j;var v;var x;var y;var z;var A;var B;var C;var E;var F;var N;var O;var P;var Q;var R;var S;var T;var k;s=this._;b=true;a:while(b===true){b=false;if(!D(this)){break a}}v=this._=s;this.E=v;y=this._=x=this.A;l=x-y;c=true;a:while(c===true){c=false;if(!H(this)){break a}}A=this._=(z=this.A)-l;m=z-A;d=true;a:while(d===true){d=false;if(!I(this)){break a}}C=this._=(B=this.A)-m;n=B-C;e=true;a:while(e===true){e=false;if(!J(this)){break a}}F=this._=(E=this.A)-n;o=E-F;f=true;a:while(f===true){f=false;if(!K(this)){break a}}O=this._=(N=this.A)-o;p=N-O;g=true;a:while(g===true){g=false;if(!L(this)){break a}}Q=this._=(P=this.A)-p;q=P-Q;h=true;a:while(h===true){h=false;if(!w(this)){break a}}S=this._=(R=this.A)-q;r=R-S;i=true;a:while(i===true){i=false;if(!t(this)){break a}}k=this._=(T=this.A)-r;u=T-k;a=true;a:while(a===true){a=false;if(!G(this)){break a}}this._=this.A-u;j=true;a:while(j===true){j=false;if(!M(this)){break a}}this._=this.E;return true};c.prototype.stem=c.prototype.J;c.prototype.N=function(a){return a instanceof c};c.prototype.equals=c.prototype.N;c.prototype.O=function(){var c;var a;var b;var d;c='HungarianStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};c.prototype.hashCode=c.prototype.O;c.serialVersionUID=1;e(c,'methodObject',function(){return new c});e(c,'a_0',function(){return[new a('cs',-1,-1),new a('dzs',-1,-1),new a('gy',-1,-1),new a('ly',-1,-1),new a('ny',-1,-1),new a('sz',-1,-1),new a('ty',-1,-1),new a('zs',-1,-1)]});e(c,'a_1',function(){return[new a('á',-1,1),new a('é',-1,2)]});e(c,'a_2',function(){return[new a('bb',-1,-1),new a('cc',-1,-1),new a('dd',-1,-1),new a('ff',-1,-1),new a('gg',-1,-1),new a('jj',-1,-1),new a('kk',-1,-1),new a('ll',-1,-1),new a('mm',-1,-1),new a('nn',-1,-1),new a('pp',-1,-1),new a('rr',-1,-1),new a('ccs',-1,-1),new a('ss',-1,-1),new a('zzs',-1,-1),new a('tt',-1,-1),new a('vv',-1,-1),new a('ggy',-1,-1),new a('lly',-1,-1),new a('nny',-1,-1),new a('tty',-1,-1),new a('ssz',-1,-1),new a('zz',-1,-1)]});e(c,'a_3',function(){return[new a('al',-1,1),new a('el',-1,2)]});e(c,'a_4',function(){return[new a('ba',-1,-1),new a('ra',-1,-1),new a('be',-1,-1),new a('re',-1,-1),new a('ig',-1,-1),new a('nak',-1,-1),new a('nek',-1,-1),new a('val',-1,-1),new a('vel',-1,-1),new a('ul',-1,-1),new a('nál',-1,-1),new a('nél',-1,-1),new a('ból',-1,-1),new a('ról',-1,-1),new a('tól',-1,-1),new a('bõl',-1,-1),new a('rõl',-1,-1),new a('tõl',-1,-1),new a('ül',-1,-1),new a('n',-1,-1),new a('an',19,-1),new a('ban',20,-1),new a('en',19,-1),new a('ben',22,-1),new a('képpen',22,-1),new a('on',19,-1),new a('ön',19,-1),new a('képp',-1,-1),new a('kor',-1,-1),new a('t',-1,-1),new a('at',29,-1),new a('et',29,-1),new a('ként',29,-1),new a('anként',32,-1),new a('enként',32,-1),new a('onként',32,-1),new a('ot',29,-1),new a('ért',29,-1),new a('öt',29,-1),new a('hez',-1,-1),new a('hoz',-1,-1),new a('höz',-1,-1),new a('vá',-1,-1),new a('vé',-1,-1)]});e(c,'a_5',function(){return[new a('án',-1,2),new a('én',-1,1),new a('ánként',-1,3)]});e(c,'a_6',function(){return[new a('stul',-1,2),new a('astul',0,1),new a('ástul',0,3),new a('stül',-1,2),new a('estül',3,1),new a('éstül',3,4)]});e(c,'a_7',function(){return[new a('á',-1,1),new a('é',-1,2)]});e(c,'a_8',function(){return[new a('k',-1,7),new a('ak',0,4),new a('ek',0,6),new a('ok',0,5),new a('ák',0,1),new a('ék',0,2),new a('ök',0,3)]});e(c,'a_9',function(){return[new a('éi',-1,7),new a('áéi',0,6),new a('ééi',0,5),new a('é',-1,9),new a('ké',3,4),new a('aké',4,1),new a('eké',4,1),new a('oké',4,1),new a('áké',4,3),new a('éké',4,2),new a('öké',4,1),new a('éé',3,8)]});e(c,'a_10',function(){return[new a('a',-1,18),new a('ja',0,17),new a('d',-1,16),new a('ad',2,13),new a('ed',2,13),new a('od',2,13),new a('ád',2,14),new a('éd',2,15),new a('öd',2,13),new a('e',-1,18),new a('je',9,17),new a('nk',-1,4),new a('unk',11,1),new a('ánk',11,2),new a('énk',11,3),new a('ünk',11,1),new a('uk',-1,8),new a('juk',16,7),new a('ájuk',17,5),new a('ük',-1,8),new a('jük',19,7),new a('éjük',20,6),new a('m',-1,12),new a('am',22,9),new a('em',22,9),new a('om',22,9),new a('ám',22,10),new a('ém',22,11),new a('o',-1,18),new a('á',-1,19),new a('é',-1,20)]});e(c,'a_11',function(){return[new a('id',-1,10),new a('aid',0,9),new a('jaid',1,6),new a('eid',0,9),new a('jeid',3,6),new a('áid',0,7),new a('éid',0,8),new a('i',-1,15),new a('ai',7,14),new a('jai',8,11),new a('ei',7,14),new a('jei',10,11),new a('ái',7,12),new a('éi',7,13),new a('itek',-1,24),new a('eitek',14,21),new a('jeitek',15,20),new a('éitek',14,23),new a('ik',-1,29),new a('aik',18,26),new a('jaik',19,25),new a('eik',18,26),new a('jeik',21,25),new a('áik',18,27),new a('éik',18,28),new a('ink',-1,20),new a('aink',25,17),new a('jaink',26,16),new a('eink',25,17),new a('jeink',28,16),new a('áink',25,18),new a('éink',25,19),new a('aitok',-1,21),new a('jaitok',32,20),new a('áitok',-1,22),new a('im',-1,5),new a('aim',35,4),new a('jaim',36,1),new a('eim',35,4),new a('jeim',38,1),new a('áim',35,2),new a('éim',35,3)]});e(c,'g_v',function(){return[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,52,14]});var q={'src/stemmer.jsx':{Stemmer:n},'src/hungarian-stemmer.jsx':{HungarianStemmer:c}}}(JSX))
+var Stemmer = JSX.require("src/hungarian-stemmer.jsx").HungarianStemmer;
+"""
+
+
+class SearchHungarian(SearchLanguage):
+ lang = 'hu'
+ language_name = 'Hungarian'
+ js_stemmer_code = js_stemmer
+ stopwords = hungarian_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('hungarian')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/it.py b/sphinx/search/it.py
new file mode 100644
index 00000000..1b8d51ec
--- /dev/null
+++ b/sphinx/search/it.py
@@ -0,0 +1,326 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.it
+ ~~~~~~~~~~~~~~~~
+
+ Italian search language: includes the JS Italian stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+italian_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/italian/stop.txt
+ad | a (to) before vowel
+al | a + il
+allo | a + lo
+ai | a + i
+agli | a + gli
+all | a + l'
+agl | a + gl'
+alla | a + la
+alle | a + le
+con | with
+col | con + il
+coi | con + i (forms collo, cogli etc are now very rare)
+da | from
+dal | da + il
+dallo | da + lo
+dai | da + i
+dagli | da + gli
+dall | da + l'
+dagl | da + gll'
+dalla | da + la
+dalle | da + le
+di | of
+del | di + il
+dello | di + lo
+dei | di + i
+degli | di + gli
+dell | di + l'
+degl | di + gl'
+della | di + la
+delle | di + le
+in | in
+nel | in + el
+nello | in + lo
+nei | in + i
+negli | in + gli
+nell | in + l'
+negl | in + gl'
+nella | in + la
+nelle | in + le
+su | on
+sul | su + il
+sullo | su + lo
+sui | su + i
+sugli | su + gli
+sull | su + l'
+sugl | su + gl'
+sulla | su + la
+sulle | su + le
+per | through, by
+tra | among
+contro | against
+io | I
+tu | thou
+lui | he
+lei | she
+noi | we
+voi | you
+loro | they
+mio | my
+mia |
+miei |
+mie |
+tuo |
+tua |
+tuoi | thy
+tue |
+suo |
+sua |
+suoi | his, her
+sue |
+nostro | our
+nostra |
+nostri |
+nostre |
+vostro | your
+vostra |
+vostri |
+vostre |
+mi | me
+ti | thee
+ci | us, there
+vi | you, there
+lo | him, the
+la | her, the
+li | them
+le | them, the
+gli | to him, the
+ne | from there etc
+il | the
+un | a
+uno | a
+una | a
+ma | but
+ed | and
+se | if
+perché | why, because
+anche | also
+come | how
+dov | where (as dov')
+dove | where
+che | who, that
+chi | who
+cui | whom
+non | not
+più | more
+quale | who, that
+quanto | how much
+quanti |
+quanta |
+quante |
+quello | that
+quelli |
+quella |
+quelle |
+questo | this
+questi |
+questa |
+queste |
+si | yes
+tutto | all
+tutti | all
+
+ | single letter forms:
+
+a | at
+c | as c' for ce or ci
+e | and
+i | the
+l | as l'
+o | or
+
+ | forms of avere, to have (not including the infinitive):
+
+ho
+hai
+ha
+abbiamo
+avete
+hanno
+abbia
+abbiate
+abbiano
+avrò
+avrai
+avrà
+avremo
+avrete
+avranno
+avrei
+avresti
+avrebbe
+avremmo
+avreste
+avrebbero
+avevo
+avevi
+aveva
+avevamo
+avevate
+avevano
+ebbi
+avesti
+ebbe
+avemmo
+aveste
+ebbero
+avessi
+avesse
+avessimo
+avessero
+avendo
+avuto
+avuta
+avuti
+avute
+
+ | forms of essere, to be (not including the infinitive):
+sono
+sei
+è
+siamo
+siete
+sia
+siate
+siano
+sarò
+sarai
+sarà
+saremo
+sarete
+saranno
+sarei
+saresti
+sarebbe
+saremmo
+sareste
+sarebbero
+ero
+eri
+era
+eravamo
+eravate
+erano
+fui
+fosti
+fu
+fummo
+foste
+furono
+fossi
+fosse
+fossimo
+fossero
+essendo
+
+ | forms of fare, to do (not including the infinitive, fa, fat-):
+faccio
+fai
+facciamo
+fanno
+faccia
+facciate
+facciano
+farò
+farai
+farà
+faremo
+farete
+faranno
+farei
+faresti
+farebbe
+faremmo
+fareste
+farebbero
+facevo
+facevi
+faceva
+facevamo
+facevate
+facevano
+feci
+facesti
+fece
+facemmo
+faceste
+fecero
+facessi
+facesse
+facessimo
+facessero
+facendo
+
+ | forms of stare, to be (not including the infinitive):
+sto
+stai
+sta
+stiamo
+stanno
+stia
+stiate
+stiano
+starò
+starai
+starà
+staremo
+starete
+staranno
+starei
+staresti
+starebbe
+staremmo
+stareste
+starebbero
+stavo
+stavi
+stava
+stavamo
+stavate
+stavano
+stetti
+stesti
+stette
+stemmo
+steste
+stettero
+stessi
+stesse
+stessimo
+stessero
+''')
+
+js_stemmer = u"""
+var JSX={};(function(k){function l(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function K(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function e(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function L(a,b,c){return a[b]=a[b]/c|0}var r=parseInt;var B=parseFloat;function M(a){return a!==a}var z=isFinite;var y=encodeURIComponent;var x=decodeURIComponent;var w=encodeURI;var u=decodeURI;var t=Object.prototype.toString;var C=Object.prototype.hasOwnProperty;function j(){}k.require=function(b){var a=q[b];return a!==undefined?a:null};k.profilerIsRunning=function(){return j.getResults!=null};k.getProfileResults=function(){return(j.getResults||function(){return{}})()};k.postProfileResults=function(a,b){if(j.postResults==null)throw new Error('profiler has not been turned on');return j.postResults(a,b)};k.resetProfileResults=function(){if(j.resetResults==null)throw new Error('profiler has not been turned on');return j.resetResults()};k.DEBUG=false;function s(){};l([s],Error);function a(a,b,c){this.F=a.length;this.K=a;this.L=b;this.I=c;this.H=null;this.P=null};l([a],Object);function p(){};l([p],Object);function i(){var a;var b;var c;this.G={};a=this.E='';b=this._=0;c=this.A=a.length;this.D=0;this.C=b;this.B=c};l([i],p);function v(a,b){a.E=b.E;a._=b._;a.A=b.A;a.D=b.D;a.C=b.C;a.B=b.B};function d(b,d,c,e){var a;if(b._>=b.A){return false}a=b.E.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function m(b,d,c,e){var a;if(b._<=b.D){return false}a=b.E.charCodeAt(b._-1);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._--;return true};function h(a,d,c,e){var b;if(a._>=a.A){return false}b=a.E.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function o(a,b,d){var c;if(a.A-a._<b){return false}if(a.E.slice(c=a._,c+b)!==d){return false}a._+=b;return true};function g(a,b,d){var c;if(a._-a.D<b){return false}if(a.E.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function n(f,m,p){var b;var d;var e;var n;var g;var k;var l;var i;var h;var c;var a;var j;var o;b=0;d=p;e=f._;n=f.A;g=0;k=0;l=false;while(true){i=b+(d-b>>>1);h=0;c=g<k?g:k;a=m[i];for(j=c;j<a.F;j++){if(e+c===n){h=-1;break}h=f.E.charCodeAt(e+c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){d=i;k=c}else{b=i;g=c}if(d-b<=1){if(b>0){break}if(d===b){break}if(l){break}l=true}}while(true){a=m[b];if(g>=a.F){f._=e+a.F|0;if(a.H==null){return a.I}o=a.H(a.P);f._=e+a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function f(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.D;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.F-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.E.charCodeAt(e-1-c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.F){d._=e-a.F|0;if(a.H==null){return a.I}o=a.H(d);d._=e-a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function D(a,b,d,e){var c;c=e.length-(d-b);a.E=a.E.slice(0,b)+e+a.E.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function c(a,f){var b;var c;var d;var e;b=false;if((c=a.C)<0||c>(d=a.B)||d>(e=a.A)||e>a.E.length?false:true){D(a,a.C,a.B,f);b=true}return b};i.prototype.J=function(){return false};i.prototype.a=function(b){var a;var c;var d;var e;a=this.G['.'+b];if(a==null){c=this.E=b;d=this._=0;e=this.A=c.length;this.D=0;this.C=d;this.B=e;this.J();a=this.E;this.G['.'+b]=a}return a};i.prototype.stemWord=i.prototype.a;i.prototype.b=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.G['.'+c];if(a==null){f=this.E=c;g=this._=0;h=this.A=f.length;this.D=0;this.C=g;this.B=h;this.J();a=this.E;this.G['.'+c]=a}d.push(a)}return d};i.prototype.stemWords=i.prototype.b;function b(){i.call(this);this.I_p2=0;this.I_p1=0;this.I_pV=0};l([b],i);b.prototype.M=function(a){this.I_p2=a.I_p2;this.I_p1=a.I_p1;this.I_pV=a.I_pV;v(this,a)};b.prototype.copy_from=b.prototype.M;b.prototype.W=function(){var e;var p;var q;var l;var a;var k;var f;var g;var h;var i;var j;var m;p=this._;b:while(true){q=this._;f=true;a:while(f===true){f=false;this.C=this._;e=n(this,b.a_0,7);if(e===0){break a}this.B=this._;switch(e){case 0:break a;case 1:if(!c(this,'à')){return false}break;case 2:if(!c(this,'è')){return false}break;case 3:if(!c(this,'ì')){return false}break;case 4:if(!c(this,'ò')){return false}break;case 5:if(!c(this,'ù')){return false}break;case 6:if(!c(this,'qU')){return false}break;case 7:if(this._>=this.A){break a}this._++;break}continue b}this._=q;break b}this._=p;b:while(true){l=this._;g=true;d:while(g===true){g=false;e:while(true){a=this._;h=true;a:while(h===true){h=false;if(!d(this,b.g_v,97,249)){break a}this.C=this._;i=true;f:while(i===true){i=false;k=this._;j=true;c:while(j===true){j=false;if(!o(this,1,'u')){break c}this.B=this._;if(!d(this,b.g_v,97,249)){break c}if(!c(this,'U')){return false}break f}this._=k;if(!o(this,1,'i')){break a}this.B=this._;if(!d(this,b.g_v,97,249)){break a}if(!c(this,'I')){return false}}this._=a;break e}m=this._=a;if(m>=this.A){break d}this._++}continue b}this._=l;break b}return true};b.prototype.r_prelude=b.prototype.W;function G(a){var e;var q;var r;var m;var f;var l;var g;var h;var i;var j;var k;var p;q=a._;b:while(true){r=a._;g=true;a:while(g===true){g=false;a.C=a._;e=n(a,b.a_0,7);if(e===0){break a}a.B=a._;switch(e){case 0:break a;case 1:if(!c(a,'à')){return false}break;case 2:if(!c(a,'è')){return false}break;case 3:if(!c(a,'ì')){return false}break;case 4:if(!c(a,'ò')){return false}break;case 5:if(!c(a,'ù')){return false}break;case 6:if(!c(a,'qU')){return false}break;case 7:if(a._>=a.A){break a}a._++;break}continue b}a._=r;break b}a._=q;b:while(true){m=a._;h=true;d:while(h===true){h=false;e:while(true){f=a._;i=true;a:while(i===true){i=false;if(!d(a,b.g_v,97,249)){break a}a.C=a._;j=true;f:while(j===true){j=false;l=a._;k=true;c:while(k===true){k=false;if(!o(a,1,'u')){break c}a.B=a._;if(!d(a,b.g_v,97,249)){break c}if(!c(a,'U')){return false}break f}a._=l;if(!o(a,1,'i')){break a}a.B=a._;if(!d(a,b.g_v,97,249)){break a}if(!c(a,'I')){return false}}a._=f;break e}p=a._=f;if(p>=a.A){break d}a._++}continue b}a._=m;break b}return true};b.prototype.U=function(){var u;var w;var x;var y;var t;var l;var e;var f;var g;var i;var c;var j;var k;var a;var m;var n;var o;var p;var q;var r;var s;var v;this.I_pV=s=this.A;this.I_p1=s;this.I_p2=s;u=this._;l=true;a:while(l===true){l=false;e=true;g:while(e===true){e=false;w=this._;f=true;b:while(f===true){f=false;if(!d(this,b.g_v,97,249)){break b}g=true;f:while(g===true){g=false;x=this._;i=true;c:while(i===true){i=false;if(!h(this,b.g_v,97,249)){break c}d:while(true){c=true;e:while(c===true){c=false;if(!d(this,b.g_v,97,249)){break e}break d}if(this._>=this.A){break c}this._++}break f}this._=x;if(!d(this,b.g_v,97,249)){break b}c:while(true){j=true;d:while(j===true){j=false;if(!h(this,b.g_v,97,249)){break d}break c}if(this._>=this.A){break b}this._++}}break g}this._=w;if(!h(this,b.g_v,97,249)){break a}k=true;c:while(k===true){k=false;y=this._;a=true;b:while(a===true){a=false;if(!h(this,b.g_v,97,249)){break b}e:while(true){m=true;d:while(m===true){m=false;if(!d(this,b.g_v,97,249)){break d}break e}if(this._>=this.A){break b}this._++}break c}this._=y;if(!d(this,b.g_v,97,249)){break a}if(this._>=this.A){break a}this._++}}this.I_pV=this._}v=this._=u;t=v;n=true;a:while(n===true){n=false;b:while(true){o=true;c:while(o===true){o=false;if(!d(this,b.g_v,97,249)){break c}break b}if(this._>=this.A){break a}this._++}b:while(true){p=true;c:while(p===true){p=false;if(!h(this,b.g_v,97,249)){break c}break b}if(this._>=this.A){break a}this._++}this.I_p1=this._;b:while(true){q=true;c:while(q===true){q=false;if(!d(this,b.g_v,97,249)){break c}break b}if(this._>=this.A){break a}this._++}c:while(true){r=true;b:while(r===true){r=false;if(!h(this,b.g_v,97,249)){break b}break c}if(this._>=this.A){break a}this._++}this.I_p2=this._}this._=t;return true};b.prototype.r_mark_regions=b.prototype.U;function H(a){var x;var y;var z;var u;var v;var l;var e;var f;var g;var i;var j;var k;var c;var m;var n;var o;var p;var q;var r;var s;var t;var w;a.I_pV=t=a.A;a.I_p1=t;a.I_p2=t;x=a._;l=true;a:while(l===true){l=false;e=true;g:while(e===true){e=false;y=a._;f=true;b:while(f===true){f=false;if(!d(a,b.g_v,97,249)){break b}g=true;f:while(g===true){g=false;z=a._;i=true;c:while(i===true){i=false;if(!h(a,b.g_v,97,249)){break c}d:while(true){j=true;e:while(j===true){j=false;if(!d(a,b.g_v,97,249)){break e}break d}if(a._>=a.A){break c}a._++}break f}a._=z;if(!d(a,b.g_v,97,249)){break b}c:while(true){k=true;d:while(k===true){k=false;if(!h(a,b.g_v,97,249)){break d}break c}if(a._>=a.A){break b}a._++}}break g}a._=y;if(!h(a,b.g_v,97,249)){break a}c=true;c:while(c===true){c=false;u=a._;m=true;b:while(m===true){m=false;if(!h(a,b.g_v,97,249)){break b}e:while(true){n=true;d:while(n===true){n=false;if(!d(a,b.g_v,97,249)){break d}break e}if(a._>=a.A){break b}a._++}break c}a._=u;if(!d(a,b.g_v,97,249)){break a}if(a._>=a.A){break a}a._++}}a.I_pV=a._}w=a._=x;v=w;o=true;a:while(o===true){o=false;b:while(true){p=true;c:while(p===true){p=false;if(!d(a,b.g_v,97,249)){break c}break b}if(a._>=a.A){break a}a._++}b:while(true){q=true;c:while(q===true){q=false;if(!h(a,b.g_v,97,249)){break c}break b}if(a._>=a.A){break a}a._++}a.I_p1=a._;b:while(true){r=true;c:while(r===true){r=false;if(!d(a,b.g_v,97,249)){break c}break b}if(a._>=a.A){break a}a._++}c:while(true){s=true;b:while(s===true){s=false;if(!h(a,b.g_v,97,249)){break b}break c}if(a._>=a.A){break a}a._++}a.I_p2=a._}a._=v;return true};b.prototype.V=function(){var a;var e;var d;b:while(true){e=this._;d=true;a:while(d===true){d=false;this.C=this._;a=n(this,b.a_1,3);if(a===0){break a}this.B=this._;switch(a){case 0:break a;case 1:if(!c(this,'i')){return false}break;case 2:if(!c(this,'u')){return false}break;case 3:if(this._>=this.A){break a}this._++;break}continue b}this._=e;break b}return true};b.prototype.r_postlude=b.prototype.V;function I(a){var d;var f;var e;b:while(true){f=a._;e=true;a:while(e===true){e=false;a.C=a._;d=n(a,b.a_1,3);if(d===0){break a}a.B=a._;switch(d){case 0:break a;case 1:if(!c(a,'i')){return false}break;case 2:if(!c(a,'u')){return false}break;case 3:if(a._>=a.A){break a}a._++;break}continue b}a._=f;break b}return true};b.prototype.S=function(){return!(this.I_pV<=this._)?false:true};b.prototype.r_RV=b.prototype.S;b.prototype.Q=function(){return!(this.I_p1<=this._)?false:true};b.prototype.r_R1=b.prototype.Q;b.prototype.R=function(){return!(this.I_p2<=this._)?false:true};b.prototype.r_R2=b.prototype.R;b.prototype.T=function(){var a;this.B=this._;if(f(this,b.a_2,37)===0){return false}this.C=this._;a=f(this,b.a_3,5);if(a===0){return false}if(!(!(this.I_pV<=this._)?false:true)){return false}switch(a){case 0:return false;case 1:if(!c(this,'')){return false}break;case 2:if(!c(this,'e')){return false}break}return true};b.prototype.r_attached_pronoun=b.prototype.T;function J(a){var d;a.B=a._;if(f(a,b.a_2,37)===0){return false}a.C=a._;d=f(a,b.a_3,5);if(d===0){return false}if(!(!(a.I_pV<=a._)?false:true)){return false}switch(d){case 0:return false;case 1:if(!c(a,'')){return false}break;case 2:if(!c(a,'e')){return false}break}return true};b.prototype.X=function(){var a;var j;var d;var h;var e;var k;var i;var l;var m;var o;var p;var q;var r;var n;this.B=this._;a=f(this,b.a_6,51);if(a===0){return false}this.C=this._;switch(a){case 0:return false;case 1:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}break;case 2:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}j=this.A-this._;k=true;a:while(k===true){k=false;this.B=this._;if(!g(this,2,'ic')){this._=this.A-j;break a}this.C=o=this._;if(!(!(this.I_p2<=o)?false:true)){this._=this.A-j;break a}if(!c(this,'')){return false}}break;case 3:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'log')){return false}break;case 4:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'u')){return false}break;case 5:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'ente')){return false}break;case 6:if(!(!(this.I_pV<=this._)?false:true)){return false}if(!c(this,'')){return false}break;case 7:if(!(!(this.I_p1<=this._)?false:true)){return false}if(!c(this,'')){return false}d=this.A-this._;i=true;a:while(i===true){i=false;this.B=this._;a=f(this,b.a_4,4);if(a===0){this._=this.A-d;break a}this.C=p=this._;if(!(!(this.I_p2<=p)?false:true)){this._=this.A-d;break a}if(!c(this,'')){return false}switch(a){case 0:this._=this.A-d;break a;case 1:this.B=this._;if(!g(this,2,'at')){this._=this.A-d;break a}this.C=q=this._;if(!(!(this.I_p2<=q)?false:true)){this._=this.A-d;break a}if(!c(this,'')){return false}break}}break;case 8:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}h=this.A-this._;l=true;a:while(l===true){l=false;this.B=this._;a=f(this,b.a_5,3);if(a===0){this._=this.A-h;break a}this.C=this._;switch(a){case 0:this._=this.A-h;break a;case 1:if(!(!(this.I_p2<=this._)?false:true)){this._=this.A-h;break a}if(!c(this,'')){return false}break}}break;case 9:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}e=this.A-this._;m=true;a:while(m===true){m=false;this.B=this._;if(!g(this,2,'at')){this._=this.A-e;break a}this.C=r=this._;if(!(!(this.I_p2<=r)?false:true)){this._=this.A-e;break a}if(!c(this,'')){return false}this.B=this._;if(!g(this,2,'ic')){this._=this.A-e;break a}this.C=n=this._;if(!(!(this.I_p2<=n)?false:true)){this._=this.A-e;break a}if(!c(this,'')){return false}}break}return true};b.prototype.r_standard_suffix=b.prototype.X;function F(a){var d;var k;var e;var i;var h;var l;var j;var m;var n;var p;var q;var r;var s;var o;a.B=a._;d=f(a,b.a_6,51);if(d===0){return false}a.C=a._;switch(d){case 0:return false;case 1:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}break;case 2:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}k=a.A-a._;l=true;a:while(l===true){l=false;a.B=a._;if(!g(a,2,'ic')){a._=a.A-k;break a}a.C=p=a._;if(!(!(a.I_p2<=p)?false:true)){a._=a.A-k;break a}if(!c(a,'')){return false}}break;case 3:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'log')){return false}break;case 4:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'u')){return false}break;case 5:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'ente')){return false}break;case 6:if(!(!(a.I_pV<=a._)?false:true)){return false}if(!c(a,'')){return false}break;case 7:if(!(!(a.I_p1<=a._)?false:true)){return false}if(!c(a,'')){return false}e=a.A-a._;j=true;a:while(j===true){j=false;a.B=a._;d=f(a,b.a_4,4);if(d===0){a._=a.A-e;break a}a.C=q=a._;if(!(!(a.I_p2<=q)?false:true)){a._=a.A-e;break a}if(!c(a,'')){return false}switch(d){case 0:a._=a.A-e;break a;case 1:a.B=a._;if(!g(a,2,'at')){a._=a.A-e;break a}a.C=r=a._;if(!(!(a.I_p2<=r)?false:true)){a._=a.A-e;break a}if(!c(a,'')){return false}break}}break;case 8:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}i=a.A-a._;m=true;a:while(m===true){m=false;a.B=a._;d=f(a,b.a_5,3);if(d===0){a._=a.A-i;break a}a.C=a._;switch(d){case 0:a._=a.A-i;break a;case 1:if(!(!(a.I_p2<=a._)?false:true)){a._=a.A-i;break a}if(!c(a,'')){return false}break}}break;case 9:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}h=a.A-a._;n=true;a:while(n===true){n=false;a.B=a._;if(!g(a,2,'at')){a._=a.A-h;break a}a.C=s=a._;if(!(!(a.I_p2<=s)?false:true)){a._=a.A-h;break a}if(!c(a,'')){return false}a.B=a._;if(!g(a,2,'ic')){a._=a.A-h;break a}a.C=o=a._;if(!(!(a.I_p2<=o)?false:true)){a._=a.A-h;break a}if(!c(a,'')){return false}}break}return true};b.prototype.Y=function(){var d;var e;var a;var g;var h;var i;e=this.A-(g=this._);if(g<this.I_pV){return false}h=this._=this.I_pV;a=this.D;this.D=h;i=this._=this.A-e;this.B=i;d=f(this,b.a_7,87);if(d===0){this.D=a;return false}this.C=this._;switch(d){case 0:this.D=a;return false;case 1:if(!c(this,'')){return false}break}this.D=a;return true};b.prototype.r_verb_suffix=b.prototype.Y;function E(a){var e;var g;var d;var h;var i;var j;g=a.A-(h=a._);if(h<a.I_pV){return false}i=a._=a.I_pV;d=a.D;a.D=i;j=a._=a.A-g;a.B=j;e=f(a,b.a_7,87);if(e===0){a.D=d;return false}a.C=a._;switch(e){case 0:a.D=d;return false;case 1:if(!c(a,'')){return false}break}a.D=d;return true};b.prototype.Z=function(){var a;var d;var e;var f;var h;var i;a=this.A-this._;e=true;a:while(e===true){e=false;this.B=this._;if(!m(this,b.g_AEIO,97,242)){this._=this.A-a;break a}this.C=h=this._;if(!(!(this.I_pV<=h)?false:true)){this._=this.A-a;break a}if(!c(this,'')){return false}this.B=this._;if(!g(this,1,'i')){this._=this.A-a;break a}this.C=i=this._;if(!(!(this.I_pV<=i)?false:true)){this._=this.A-a;break a}if(!c(this,'')){return false}}d=this.A-this._;f=true;a:while(f===true){f=false;this.B=this._;if(!g(this,1,'h')){this._=this.A-d;break a}this.C=this._;if(!m(this,b.g_CG,99,103)){this._=this.A-d;break a}if(!(!(this.I_pV<=this._)?false:true)){this._=this.A-d;break a}if(!c(this,'')){return false}}return true};b.prototype.r_vowel_suffix=b.prototype.Z;function A(a){var d;var e;var f;var h;var i;var j;d=a.A-a._;f=true;a:while(f===true){f=false;a.B=a._;if(!m(a,b.g_AEIO,97,242)){a._=a.A-d;break a}a.C=i=a._;if(!(!(a.I_pV<=i)?false:true)){a._=a.A-d;break a}if(!c(a,'')){return false}a.B=a._;if(!g(a,1,'i')){a._=a.A-d;break a}a.C=j=a._;if(!(!(a.I_pV<=j)?false:true)){a._=a.A-d;break a}if(!c(a,'')){return false}}e=a.A-a._;h=true;a:while(h===true){h=false;a.B=a._;if(!g(a,1,'h')){a._=a.A-e;break a}a.C=a._;if(!m(a,b.g_CG,99,103)){a._=a.A-e;break a}if(!(!(a.I_pV<=a._)?false:true)){a._=a.A-e;break a}if(!c(a,'')){return false}}return true};b.prototype.J=function(){var l;var i;var j;var k;var m;var n;var b;var c;var d;var e;var a;var f;var g;var h;var p;var q;var r;var s;var t;var u;var o;l=this._;b=true;a:while(b===true){b=false;if(!G(this)){break a}}p=this._=l;i=p;c=true;a:while(c===true){c=false;if(!H(this)){break a}}q=this._=i;this.D=q;s=this._=r=this.A;j=r-s;d=true;a:while(d===true){d=false;if(!J(this)){break a}}u=this._=(t=this.A)-j;k=t-u;e=true;a:while(e===true){e=false;a=true;b:while(a===true){a=false;m=this.A-this._;f=true;c:while(f===true){f=false;if(!F(this)){break c}break b}this._=this.A-m;if(!E(this)){break a}}}this._=this.A-k;g=true;a:while(g===true){g=false;if(!A(this)){break a}}o=this._=this.D;n=o;h=true;a:while(h===true){h=false;if(!I(this)){break a}}this._=n;return true};b.prototype.stem=b.prototype.J;b.prototype.N=function(a){return a instanceof b};b.prototype.equals=b.prototype.N;b.prototype.O=function(){var c;var a;var b;var d;c='ItalianStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};b.prototype.hashCode=b.prototype.O;b.serialVersionUID=1;e(b,'methodObject',function(){return new b});e(b,'a_0',function(){return[new a('',-1,7),new a('qu',0,6),new a('á',0,1),new a('é',0,2),new a('í',0,3),new a('ó',0,4),new a('ú',0,5)]});e(b,'a_1',function(){return[new a('',-1,3),new a('I',0,1),new a('U',0,2)]});e(b,'a_2',function(){return[new a('la',-1,-1),new a('cela',0,-1),new a('gliela',0,-1),new a('mela',0,-1),new a('tela',0,-1),new a('vela',0,-1),new a('le',-1,-1),new a('cele',6,-1),new a('gliele',6,-1),new a('mele',6,-1),new a('tele',6,-1),new a('vele',6,-1),new a('ne',-1,-1),new a('cene',12,-1),new a('gliene',12,-1),new a('mene',12,-1),new a('sene',12,-1),new a('tene',12,-1),new a('vene',12,-1),new a('ci',-1,-1),new a('li',-1,-1),new a('celi',20,-1),new a('glieli',20,-1),new a('meli',20,-1),new a('teli',20,-1),new a('veli',20,-1),new a('gli',20,-1),new a('mi',-1,-1),new a('si',-1,-1),new a('ti',-1,-1),new a('vi',-1,-1),new a('lo',-1,-1),new a('celo',31,-1),new a('glielo',31,-1),new a('melo',31,-1),new a('telo',31,-1),new a('velo',31,-1)]});e(b,'a_3',function(){return[new a('ando',-1,1),new a('endo',-1,1),new a('ar',-1,2),new a('er',-1,2),new a('ir',-1,2)]});e(b,'a_4',function(){return[new a('ic',-1,-1),new a('abil',-1,-1),new a('os',-1,-1),new a('iv',-1,1)]});e(b,'a_5',function(){return[new a('ic',-1,1),new a('abil',-1,1),new a('iv',-1,1)]});e(b,'a_6',function(){return[new a('ica',-1,1),new a('logia',-1,3),new a('osa',-1,1),new a('ista',-1,1),new a('iva',-1,9),new a('anza',-1,1),new a('enza',-1,5),new a('ice',-1,1),new a('atrice',7,1),new a('iche',-1,1),new a('logie',-1,3),new a('abile',-1,1),new a('ibile',-1,1),new a('usione',-1,4),new a('azione',-1,2),new a('uzione',-1,4),new a('atore',-1,2),new a('ose',-1,1),new a('ante',-1,1),new a('mente',-1,1),new a('amente',19,7),new a('iste',-1,1),new a('ive',-1,9),new a('anze',-1,1),new a('enze',-1,5),new a('ici',-1,1),new a('atrici',25,1),new a('ichi',-1,1),new a('abili',-1,1),new a('ibili',-1,1),new a('ismi',-1,1),new a('usioni',-1,4),new a('azioni',-1,2),new a('uzioni',-1,4),new a('atori',-1,2),new a('osi',-1,1),new a('anti',-1,1),new a('amenti',-1,6),new a('imenti',-1,6),new a('isti',-1,1),new a('ivi',-1,9),new a('ico',-1,1),new a('ismo',-1,1),new a('oso',-1,1),new a('amento',-1,6),new a('imento',-1,6),new a('ivo',-1,9),new a('ità',-1,8),new a('istà',-1,1),new a('istè',-1,1),new a('istì',-1,1)]});e(b,'a_7',function(){return[new a('isca',-1,1),new a('enda',-1,1),new a('ata',-1,1),new a('ita',-1,1),new a('uta',-1,1),new a('ava',-1,1),new a('eva',-1,1),new a('iva',-1,1),new a('erebbe',-1,1),new a('irebbe',-1,1),new a('isce',-1,1),new a('ende',-1,1),new a('are',-1,1),new a('ere',-1,1),new a('ire',-1,1),new a('asse',-1,1),new a('ate',-1,1),new a('avate',16,1),new a('evate',16,1),new a('ivate',16,1),new a('ete',-1,1),new a('erete',20,1),new a('irete',20,1),new a('ite',-1,1),new a('ereste',-1,1),new a('ireste',-1,1),new a('ute',-1,1),new a('erai',-1,1),new a('irai',-1,1),new a('isci',-1,1),new a('endi',-1,1),new a('erei',-1,1),new a('irei',-1,1),new a('assi',-1,1),new a('ati',-1,1),new a('iti',-1,1),new a('eresti',-1,1),new a('iresti',-1,1),new a('uti',-1,1),new a('avi',-1,1),new a('evi',-1,1),new a('ivi',-1,1),new a('isco',-1,1),new a('ando',-1,1),new a('endo',-1,1),new a('Yamo',-1,1),new a('iamo',-1,1),new a('avamo',-1,1),new a('evamo',-1,1),new a('ivamo',-1,1),new a('eremo',-1,1),new a('iremo',-1,1),new a('assimo',-1,1),new a('ammo',-1,1),new a('emmo',-1,1),new a('eremmo',54,1),new a('iremmo',54,1),new a('immo',-1,1),new a('ano',-1,1),new a('iscano',58,1),new a('avano',58,1),new a('evano',58,1),new a('ivano',58,1),new a('eranno',-1,1),new a('iranno',-1,1),new a('ono',-1,1),new a('iscono',65,1),new a('arono',65,1),new a('erono',65,1),new a('irono',65,1),new a('erebbero',-1,1),new a('irebbero',-1,1),new a('assero',-1,1),new a('essero',-1,1),new a('issero',-1,1),new a('ato',-1,1),new a('ito',-1,1),new a('uto',-1,1),new a('avo',-1,1),new a('evo',-1,1),new a('ivo',-1,1),new a('ar',-1,1),new a('ir',-1,1),new a('erà',-1,1),new a('irà',-1,1),new a('erò',-1,1),new a('irò',-1,1)]});e(b,'g_v',function(){return[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2,1]});e(b,'g_AEIO',function(){return[17,65,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2]});e(b,'g_CG',function(){return[17]});var q={'src/stemmer.jsx':{Stemmer:p},'src/italian-stemmer.jsx':{ItalianStemmer:b}}}(JSX))
+var Stemmer = JSX.require("src/italian-stemmer.jsx").ItalianStemmer;
+"""
+
+
+class SearchItalian(SearchLanguage):
+ lang = 'it'
+ language_name = 'Italian'
+ js_stemmer_code = js_stemmer
+ stopwords = italian_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('italian')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/ja.py b/sphinx/search/ja.py
index d5a7b4af..bc308b67 100644
--- a/sphinx/search/ja.py
+++ b/sphinx/search/ja.py
@@ -21,6 +21,8 @@ import os
import re
import sys
+from six import iteritems
+
try:
import MeCab
native_module = True
@@ -91,14 +93,14 @@ class MecabBinder(object):
class TinySegmenter(object):
- patterns_ = dict([(re.compile(pattern), value) for pattern, value in {
+ patterns_ = dict([(re.compile(pattern), value) for pattern, value in iteritems({
u'[一二三四五六七八ä¹å百åƒä¸‡å„„å…†]': u'M',
u'[一-龠々〆ヵヶ]': u'H',
u'[ã-ã‚“]': u'I',
u'[ã‚¡-ヴーア-ï¾ï¾žï½°]': u'K',
u'[a-zA-Zï½-zA-Z]': u'A',
u'[0-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}
@@ -145,7 +147,7 @@ class TinySegmenter(object):
# ctype_
def ctype_(self, char):
- for pattern, value in self.patterns_.iteritems():
+ for pattern, value in iteritems(self.patterns_):
if pattern.match(char):
return value
return u'O'
@@ -254,6 +256,7 @@ class SearchJapanese(SearchLanguage):
complicated.
"""
lang = 'ja'
+ language_name = 'Japanese'
def init(self, options):
type = options.get('type', 'default')
diff --git a/sphinx/search/nl.py b/sphinx/search/nl.py
new file mode 100644
index 00000000..f0d612c0
--- /dev/null
+++ b/sphinx/search/nl.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.nl
+ ~~~~~~~~~~~~~~~~
+
+ Danish search language: includes the JS porter stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+danish_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/danish/stop.txt
+og | and
+i | in
+jeg | I
+det | that (dem. pronoun)/it (pers. pronoun)
+at | that (in front of a sentence)/to (with infinitive)
+en | a/an
+den | it (pers. pronoun)/that (dem. pronoun)
+til | to/at/for/until/against/by/of/into, more
+er | present tense of "to be"
+som | who, as
+på | on/upon/in/on/at/to/after/of/with/for, on
+de | they
+med | with/by/in, along
+han | he
+af | of/by/from/off/for/in/with/on, off
+for | at/for/to/from/by/of/ago, in front/before, because
+ikke | not
+der | who/which, there/those
+var | past tense of "to be"
+mig | me/myself
+sig | oneself/himself/herself/itself/themselves
+men | but
+et | a/an/one, one (number), someone/somebody/one
+har | present tense of "to have"
+om | round/about/for/in/a, about/around/down, if
+vi | we
+min | my
+havde | past tense of "to have"
+ham | him
+hun | she
+nu | now
+over | over/above/across/by/beyond/past/on/about, over/past
+da | then, when/as/since
+fra | from/off/since, off, since
+du | you
+ud | out
+sin | his/her/its/one's
+dem | them
+os | us/ourselves
+op | up
+man | you/one
+hans | his
+hvor | where
+eller | or
+hvad | what
+skal | must/shall etc.
+selv | myself/youself/herself/ourselves etc., even
+her | here
+alle | all/everyone/everybody etc.
+vil | will (verb)
+blev | past tense of "to stay/to remain/to get/to become"
+kunne | could
+ind | in
+når | when
+være | present tense of "to be"
+dog | however/yet/after all
+noget | something
+ville | would
+jo | you know/you see (adv), yes
+deres | their/theirs
+efter | after/behind/according to/for/by/from, later/afterwards
+ned | down
+skulle | should
+denne | this
+end | than
+dette | this
+mit | my/mine
+også | also
+under | under/beneath/below/during, below/underneath
+have | have
+dig | you
+anden | other
+hende | her
+mine | my
+alt | everything
+meget | much/very, plenty of
+sit | his, her, its, one's
+sine | his, her, its, one's
+vor | our
+mod | against
+disse | these
+hvis | if
+din | your/yours
+nogle | some
+hos | by/at
+blive | be/become
+mange | many
+ad | by/through
+bliver | present tense of "to be/to become"
+hendes | her/hers
+været | be
+thi | for (conj)
+jer | you
+sådan | such, like this/like that
+''')
+
+js_stemmer = u"""
+var JSX={};(function(m){function n(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function L(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function e(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function K(a,b,c){return a[b]=a[b]/c|0}var I=parseInt;var E=parseFloat;function M(a){return a!==a}var B=isFinite;var A=encodeURIComponent;var z=decodeURIComponent;var y=encodeURI;var x=decodeURI;var w=Object.prototype.toString;var C=Object.prototype.hasOwnProperty;function l(){}m.require=function(b){var a=t[b];return a!==undefined?a:null};m.profilerIsRunning=function(){return l.getResults!=null};m.getProfileResults=function(){return(l.getResults||function(){return{}})()};m.postProfileResults=function(a,b){if(l.postResults==null)throw new Error('profiler has not been turned on');return l.postResults(a,b)};m.resetProfileResults=function(){if(l.resetResults==null)throw new Error('profiler has not been turned on');return l.resetResults()};m.DEBUG=false;function v(){};n([v],Error);function c(a,b,c){this.F=a.length;this.K=a;this.L=b;this.I=c;this.H=null;this.P=null};n([c],Object);function s(){};n([s],Object);function g(){var a;var b;var c;this.G={};a=this.D='';b=this._=0;c=this.A=a.length;this.E=0;this.C=b;this.B=c};n([g],s);function D(a,b){a.D=b.D;a._=b._;a.A=b.A;a.E=b.E;a.C=b.C;a.B=b.B};function i(b,d,c,e){var a;if(b._>=b.A){return false}a=b.D.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function r(a,d,c,e){var b;if(a._>=a.A){return false}b=a.D.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function f(a,d,c,e){var b;if(a._<=a.E){return false}b=a.D.charCodeAt(a._-1);if(b>e||b<c){a._--;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._--;return true}return false};function k(a,b,d){var c;if(a.A-a._<b){return false}if(a.D.slice(c=a._,c+b)!==d){return false}a._+=b;return true};function d(a,b,d){var c;if(a._-a.E<b){return false}if(a.D.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function q(f,m,p){var b;var d;var e;var n;var g;var k;var l;var i;var h;var c;var a;var j;var o;b=0;d=p;e=f._;n=f.A;g=0;k=0;l=false;while(true){i=b+(d-b>>>1);h=0;c=g<k?g:k;a=m[i];for(j=c;j<a.F;j++){if(e+c===n){h=-1;break}h=f.D.charCodeAt(e+c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){d=i;k=c}else{b=i;g=c}if(d-b<=1){if(b>0){break}if(d===b){break}if(l){break}l=true}}while(true){a=m[b];if(g>=a.F){f._=e+a.F|0;if(a.H==null){return a.I}o=a.H(a.P);f._=e+a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function h(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.E;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.F-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.D.charCodeAt(e-1-c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.F){d._=e-a.F|0;if(a.H==null){return a.I}o=a.H(d);d._=e-a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function u(a,b,d,e){var c;c=e.length-(d-b);a.D=a.D.slice(0,b)+e+a.D.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function b(a,f){var b;var c;var d;var e;b=false;if((c=a.C)<0||c>(d=a.B)||d>(e=a.A)||e>a.D.length?false:true){u(a,a.C,a.B,f);b=true}return b};g.prototype.J=function(){return false};g.prototype.Z=function(b){var a;var c;var d;var e;a=this.G['.'+b];if(a==null){c=this.D=b;d=this._=0;e=this.A=c.length;this.E=0;this.C=d;this.B=e;this.J();a=this.D;this.G['.'+b]=a}return a};g.prototype.stemWord=g.prototype.Z;g.prototype.a=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.G['.'+c];if(a==null){f=this.D=c;g=this._=0;h=this.A=f.length;this.E=0;this.C=g;this.B=h;this.J();a=this.D;this.G['.'+c]=a}d.push(a)}return d};g.prototype.stemWords=g.prototype.a;function a(){g.call(this);this.I_p2=0;this.I_p1=0;this.B_e_found=false};n([a],g);a.prototype.M=function(a){this.I_p2=a.I_p2;this.I_p1=a.I_p1;this.B_e_found=a.B_e_found;D(this,a)};a.prototype.copy_from=a.prototype.M;a.prototype.W=function(){var e;var m;var n;var o;var p;var d;var s;var c;var f;var g;var h;var j;var l;var t;var r;m=this._;b:while(true){n=this._;c=true;a:while(c===true){c=false;this.C=this._;e=q(this,a.a_0,11);if(e===0){break a}this.B=this._;switch(e){case 0:break a;case 1:if(!b(this,'a')){return false}break;case 2:if(!b(this,'e')){return false}break;case 3:if(!b(this,'i')){return false}break;case 4:if(!b(this,'o')){return false}break;case 5:if(!b(this,'u')){return false}break;case 6:if(this._>=this.A){break a}this._++;break}continue b}this._=n;break b}t=this._=m;o=t;f=true;a:while(f===true){f=false;this.C=this._;if(!k(this,1,'y')){this._=o;break a}this.B=this._;if(!b(this,'Y')){return false}}a:while(true){p=this._;g=true;d:while(g===true){g=false;e:while(true){d=this._;h=true;b:while(h===true){h=false;if(!i(this,a.g_v,97,232)){break b}this.C=this._;j=true;f:while(j===true){j=false;s=this._;l=true;c:while(l===true){l=false;if(!k(this,1,'i')){break c}this.B=this._;if(!i(this,a.g_v,97,232)){break c}if(!b(this,'I')){return false}break f}this._=s;if(!k(this,1,'y')){break b}this.B=this._;if(!b(this,'Y')){return false}}this._=d;break e}r=this._=d;if(r>=this.A){break d}this._++}continue a}this._=p;break a}return true};a.prototype.r_prelude=a.prototype.W;function F(c){var d;var s;var t;var o;var p;var e;var n;var f;var g;var h;var j;var l;var m;var u;var r;s=c._;b:while(true){t=c._;f=true;a:while(f===true){f=false;c.C=c._;d=q(c,a.a_0,11);if(d===0){break a}c.B=c._;switch(d){case 0:break a;case 1:if(!b(c,'a')){return false}break;case 2:if(!b(c,'e')){return false}break;case 3:if(!b(c,'i')){return false}break;case 4:if(!b(c,'o')){return false}break;case 5:if(!b(c,'u')){return false}break;case 6:if(c._>=c.A){break a}c._++;break}continue b}c._=t;break b}u=c._=s;o=u;g=true;a:while(g===true){g=false;c.C=c._;if(!k(c,1,'y')){c._=o;break a}c.B=c._;if(!b(c,'Y')){return false}}a:while(true){p=c._;h=true;d:while(h===true){h=false;e:while(true){e=c._;j=true;b:while(j===true){j=false;if(!i(c,a.g_v,97,232)){break b}c.C=c._;l=true;f:while(l===true){l=false;n=c._;m=true;c:while(m===true){m=false;if(!k(c,1,'i')){break c}c.B=c._;if(!i(c,a.g_v,97,232)){break c}if(!b(c,'I')){return false}break f}c._=n;if(!k(c,1,'y')){break b}c.B=c._;if(!b(c,'Y')){return false}}c._=e;break e}r=c._=e;if(r>=c.A){break d}c._++}continue a}c._=p;break a}return true};a.prototype.U=function(){var b;var c;var d;var e;var f;var g;this.I_p1=g=this.A;this.I_p2=g;a:while(true){b=true;b:while(b===true){b=false;if(!i(this,a.g_v,97,232)){break b}break a}if(this._>=this.A){return false}this._++}a:while(true){c=true;b:while(c===true){c=false;if(!r(this,a.g_v,97,232)){break b}break a}if(this._>=this.A){return false}this._++}this.I_p1=this._;d=true;a:while(d===true){d=false;if(!(this.I_p1<3)){break a}this.I_p1=3}a:while(true){e=true;b:while(e===true){e=false;if(!i(this,a.g_v,97,232)){break b}break a}if(this._>=this.A){return false}this._++}a:while(true){f=true;b:while(f===true){f=false;if(!r(this,a.g_v,97,232)){break b}break a}if(this._>=this.A){return false}this._++}this.I_p2=this._;return true};a.prototype.r_mark_regions=a.prototype.U;function G(b){var c;var d;var e;var f;var g;var h;b.I_p1=h=b.A;b.I_p2=h;a:while(true){c=true;b:while(c===true){c=false;if(!i(b,a.g_v,97,232)){break b}break a}if(b._>=b.A){return false}b._++}a:while(true){d=true;b:while(d===true){d=false;if(!r(b,a.g_v,97,232)){break b}break a}if(b._>=b.A){return false}b._++}b.I_p1=b._;e=true;a:while(e===true){e=false;if(!(b.I_p1<3)){break a}b.I_p1=3}a:while(true){f=true;b:while(f===true){f=false;if(!i(b,a.g_v,97,232)){break b}break a}if(b._>=b.A){return false}b._++}a:while(true){g=true;b:while(g===true){g=false;if(!r(b,a.g_v,97,232)){break b}break a}if(b._>=b.A){return false}b._++}b.I_p2=b._;return true};a.prototype.V=function(){var c;var e;var d;b:while(true){e=this._;d=true;a:while(d===true){d=false;this.C=this._;c=q(this,a.a_1,3);if(c===0){break a}this.B=this._;switch(c){case 0:break a;case 1:if(!b(this,'y')){return false}break;case 2:if(!b(this,'i')){return false}break;case 3:if(this._>=this.A){break a}this._++;break}continue b}this._=e;break b}return true};a.prototype.r_postlude=a.prototype.V;function H(c){var d;var f;var e;b:while(true){f=c._;e=true;a:while(e===true){e=false;c.C=c._;d=q(c,a.a_1,3);if(d===0){break a}c.B=c._;switch(d){case 0:break a;case 1:if(!b(c,'y')){return false}break;case 2:if(!b(c,'i')){return false}break;case 3:if(c._>=c.A){break a}c._++;break}continue b}c._=f;break b}return true};a.prototype.Q=function(){return!(this.I_p1<=this._)?false:true};a.prototype.r_R1=a.prototype.Q;a.prototype.R=function(){return!(this.I_p2<=this._)?false:true};a.prototype.r_R2=a.prototype.R;a.prototype.Y=function(){var d;var c;d=this.A-this._;if(h(this,a.a_2,3)===0){return false}c=this._=this.A-d;this.B=c;if(c<=this.E){return false}this._--;this.C=this._;return!b(this,'')?false:true};a.prototype.r_undouble=a.prototype.Y;function j(c){var e;var d;e=c.A-c._;if(h(c,a.a_2,3)===0){return false}d=c._=c.A-e;c.B=d;if(d<=c.E){return false}c._--;c.C=c._;return!b(c,'')?false:true};a.prototype.S=function(){var c;var e;this.B_e_found=false;this.B=this._;if(!d(this,1,'e')){return false}this.C=e=this._;if(!(!(this.I_p1<=e)?false:true)){return false}c=this.A-this._;if(!f(this,a.g_v,97,232)){return false}this._=this.A-c;if(!b(this,'')){return false}this.B_e_found=true;return!j(this)?false:true};a.prototype.r_e_ending=a.prototype.S;function o(c){var e;var g;c.B_e_found=false;c.B=c._;if(!d(c,1,'e')){return false}c.C=g=c._;if(!(!(c.I_p1<=g)?false:true)){return false}e=c.A-c._;if(!f(c,a.g_v,97,232)){return false}c._=c.A-e;if(!b(c,'')){return false}c.B_e_found=true;return!j(c)?false:true};a.prototype.T=function(){var e;var g;var c;var h;var i;if(!(!(this.I_p1<=this._)?false:true)){return false}e=this.A-this._;if(!f(this,a.g_v,97,232)){return false}i=this._=(h=this.A)-e;g=h-i;c=true;a:while(c===true){c=false;if(!d(this,3,'gem')){break a}return false}this._=this.A-g;return!b(this,'')?false:!j(this)?false:true};a.prototype.r_en_ending=a.prototype.T;function p(c){var g;var h;var e;var i;var k;if(!(!(c.I_p1<=c._)?false:true)){return false}g=c.A-c._;if(!f(c,a.g_v,97,232)){return false}k=c._=(i=c.A)-g;h=i-k;e=true;a:while(e===true){e=false;if(!d(c,3,'gem')){break a}return false}c._=c.A-h;return!b(c,'')?false:!j(c)?false:true};a.prototype.X=function(){var c;var v;var w;var x;var y;var z;var A;var B;var C;var D;var M;var m;var g;var i;var k;var l;var e;var n;var q;var r;var s;var E;var F;var G;var H;var I;var J;var K;var L;var t;var N;var u;v=this.A-this._;m=true;a:while(m===true){m=false;this.B=this._;c=h(this,a.a_3,5);if(c===0){break a}this.C=this._;switch(c){case 0:break a;case 1:if(!(!(this.I_p1<=this._)?false:true)){break a}if(!b(this,'heid')){return false}break;case 2:if(!p(this)){break a}break;case 3:if(!(!(this.I_p1<=this._)?false:true)){break a}if(!f(this,a.g_v_j,97,232)){break a}if(!b(this,'')){return false}break}}F=this._=(E=this.A)-v;w=E-F;g=true;a:while(g===true){g=false;if(!o(this)){break a}}I=this._=(H=this.A)-w;x=H-I;i=true;a:while(i===true){i=false;this.B=this._;if(!d(this,4,'heid')){break a}this.C=G=this._;if(!(!(this.I_p2<=G)?false:true)){break a}y=this.A-this._;k=true;b:while(k===true){k=false;if(!d(this,1,'c')){break b}break a}this._=this.A-y;if(!b(this,'')){return false}this.B=this._;if(!d(this,2,'en')){break a}this.C=this._;if(!p(this)){break a}}L=this._=(K=this.A)-x;z=K-L;l=true;a:while(l===true){l=false;this.B=this._;c=h(this,a.a_4,6);if(c===0){break a}this.C=this._;switch(c){case 0:break a;case 1:if(!(!(this.I_p2<=this._)?false:true)){break a}if(!b(this,'')){return false}e=true;c:while(e===true){e=false;A=this.A-this._;n=true;b:while(n===true){n=false;this.B=this._;if(!d(this,2,'ig')){break b}this.C=J=this._;if(!(!(this.I_p2<=J)?false:true)){break b}B=this.A-this._;q=true;d:while(q===true){q=false;if(!d(this,1,'e')){break d}break b}this._=this.A-B;if(!b(this,'')){return false}break c}this._=this.A-A;if(!j(this)){break a}}break;case 2:if(!(!(this.I_p2<=this._)?false:true)){break a}C=this.A-this._;r=true;b:while(r===true){r=false;if(!d(this,1,'e')){break b}break a}this._=this.A-C;if(!b(this,'')){return false}break;case 3:if(!(!(this.I_p2<=this._)?false:true)){break a}if(!b(this,'')){return false}if(!o(this)){break a}break;case 4:if(!(!(this.I_p2<=this._)?false:true)){break a}if(!b(this,'')){return false}break;case 5:if(!(!(this.I_p2<=this._)?false:true)){break a}if(!this.B_e_found){break a}if(!b(this,'')){return false}break}}u=this._=(N=this.A)-z;D=N-u;s=true;a:while(s===true){s=false;if(!f(this,a.g_v_I,73,232)){break a}M=this.A-this._;if(h(this,a.a_5,4)===0){break a}if(!f(this,a.g_v,97,232)){break a}t=this._=this.A-M;this.B=t;if(t<=this.E){break a}this._--;this.C=this._;if(!b(this,'')){return false}}this._=this.A-D;return true};a.prototype.r_standard_suffix=a.prototype.X;function J(c){var e;var w;var x;var y;var z;var A;var B;var C;var D;var E;var N;var g;var i;var k;var l;var m;var n;var q;var r;var s;var t;var F;var G;var H;var I;var J;var K;var L;var M;var u;var O;var v;w=c.A-c._;g=true;a:while(g===true){g=false;c.B=c._;e=h(c,a.a_3,5);if(e===0){break a}c.C=c._;switch(e){case 0:break a;case 1:if(!(!(c.I_p1<=c._)?false:true)){break a}if(!b(c,'heid')){return false}break;case 2:if(!p(c)){break a}break;case 3:if(!(!(c.I_p1<=c._)?false:true)){break a}if(!f(c,a.g_v_j,97,232)){break a}if(!b(c,'')){return false}break}}G=c._=(F=c.A)-w;x=F-G;i=true;a:while(i===true){i=false;if(!o(c)){break a}}J=c._=(I=c.A)-x;y=I-J;k=true;a:while(k===true){k=false;c.B=c._;if(!d(c,4,'heid')){break a}c.C=H=c._;if(!(!(c.I_p2<=H)?false:true)){break a}z=c.A-c._;l=true;b:while(l===true){l=false;if(!d(c,1,'c')){break b}break a}c._=c.A-z;if(!b(c,'')){return false}c.B=c._;if(!d(c,2,'en')){break a}c.C=c._;if(!p(c)){break a}}M=c._=(L=c.A)-y;A=L-M;m=true;a:while(m===true){m=false;c.B=c._;e=h(c,a.a_4,6);if(e===0){break a}c.C=c._;switch(e){case 0:break a;case 1:if(!(!(c.I_p2<=c._)?false:true)){break a}if(!b(c,'')){return false}n=true;c:while(n===true){n=false;B=c.A-c._;q=true;b:while(q===true){q=false;c.B=c._;if(!d(c,2,'ig')){break b}c.C=K=c._;if(!(!(c.I_p2<=K)?false:true)){break b}C=c.A-c._;r=true;d:while(r===true){r=false;if(!d(c,1,'e')){break d}break b}c._=c.A-C;if(!b(c,'')){return false}break c}c._=c.A-B;if(!j(c)){break a}}break;case 2:if(!(!(c.I_p2<=c._)?false:true)){break a}D=c.A-c._;s=true;b:while(s===true){s=false;if(!d(c,1,'e')){break b}break a}c._=c.A-D;if(!b(c,'')){return false}break;case 3:if(!(!(c.I_p2<=c._)?false:true)){break a}if(!b(c,'')){return false}if(!o(c)){break a}break;case 4:if(!(!(c.I_p2<=c._)?false:true)){break a}if(!b(c,'')){return false}break;case 5:if(!(!(c.I_p2<=c._)?false:true)){break a}if(!c.B_e_found){break a}if(!b(c,'')){return false}break}}v=c._=(O=c.A)-A;E=O-v;t=true;a:while(t===true){t=false;if(!f(c,a.g_v_I,73,232)){break a}N=c.A-c._;if(h(c,a.a_5,4)===0){break a}if(!f(c,a.g_v,97,232)){break a}u=c._=c.A-N;c.B=u;if(u<=c.E){break a}c._--;c.C=c._;if(!b(c,'')){return false}}c._=c.A-E;return true};a.prototype.J=function(){var f;var g;var h;var b;var a;var c;var d;var i;var j;var e;f=this._;b=true;a:while(b===true){b=false;if(!F(this)){break a}}i=this._=f;g=i;a=true;a:while(a===true){a=false;if(!G(this)){break a}}j=this._=g;this.E=j;this._=this.A;c=true;a:while(c===true){c=false;if(!J(this)){break a}}e=this._=this.E;h=e;d=true;a:while(d===true){d=false;if(!H(this)){break a}}this._=h;return true};a.prototype.stem=a.prototype.J;a.prototype.N=function(b){return b instanceof a};a.prototype.equals=a.prototype.N;a.prototype.O=function(){var c;var a;var b;var d;c='DutchStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};a.prototype.hashCode=a.prototype.O;a.serialVersionUID=1;e(a,'methodObject',function(){return new a});e(a,'a_0',function(){return[new c('',-1,6),new c('á',0,1),new c('ä',0,1),new c('é',0,2),new c('ë',0,2),new c('í',0,3),new c('ï',0,3),new c('ó',0,4),new c('ö',0,4),new c('ú',0,5),new c('ü',0,5)]});e(a,'a_1',function(){return[new c('',-1,3),new c('I',0,2),new c('Y',0,1)]});e(a,'a_2',function(){return[new c('dd',-1,-1),new c('kk',-1,-1),new c('tt',-1,-1)]});e(a,'a_3',function(){return[new c('ene',-1,2),new c('se',-1,3),new c('en',-1,2),new c('heden',2,1),new c('s',-1,3)]});e(a,'a_4',function(){return[new c('end',-1,1),new c('ig',-1,2),new c('ing',-1,1),new c('lijk',-1,3),new c('baar',-1,4),new c('bar',-1,5)]});e(a,'a_5',function(){return[new c('aa',-1,-1),new c('ee',-1,-1),new c('oo',-1,-1),new c('uu',-1,-1)]});e(a,'g_v',function(){return[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128]});e(a,'g_v_I',function(){return[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128]});e(a,'g_v_j',function(){return[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128]});var t={'src/stemmer.jsx':{Stemmer:s},'src/dutch-stemmer.jsx':{DutchStemmer:a}}}(JSX))
+var Stemmer = JSX.require("src/dutch-stemmer.jsx").DutchStemmer;
+"""
+
+
+class SearchDutch(SearchLanguage):
+ lang = 'nl'
+ language_name = 'Dutch'
+ js_stemmer_code = js_stemmer
+ stopwords = danish_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('dutch')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/no.py b/sphinx/search/no.py
new file mode 100644
index 00000000..b72b4ea0
--- /dev/null
+++ b/sphinx/search/no.py
@@ -0,0 +1,212 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.no
+ ~~~~~~~~~~~~~~~~
+
+ Norwegian search language: includes the JS Norwegian stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+norwegian_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/norwegian/stop.txt
+og | and
+i | in
+jeg | I
+det | it/this/that
+at | to (w. inf.)
+en | a/an
+et | a/an
+den | it/this/that
+til | to
+er | is/am/are
+som | who/that
+på | on
+de | they / you(formal)
+med | with
+han | he
+av | of
+ikke | not
+ikkje | not *
+der | there
+så | so
+var | was/were
+meg | me
+seg | you
+men | but
+ett | one
+har | have
+om | about
+vi | we
+min | my
+mitt | my
+ha | have
+hadde | had
+hun | she
+nå | now
+over | over
+da | when/as
+ved | by/know
+fra | from
+du | you
+ut | out
+sin | your
+dem | them
+oss | us
+opp | up
+man | you/one
+kan | can
+hans | his
+hvor | where
+eller | or
+hva | what
+skal | shall/must
+selv | self (reflective)
+sjøl | self (reflective)
+her | here
+alle | all
+vil | will
+bli | become
+ble | became
+blei | became *
+blitt | have become
+kunne | could
+inn | in
+når | when
+være | be
+kom | come
+noen | some
+noe | some
+ville | would
+dere | you
+som | who/which/that
+deres | their/theirs
+kun | only/just
+ja | yes
+etter | after
+ned | down
+skulle | should
+denne | this
+for | for/because
+deg | you
+si | hers/his
+sine | hers/his
+sitt | hers/his
+mot | against
+Ã¥ | to
+meget | much
+hvorfor | why
+dette | this
+disse | these/those
+uten | without
+hvordan | how
+ingen | none
+din | your
+ditt | your
+blir | become
+samme | same
+hvilken | which
+hvilke | which (plural)
+sånn | such a
+inni | inside/within
+mellom | between
+vår | our
+hver | each
+hvem | who
+vors | us/ours
+hvis | whose
+både | both
+bare | only/just
+enn | than
+fordi | as/because
+før | before
+mange | many
+også | also
+slik | just
+vært | been
+være | to be
+båe | both *
+begge | both
+siden | since
+dykk | your *
+dykkar | yours *
+dei | they *
+deira | them *
+deires | theirs *
+deim | them *
+di | your (fem.) *
+då | as/when *
+eg | I *
+ein | a/an *
+eit | a/an *
+eitt | a/an *
+elles | or *
+honom | he *
+hjå | at *
+ho | she *
+hoe | she *
+henne | her
+hennar | her/hers
+hennes | hers
+hoss | how *
+hossen | how *
+ikkje | not *
+ingi | noone *
+inkje | noone *
+korleis | how *
+korso | how *
+kva | what/which *
+kvar | where *
+kvarhelst | where *
+kven | who/whom *
+kvi | why *
+kvifor | why *
+me | we *
+medan | while *
+mi | my *
+mine | my *
+mykje | much *
+no | now *
+nokon | some (masc./neut.) *
+noka | some (fem.) *
+nokor | some *
+noko | some *
+nokre | some *
+si | his/hers *
+sia | since *
+sidan | since *
+so | so *
+somt | some *
+somme | some *
+um | about*
+upp | up *
+vere | be *
+vore | was *
+verte | become *
+vort | become *
+varte | became *
+vart | became *
+''')
+
+js_stemmer = u"""
+var JSX={};(function(g){function i(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function G(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function e(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function H(a,b,c){return a[b]=a[b]/c|0}var B=parseInt;var q=parseFloat;function I(a){return a!==a}var y=isFinite;var x=encodeURIComponent;var w=decodeURIComponent;var u=encodeURI;var t=decodeURI;var s=Object.prototype.toString;var r=Object.prototype.hasOwnProperty;function h(){}g.require=function(b){var a=m[b];return a!==undefined?a:null};g.profilerIsRunning=function(){return h.getResults!=null};g.getProfileResults=function(){return(h.getResults||function(){return{}})()};g.postProfileResults=function(a,b){if(h.postResults==null)throw new Error('profiler has not been turned on');return h.postResults(a,b)};g.resetProfileResults=function(){if(h.resetResults==null)throw new Error('profiler has not been turned on');return h.resetResults()};g.DEBUG=false;function A(){};i([A],Error);function b(a,b,c){this.G=a.length;this.R=a;this.U=b;this.J=c;this.I=null;this.V=null};i([b],Object);function j(){};i([j],Object);function d(){var a;var b;var c;this.F={};a=this.C='';b=this._=0;c=this.A=a.length;this.B=0;this.D=b;this.E=c};i([d],j);function v(a,b){a.C=b.C;a._=b._;a.A=b.A;a.B=b.B;a.D=b.D;a.E=b.E};function l(b,d,c,e){var a;if(b._>=b.A){return false}a=b.C.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function k(b,d,c,e){var a;if(b._<=b.B){return false}a=b.C.charCodeAt(b._-1);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._--;return true};function p(a,d,c,e){var b;if(a._>=a.A){return false}b=a.C.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function o(a,d,c,e){var b;if(a._<=a.B){return false}b=a.C.charCodeAt(a._-1);if(b>e||b<c){a._--;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._--;return true}return false};function n(a,b,d){var c;if(a._-a.B<b){return false}if(a.C.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function f(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.B;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.G-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.C.charCodeAt(e-1-c)-a.R.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.G){d._=e-a.G|0;if(a.I==null){return a.J}o=a.I(d);d._=e-a.G|0;if(o){return a.J}}b=a.U;if(b<0){return 0}}return-1};function C(a,b,d,e){var c;c=e.length-(d-b);a.C=a.C.slice(0,b)+e+a.C.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function c(a,f){var b;var c;var d;var e;b=false;if((c=a.D)<0||c>(d=a.E)||d>(e=a.A)||e>a.C.length?false:true){C(a,a.D,a.E,f);b=true}return b};d.prototype.H=function(){return false};d.prototype.S=function(b){var a;var c;var d;var e;a=this.F['.'+b];if(a==null){c=this.C=b;d=this._=0;e=this.A=c.length;this.B=0;this.D=d;this.E=e;this.H();a=this.C;this.F['.'+b]=a}return a};d.prototype.stemWord=d.prototype.S;d.prototype.T=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.F['.'+c];if(a==null){f=this.C=c;g=this._=0;h=this.A=f.length;this.B=0;this.D=g;this.E=h;this.H();a=this.C;this.F['.'+c]=a}d.push(a)}return d};d.prototype.stemWords=d.prototype.T;function a(){d.call(this);this.I_x=0;this.I_p1=0};i([a],d);a.prototype.K=function(a){this.I_x=a.I_x;this.I_p1=a.I_p1;v(this,a)};a.prototype.copy_from=a.prototype.K;a.prototype.P=function(){var g;var d;var b;var e;var c;var f;var i;var j;var k;var h;this.I_p1=j=this.A;g=i=this._;b=i+3|0;if(0>b||b>j){return false}h=this._=b;this.I_x=h;this._=g;a:while(true){d=this._;e=true;b:while(e===true){e=false;if(!l(this,a.g_v,97,248)){break b}this._=d;break a}k=this._=d;if(k>=this.A){return false}this._++}a:while(true){c=true;b:while(c===true){c=false;if(!p(this,a.g_v,97,248)){break b}break a}if(this._>=this.A){return false}this._++}this.I_p1=this._;f=true;a:while(f===true){f=false;if(!(this.I_p1<this.I_x)){break a}this.I_p1=this.I_x}return true};a.prototype.r_mark_regions=a.prototype.P;function F(b){var h;var e;var c;var f;var d;var g;var j;var k;var m;var i;b.I_p1=k=b.A;h=j=b._;c=j+3|0;if(0>c||c>k){return false}i=b._=c;b.I_x=i;b._=h;a:while(true){e=b._;f=true;b:while(f===true){f=false;if(!l(b,a.g_v,97,248)){break b}b._=e;break a}m=b._=e;if(m>=b.A){return false}b._++}a:while(true){d=true;b:while(d===true){d=false;if(!p(b,a.g_v,97,248)){break b}break a}if(b._>=b.A){return false}b._++}b.I_p1=b._;g=true;a:while(g===true){g=false;if(!(b.I_p1<b.I_x)){break a}b.I_p1=b.I_x}return true};a.prototype.O=function(){var b;var h;var d;var i;var e;var g;var j;var l;var m;h=this.A-(j=this._);if(j<this.I_p1){return false}l=this._=this.I_p1;d=this.B;this.B=l;m=this._=this.A-h;this.E=m;b=f(this,a.a_0,29);if(b===0){this.B=d;return false}this.D=this._;this.B=d;switch(b){case 0:return false;case 1:if(!c(this,'')){return false}break;case 2:e=true;a:while(e===true){e=false;i=this.A-this._;g=true;b:while(g===true){g=false;if(!k(this,a.g_s_ending,98,122)){break b}break a}this._=this.A-i;if(!n(this,1,'k')){return false}if(!o(this,a.g_v,97,248)){return false}}if(!c(this,'')){return false}break;case 3:if(!c(this,'er')){return false}break}return true};a.prototype.r_main_suffix=a.prototype.O;function E(b){var d;var l;var e;var i;var g;var h;var m;var p;var j;l=b.A-(m=b._);if(m<b.I_p1){return false}p=b._=b.I_p1;e=b.B;b.B=p;j=b._=b.A-l;b.E=j;d=f(b,a.a_0,29);if(d===0){b.B=e;return false}b.D=b._;b.B=e;switch(d){case 0:return false;case 1:if(!c(b,'')){return false}break;case 2:g=true;a:while(g===true){g=false;i=b.A-b._;h=true;b:while(h===true){h=false;if(!k(b,a.g_s_ending,98,122)){break b}break a}b._=b.A-i;if(!n(b,1,'k')){return false}if(!o(b,a.g_v,97,248)){return false}}if(!c(b,'')){return false}break;case 3:if(!c(b,'er')){return false}break}return true};a.prototype.N=function(){var e;var g;var b;var h;var d;var i;var j;var k;var l;e=(h=this.A)-(d=this._);g=h-d;if(d<this.I_p1){return false}i=this._=this.I_p1;b=this.B;this.B=i;j=this._=this.A-g;this.E=j;if(f(this,a.a_1,2)===0){this.B=b;return false}this.D=this._;l=this.B=b;k=this._=this.A-e;if(k<=l){return false}this._--;this.D=this._;return!c(this,'')?false:true};a.prototype.r_consonant_pair=a.prototype.N;function D(b){var i;var j;var d;var g;var e;var k;var l;var m;var h;i=(g=b.A)-(e=b._);j=g-e;if(e<b.I_p1){return false}k=b._=b.I_p1;d=b.B;b.B=k;l=b._=b.A-j;b.E=l;if(f(b,a.a_1,2)===0){b.B=d;return false}b.D=b._;h=b.B=d;m=b._=b.A-i;if(m<=h){return false}b._--;b.D=b._;return!c(b,'')?false:true};a.prototype.Q=function(){var b;var e;var d;var g;var h;var i;e=this.A-(g=this._);if(g<this.I_p1){return false}h=this._=this.I_p1;d=this.B;this.B=h;i=this._=this.A-e;this.E=i;b=f(this,a.a_2,11);if(b===0){this.B=d;return false}this.D=this._;this.B=d;switch(b){case 0:return false;case 1:if(!c(this,'')){return false}break}return true};a.prototype.r_other_suffix=a.prototype.Q;function z(b){var d;var g;var e;var h;var i;var j;g=b.A-(h=b._);if(h<b.I_p1){return false}i=b._=b.I_p1;e=b.B;b.B=i;j=b._=b.A-g;b.E=j;d=f(b,a.a_2,11);if(d===0){b.B=e;return false}b.D=b._;b.B=e;switch(d){case 0:return false;case 1:if(!c(b,'')){return false}break}return true};a.prototype.H=function(){var g;var f;var h;var b;var c;var a;var d;var i;var j;var k;var l;var e;g=this._;b=true;a:while(b===true){b=false;if(!F(this)){break a}}i=this._=g;this.B=i;k=this._=j=this.A;f=j-k;c=true;a:while(c===true){c=false;if(!E(this)){break a}}e=this._=(l=this.A)-f;h=l-e;a=true;a:while(a===true){a=false;if(!D(this)){break a}}this._=this.A-h;d=true;a:while(d===true){d=false;if(!z(this)){break a}}this._=this.B;return true};a.prototype.stem=a.prototype.H;a.prototype.L=function(b){return b instanceof a};a.prototype.equals=a.prototype.L;a.prototype.M=function(){var c;var a;var b;var d;c='NorwegianStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};a.prototype.hashCode=a.prototype.M;a.serialVersionUID=1;e(a,'methodObject',function(){return new a});e(a,'a_0',function(){return[new b('a',-1,1),new b('e',-1,1),new b('ede',1,1),new b('ande',1,1),new b('ende',1,1),new b('ane',1,1),new b('ene',1,1),new b('hetene',6,1),new b('erte',1,3),new b('en',-1,1),new b('heten',9,1),new b('ar',-1,1),new b('er',-1,1),new b('heter',12,1),new b('s',-1,2),new b('as',14,1),new b('es',14,1),new b('edes',16,1),new b('endes',16,1),new b('enes',16,1),new b('hetenes',19,1),new b('ens',14,1),new b('hetens',21,1),new b('ers',14,1),new b('ets',14,1),new b('et',-1,1),new b('het',25,1),new b('ert',-1,3),new b('ast',-1,1)]});e(a,'a_1',function(){return[new b('dt',-1,-1),new b('vt',-1,-1)]});e(a,'a_2',function(){return[new b('leg',-1,1),new b('eleg',0,1),new b('ig',-1,1),new b('eig',2,1),new b('lig',2,1),new b('elig',4,1),new b('els',-1,1),new b('lov',-1,1),new b('elov',7,1),new b('slov',7,1),new b('hetslov',9,1)]});e(a,'g_v',function(){return[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128]});e(a,'g_s_ending',function(){return[119,125,149,1]});var m={'src/stemmer.jsx':{Stemmer:j},'src/norwegian-stemmer.jsx':{NorwegianStemmer:a}}}(JSX))
+var Stemmer = JSX.require("src/norwegian-stemmer.jsx").NorwegianStemmer;
+"""
+
+
+class SearchNorwegian(SearchLanguage):
+ lang = 'no'
+ language_name = 'Norwegian'
+ js_stemmer_code = js_stemmer
+ stopwords = norwegian_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('norwegian')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/pt.py b/sphinx/search/pt.py
new file mode 100644
index 00000000..cb93f26d
--- /dev/null
+++ b/sphinx/search/pt.py
@@ -0,0 +1,272 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.pt
+ ~~~~~~~~~~~~~~~~
+
+ Portuguese search language: includes the JS Portuguese stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+portuguese_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/portuguese/stop.txt
+de | of, from
+a | the; to, at; her
+o | the; him
+que | who, that
+e | and
+do | de + o
+da | de + a
+em | in
+um | a
+para | for
+ | é from SER
+com | with
+não | not, no
+uma | a
+os | the; them
+no | em + o
+se | himself etc
+na | em + a
+por | for
+mais | more
+as | the; them
+dos | de + os
+como | as, like
+mas | but
+ | foi from SER
+ao | a + o
+ele | he
+das | de + as
+ | tem from TER
+à | a + a
+seu | his
+sua | her
+ou | or
+ | ser from SER
+quando | when
+muito | much
+ | há from HAV
+nos | em + os; us
+já | already, now
+ | está from EST
+eu | I
+também | also
+só | only, just
+pelo | per + o
+pela | per + a
+até | up to
+isso | that
+ela | he
+entre | between
+ | era from SER
+depois | after
+sem | without
+mesmo | same
+aos | a + os
+ | ter from TER
+seus | his
+quem | whom
+nas | em + as
+me | me
+esse | that
+eles | they
+ | estão from EST
+você | you
+ | tinha from TER
+ | foram from SER
+essa | that
+num | em + um
+nem | nor
+suas | her
+meu | my
+às | a + as
+minha | my
+ | têm from TER
+numa | em + uma
+pelos | per + os
+elas | they
+ | havia from HAV
+ | seja from SER
+qual | which
+ | será from SER
+nós | we
+ | tenho from TER
+lhe | to him, her
+deles | of them
+essas | those
+esses | those
+pelas | per + as
+este | this
+ | fosse from SER
+dele | of him
+
+ | other words. There are many contractions such as naquele = em+aquele,
+ | mo = me+o, but they are rare.
+ | Indefinite article plural forms are also rare.
+
+tu | thou
+te | thee
+vocês | you (plural)
+vos | you
+lhes | to them
+meus | my
+minhas
+teu | thy
+tua
+teus
+tuas
+nosso | our
+nossa
+nossos
+nossas
+
+dela | of her
+delas | of them
+
+esta | this
+estes | these
+estas | these
+aquele | that
+aquela | that
+aqueles | those
+aquelas | those
+isto | this
+aquilo | that
+
+ | forms of estar, to be (not including the infinitive):
+estou
+está
+estamos
+estão
+estive
+esteve
+estivemos
+estiveram
+estava
+estávamos
+estavam
+estivera
+estivéramos
+esteja
+estejamos
+estejam
+estivesse
+estivéssemos
+estivessem
+estiver
+estivermos
+estiverem
+
+ | forms of haver, to have (not including the infinitive):
+hei
+há
+havemos
+hão
+houve
+houvemos
+houveram
+houvera
+houvéramos
+haja
+hajamos
+hajam
+houvesse
+houvéssemos
+houvessem
+houver
+houvermos
+houverem
+houverei
+houverá
+houveremos
+houverão
+houveria
+houveríamos
+houveriam
+
+ | forms of ser, to be (not including the infinitive):
+sou
+somos
+são
+era
+éramos
+eram
+fui
+foi
+fomos
+foram
+fora
+fôramos
+seja
+sejamos
+sejam
+fosse
+fôssemos
+fossem
+for
+formos
+forem
+serei
+será
+seremos
+serão
+seria
+seríamos
+seriam
+
+ | forms of ter, to have (not including the infinitive):
+tenho
+tem
+temos
+tém
+tinha
+tínhamos
+tinham
+tive
+teve
+tivemos
+tiveram
+tivera
+tivéramos
+tenha
+tenhamos
+tenham
+tivesse
+tivéssemos
+tivessem
+tiver
+tivermos
+tiverem
+terei
+terá
+teremos
+terão
+teria
+teríamos
+teriam
+''')
+
+js_stemmer = u"""
+
+var JSX={};(function(j){function l(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function I(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function h(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function J(a,b,c){return a[b]=a[b]/c|0}var p=parseInt;var z=parseFloat;function K(a){return a!==a}var x=isFinite;var w=encodeURIComponent;var u=decodeURIComponent;var t=encodeURI;var s=decodeURI;var A=Object.prototype.toString;var q=Object.prototype.hasOwnProperty;function k(){}j.require=function(b){var a=o[b];return a!==undefined?a:null};j.profilerIsRunning=function(){return k.getResults!=null};j.getProfileResults=function(){return(k.getResults||function(){return{}})()};j.postProfileResults=function(a,b){if(k.postResults==null)throw new Error('profiler has not been turned on');return k.postResults(a,b)};j.resetProfileResults=function(){if(k.resetResults==null)throw new Error('profiler has not been turned on');return k.resetResults()};j.DEBUG=false;function r(){};l([r],Error);function a(a,b,c){this.F=a.length;this.K=a;this.L=b;this.I=c;this.H=null;this.P=null};l([a],Object);function n(){};l([n],Object);function i(){var a;var b;var c;this.G={};a=this.E='';b=this._=0;c=this.A=a.length;this.D=0;this.B=b;this.C=c};l([i],n);function v(a,b){a.E=b.E;a._=b._;a.A=b.A;a.D=b.D;a.B=b.B;a.C=b.C};function f(b,d,c,e){var a;if(b._>=b.A){return false}a=b.E.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function g(a,d,c,e){var b;if(a._>=a.A){return false}b=a.E.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function d(a,b,d){var c;if(a._-a.D<b){return false}if(a.E.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function m(f,m,p){var b;var d;var e;var n;var g;var k;var l;var i;var h;var c;var a;var j;var o;b=0;d=p;e=f._;n=f.A;g=0;k=0;l=false;while(true){i=b+(d-b>>>1);h=0;c=g<k?g:k;a=m[i];for(j=c;j<a.F;j++){if(e+c===n){h=-1;break}h=f.E.charCodeAt(e+c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){d=i;k=c}else{b=i;g=c}if(d-b<=1){if(b>0){break}if(d===b){break}if(l){break}l=true}}while(true){a=m[b];if(g>=a.F){f._=e+a.F|0;if(a.H==null){return a.I}o=a.H(a.P);f._=e+a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function e(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.D;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.F-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.E.charCodeAt(e-1-c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.F){d._=e-a.F|0;if(a.H==null){return a.I}o=a.H(d);d._=e-a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function B(a,b,d,e){var c;c=e.length-(d-b);a.E=a.E.slice(0,b)+e+a.E.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function c(a,f){var b;var c;var d;var e;b=false;if((c=a.B)<0||c>(d=a.C)||d>(e=a.A)||e>a.E.length?false:true){B(a,a.B,a.C,f);b=true}return b};i.prototype.J=function(){return false};i.prototype.a=function(b){var a;var c;var d;var e;a=this.G['.'+b];if(a==null){c=this.E=b;d=this._=0;e=this.A=c.length;this.D=0;this.B=d;this.C=e;this.J();a=this.E;this.G['.'+b]=a}return a};i.prototype.stemWord=i.prototype.a;i.prototype.b=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.G['.'+c];if(a==null){f=this.E=c;g=this._=0;h=this.A=f.length;this.D=0;this.B=g;this.C=h;this.J();a=this.E;this.G['.'+c]=a}d.push(a)}return d};i.prototype.stemWords=i.prototype.b;function b(){i.call(this);this.I_p2=0;this.I_p1=0;this.I_pV=0};l([b],i);b.prototype.M=function(a){this.I_p2=a.I_p2;this.I_p1=a.I_p1;this.I_pV=a.I_pV;v(this,a)};b.prototype.copy_from=b.prototype.M;b.prototype.V=function(){var a;var e;var d;b:while(true){e=this._;d=true;a:while(d===true){d=false;this.B=this._;a=m(this,b.a_0,3);if(a===0){break a}this.C=this._;switch(a){case 0:break a;case 1:if(!c(this,'a~')){return false}break;case 2:if(!c(this,'o~')){return false}break;case 3:if(this._>=this.A){break a}this._++;break}continue b}this._=e;break b}return true};b.prototype.r_prelude=b.prototype.V;function E(a){var d;var f;var e;b:while(true){f=a._;e=true;a:while(e===true){e=false;a.B=a._;d=m(a,b.a_0,3);if(d===0){break a}a.C=a._;switch(d){case 0:break a;case 1:if(!c(a,'a~')){return false}break;case 2:if(!c(a,'o~')){return false}break;case 3:if(a._>=a.A){break a}a._++;break}continue b}a._=f;break b}return true};b.prototype.T=function(){var u;var w;var x;var y;var t;var l;var d;var e;var h;var i;var c;var j;var k;var a;var m;var n;var o;var p;var q;var r;var s;var v;this.I_pV=s=this.A;this.I_p1=s;this.I_p2=s;u=this._;l=true;a:while(l===true){l=false;d=true;g:while(d===true){d=false;w=this._;e=true;b:while(e===true){e=false;if(!f(this,b.g_v,97,250)){break b}h=true;f:while(h===true){h=false;x=this._;i=true;c:while(i===true){i=false;if(!g(this,b.g_v,97,250)){break c}d:while(true){c=true;e:while(c===true){c=false;if(!f(this,b.g_v,97,250)){break e}break d}if(this._>=this.A){break c}this._++}break f}this._=x;if(!f(this,b.g_v,97,250)){break b}c:while(true){j=true;d:while(j===true){j=false;if(!g(this,b.g_v,97,250)){break d}break c}if(this._>=this.A){break b}this._++}}break g}this._=w;if(!g(this,b.g_v,97,250)){break a}k=true;c:while(k===true){k=false;y=this._;a=true;b:while(a===true){a=false;if(!g(this,b.g_v,97,250)){break b}e:while(true){m=true;d:while(m===true){m=false;if(!f(this,b.g_v,97,250)){break d}break e}if(this._>=this.A){break b}this._++}break c}this._=y;if(!f(this,b.g_v,97,250)){break a}if(this._>=this.A){break a}this._++}}this.I_pV=this._}v=this._=u;t=v;n=true;a:while(n===true){n=false;b:while(true){o=true;c:while(o===true){o=false;if(!f(this,b.g_v,97,250)){break c}break b}if(this._>=this.A){break a}this._++}b:while(true){p=true;c:while(p===true){p=false;if(!g(this,b.g_v,97,250)){break c}break b}if(this._>=this.A){break a}this._++}this.I_p1=this._;b:while(true){q=true;c:while(q===true){q=false;if(!f(this,b.g_v,97,250)){break c}break b}if(this._>=this.A){break a}this._++}c:while(true){r=true;b:while(r===true){r=false;if(!g(this,b.g_v,97,250)){break b}break c}if(this._>=this.A){break a}this._++}this.I_p2=this._}this._=t;return true};b.prototype.r_mark_regions=b.prototype.T;function F(a){var x;var y;var z;var u;var v;var l;var d;var e;var h;var i;var j;var k;var c;var m;var n;var o;var p;var q;var r;var s;var t;var w;a.I_pV=t=a.A;a.I_p1=t;a.I_p2=t;x=a._;l=true;a:while(l===true){l=false;d=true;g:while(d===true){d=false;y=a._;e=true;b:while(e===true){e=false;if(!f(a,b.g_v,97,250)){break b}h=true;f:while(h===true){h=false;z=a._;i=true;c:while(i===true){i=false;if(!g(a,b.g_v,97,250)){break c}d:while(true){j=true;e:while(j===true){j=false;if(!f(a,b.g_v,97,250)){break e}break d}if(a._>=a.A){break c}a._++}break f}a._=z;if(!f(a,b.g_v,97,250)){break b}c:while(true){k=true;d:while(k===true){k=false;if(!g(a,b.g_v,97,250)){break d}break c}if(a._>=a.A){break b}a._++}}break g}a._=y;if(!g(a,b.g_v,97,250)){break a}c=true;c:while(c===true){c=false;u=a._;m=true;b:while(m===true){m=false;if(!g(a,b.g_v,97,250)){break b}e:while(true){n=true;d:while(n===true){n=false;if(!f(a,b.g_v,97,250)){break d}break e}if(a._>=a.A){break b}a._++}break c}a._=u;if(!f(a,b.g_v,97,250)){break a}if(a._>=a.A){break a}a._++}}a.I_pV=a._}w=a._=x;v=w;o=true;a:while(o===true){o=false;b:while(true){p=true;c:while(p===true){p=false;if(!f(a,b.g_v,97,250)){break c}break b}if(a._>=a.A){break a}a._++}b:while(true){q=true;c:while(q===true){q=false;if(!g(a,b.g_v,97,250)){break c}break b}if(a._>=a.A){break a}a._++}a.I_p1=a._;b:while(true){r=true;c:while(r===true){r=false;if(!f(a,b.g_v,97,250)){break c}break b}if(a._>=a.A){break a}a._++}c:while(true){s=true;b:while(s===true){s=false;if(!g(a,b.g_v,97,250)){break b}break c}if(a._>=a.A){break a}a._++}a.I_p2=a._}a._=v;return true};b.prototype.U=function(){var a;var e;var d;b:while(true){e=this._;d=true;a:while(d===true){d=false;this.B=this._;a=m(this,b.a_1,3);if(a===0){break a}this.C=this._;switch(a){case 0:break a;case 1:if(!c(this,'ã')){return false}break;case 2:if(!c(this,'õ')){return false}break;case 3:if(this._>=this.A){break a}this._++;break}continue b}this._=e;break b}return true};b.prototype.r_postlude=b.prototype.U;function G(a){var d;var f;var e;b:while(true){f=a._;e=true;a:while(e===true){e=false;a.B=a._;d=m(a,b.a_1,3);if(d===0){break a}a.C=a._;switch(d){case 0:break a;case 1:if(!c(a,'ã')){return false}break;case 2:if(!c(a,'õ')){return false}break;case 3:if(a._>=a.A){break a}a._++;break}continue b}a._=f;break b}return true};b.prototype.S=function(){return!(this.I_pV<=this._)?false:true};b.prototype.r_RV=b.prototype.S;b.prototype.Q=function(){return!(this.I_p1<=this._)?false:true};b.prototype.r_R1=b.prototype.Q;b.prototype.R=function(){return!(this.I_p2<=this._)?false:true};b.prototype.r_R2=b.prototype.R;b.prototype.Y=function(){var a;var f;var g;var h;var j;var i;var k;var l;var m;var o;var p;var n;this.C=this._;a=e(this,b.a_5,45);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}break;case 2:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'log')){return false}break;case 3:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'u')){return false}break;case 4:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'ente')){return false}break;case 5:if(!(!(this.I_p1<=this._)?false:true)){return false}if(!c(this,'')){return false}f=this.A-this._;i=true;a:while(i===true){i=false;this.C=this._;a=e(this,b.a_2,4);if(a===0){this._=this.A-f;break a}this.B=o=this._;if(!(!(this.I_p2<=o)?false:true)){this._=this.A-f;break a}if(!c(this,'')){return false}switch(a){case 0:this._=this.A-f;break a;case 1:this.C=this._;if(!d(this,2,'at')){this._=this.A-f;break a}this.B=p=this._;if(!(!(this.I_p2<=p)?false:true)){this._=this.A-f;break a}if(!c(this,'')){return false}break}}break;case 6:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}g=this.A-this._;k=true;a:while(k===true){k=false;this.C=this._;a=e(this,b.a_3,3);if(a===0){this._=this.A-g;break a}this.B=this._;switch(a){case 0:this._=this.A-g;break a;case 1:if(!(!(this.I_p2<=this._)?false:true)){this._=this.A-g;break a}if(!c(this,'')){return false}break}}break;case 7:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}h=this.A-this._;l=true;a:while(l===true){l=false;this.C=this._;a=e(this,b.a_4,3);if(a===0){this._=this.A-h;break a}this.B=this._;switch(a){case 0:this._=this.A-h;break a;case 1:if(!(!(this.I_p2<=this._)?false:true)){this._=this.A-h;break a}if(!c(this,'')){return false}break}}break;case 8:if(!(!(this.I_p2<=this._)?false:true)){return false}if(!c(this,'')){return false}j=this.A-this._;m=true;a:while(m===true){m=false;this.C=this._;if(!d(this,2,'at')){this._=this.A-j;break a}this.B=n=this._;if(!(!(this.I_p2<=n)?false:true)){this._=this.A-j;break a}if(!c(this,'')){return false}}break;case 9:if(!(!(this.I_pV<=this._)?false:true)){return false}if(!d(this,1,'e')){return false}if(!c(this,'ir')){return false}break}return true};b.prototype.r_standard_suffix=b.prototype.Y;function H(a){var f;var g;var h;var i;var k;var j;var l;var m;var n;var p;var q;var o;a.C=a._;f=e(a,b.a_5,45);if(f===0){return false}a.B=a._;switch(f){case 0:return false;case 1:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}break;case 2:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'log')){return false}break;case 3:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'u')){return false}break;case 4:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'ente')){return false}break;case 5:if(!(!(a.I_p1<=a._)?false:true)){return false}if(!c(a,'')){return false}g=a.A-a._;j=true;a:while(j===true){j=false;a.C=a._;f=e(a,b.a_2,4);if(f===0){a._=a.A-g;break a}a.B=p=a._;if(!(!(a.I_p2<=p)?false:true)){a._=a.A-g;break a}if(!c(a,'')){return false}switch(f){case 0:a._=a.A-g;break a;case 1:a.C=a._;if(!d(a,2,'at')){a._=a.A-g;break a}a.B=q=a._;if(!(!(a.I_p2<=q)?false:true)){a._=a.A-g;break a}if(!c(a,'')){return false}break}}break;case 6:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}h=a.A-a._;l=true;a:while(l===true){l=false;a.C=a._;f=e(a,b.a_3,3);if(f===0){a._=a.A-h;break a}a.B=a._;switch(f){case 0:a._=a.A-h;break a;case 1:if(!(!(a.I_p2<=a._)?false:true)){a._=a.A-h;break a}if(!c(a,'')){return false}break}}break;case 7:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}i=a.A-a._;m=true;a:while(m===true){m=false;a.C=a._;f=e(a,b.a_4,3);if(f===0){a._=a.A-i;break a}a.B=a._;switch(f){case 0:a._=a.A-i;break a;case 1:if(!(!(a.I_p2<=a._)?false:true)){a._=a.A-i;break a}if(!c(a,'')){return false}break}}break;case 8:if(!(!(a.I_p2<=a._)?false:true)){return false}if(!c(a,'')){return false}k=a.A-a._;n=true;a:while(n===true){n=false;a.C=a._;if(!d(a,2,'at')){a._=a.A-k;break a}a.B=o=a._;if(!(!(a.I_p2<=o)?false:true)){a._=a.A-k;break a}if(!c(a,'')){return false}}break;case 9:if(!(!(a.I_pV<=a._)?false:true)){return false}if(!d(a,1,'e')){return false}if(!c(a,'ir')){return false}break}return true};b.prototype.Z=function(){var d;var f;var a;var g;var h;var i;f=this.A-(g=this._);if(g<this.I_pV){return false}h=this._=this.I_pV;a=this.D;this.D=h;i=this._=this.A-f;this.C=i;d=e(this,b.a_6,120);if(d===0){this.D=a;return false}this.B=this._;switch(d){case 0:this.D=a;return false;case 1:if(!c(this,'')){return false}break}this.D=a;return true};b.prototype.r_verb_suffix=b.prototype.Z;function D(a){var f;var g;var d;var h;var i;var j;g=a.A-(h=a._);if(h<a.I_pV){return false}i=a._=a.I_pV;d=a.D;a.D=i;j=a._=a.A-g;a.C=j;f=e(a,b.a_6,120);if(f===0){a.D=d;return false}a.B=a._;switch(f){case 0:a.D=d;return false;case 1:if(!c(a,'')){return false}break}a.D=d;return true};b.prototype.X=function(){var a;this.C=this._;a=e(this,b.a_7,7);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:if(!(!(this.I_pV<=this._)?false:true)){return false}if(!c(this,'')){return false}break}return true};b.prototype.r_residual_suffix=b.prototype.X;function C(a){var d;a.C=a._;d=e(a,b.a_7,7);if(d===0){return false}a.B=a._;switch(d){case 0:return false;case 1:if(!(!(a.I_pV<=a._)?false:true)){return false}if(!c(a,'')){return false}break}return true};b.prototype.W=function(){var a;var h;var i;var j;var f;var g;var k;var l;this.C=this._;a=e(this,b.a_8,4);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:if(!(!(this.I_pV<=this._)?false:true)){return false}if(!c(this,'')){return false}this.C=this._;f=true;b:while(f===true){f=false;h=this.A-this._;g=true;a:while(g===true){g=false;if(!d(this,1,'u')){break a}this.B=k=this._;i=this.A-k;if(!d(this,1,'g')){break a}this._=this.A-i;break b}this._=this.A-h;if(!d(this,1,'i')){return false}this.B=l=this._;j=this.A-l;if(!d(this,1,'c')){return false}this._=this.A-j}if(!(!(this.I_pV<=this._)?false:true)){return false}if(!c(this,'')){return false}break;case 2:if(!c(this,'c')){return false}break}return true};b.prototype.r_residual_form=b.prototype.W;function y(a){var f;var i;var j;var k;var g;var h;var l;var m;a.C=a._;f=e(a,b.a_8,4);if(f===0){return false}a.B=a._;switch(f){case 0:return false;case 1:if(!(!(a.I_pV<=a._)?false:true)){return false}if(!c(a,'')){return false}a.C=a._;g=true;b:while(g===true){g=false;i=a.A-a._;h=true;a:while(h===true){h=false;if(!d(a,1,'u')){break a}a.B=l=a._;j=a.A-l;if(!d(a,1,'g')){break a}a._=a.A-j;break b}a._=a.A-i;if(!d(a,1,'i')){return false}a.B=m=a._;k=a.A-m;if(!d(a,1,'c')){return false}a._=a.A-k}if(!(!(a.I_pV<=a._)?false:true)){return false}if(!c(a,'')){return false}break;case 2:if(!c(a,'c')){return false}break}return true};b.prototype.J=function(){var q;var n;var o;var p;var r;var s;var t;var u;var v;var b;var e;var f;var g;var a;var h;var i;var j;var k;var l;var w;var x;var z;var A;var B;var I;var J;var K;var m;q=this._;b=true;a:while(b===true){b=false;if(!E(this)){break a}}w=this._=q;n=w;e=true;a:while(e===true){e=false;if(!F(this)){break a}}I=this._=n;this.D=I;K=this._=J=this.A;o=J-K;f=true;b:while(f===true){f=false;g=true;c:while(g===true){g=false;p=this.A-this._;a=true;d:while(a===true){a=false;r=this.A-this._;h=true;a:while(h===true){h=false;s=this.A-this._;i=true;e:while(i===true){i=false;if(!H(this)){break e}break a}this._=this.A-s;if(!D(this)){break d}}B=this._=(A=this.A)-r;t=A-B;j=true;a:while(j===true){j=false;this.C=this._;if(!d(this,1,'i')){break a}this.B=x=this._;u=this.A-x;if(!d(this,1,'c')){break a}z=this._=this.A-u;if(!(!(this.I_pV<=z)?false:true)){break a}if(!c(this,'')){return false}}this._=this.A-t;break c}this._=this.A-p;if(!C(this)){break b}}}this._=this.A-o;k=true;a:while(k===true){k=false;if(!y(this)){break a}}m=this._=this.D;v=m;l=true;a:while(l===true){l=false;if(!G(this)){break a}}this._=v;return true};b.prototype.stem=b.prototype.J;b.prototype.N=function(a){return a instanceof b};b.prototype.equals=b.prototype.N;b.prototype.O=function(){var c;var a;var b;var d;c='PortugueseStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};b.prototype.hashCode=b.prototype.O;b.serialVersionUID=1;h(b,'methodObject',function(){return new b});h(b,'a_0',function(){return[new a('',-1,3),new a('ã',0,1),new a('õ',0,2)]});h(b,'a_1',function(){return[new a('',-1,3),new a('a~',0,1),new a('o~',0,2)]});h(b,'a_2',function(){return[new a('ic',-1,-1),new a('ad',-1,-1),new a('os',-1,-1),new a('iv',-1,1)]});h(b,'a_3',function(){return[new a('ante',-1,1),new a('avel',-1,1),new a('ível',-1,1)]});h(b,'a_4',function(){return[new a('ic',-1,1),new a('abil',-1,1),new a('iv',-1,1)]});h(b,'a_5',function(){return[new a('ica',-1,1),new a('ância',-1,1),new a('ência',-1,4),new a('ira',-1,9),new a('adora',-1,1),new a('osa',-1,1),new a('ista',-1,1),new a('iva',-1,8),new a('eza',-1,1),new a('logía',-1,2),new a('idade',-1,7),new a('ante',-1,1),new a('mente',-1,6),new a('amente',12,5),new a('ável',-1,1),new a('ível',-1,1),new a('ución',-1,3),new a('ico',-1,1),new a('ismo',-1,1),new a('oso',-1,1),new a('amento',-1,1),new a('imento',-1,1),new a('ivo',-1,8),new a('aça~o',-1,1),new a('ador',-1,1),new a('icas',-1,1),new a('ências',-1,4),new a('iras',-1,9),new a('adoras',-1,1),new a('osas',-1,1),new a('istas',-1,1),new a('ivas',-1,8),new a('ezas',-1,1),new a('logías',-1,2),new a('idades',-1,7),new a('uciones',-1,3),new a('adores',-1,1),new a('antes',-1,1),new a('aço~es',-1,1),new a('icos',-1,1),new a('ismos',-1,1),new a('osos',-1,1),new a('amentos',-1,1),new a('imentos',-1,1),new a('ivos',-1,8)]});h(b,'a_6',function(){return[new a('ada',-1,1),new a('ida',-1,1),new a('ia',-1,1),new a('aria',2,1),new a('eria',2,1),new a('iria',2,1),new a('ara',-1,1),new a('era',-1,1),new a('ira',-1,1),new a('ava',-1,1),new a('asse',-1,1),new a('esse',-1,1),new a('isse',-1,1),new a('aste',-1,1),new a('este',-1,1),new a('iste',-1,1),new a('ei',-1,1),new a('arei',16,1),new a('erei',16,1),new a('irei',16,1),new a('am',-1,1),new a('iam',20,1),new a('ariam',21,1),new a('eriam',21,1),new a('iriam',21,1),new a('aram',20,1),new a('eram',20,1),new a('iram',20,1),new a('avam',20,1),new a('em',-1,1),new a('arem',29,1),new a('erem',29,1),new a('irem',29,1),new a('assem',29,1),new a('essem',29,1),new a('issem',29,1),new a('ado',-1,1),new a('ido',-1,1),new a('ando',-1,1),new a('endo',-1,1),new a('indo',-1,1),new a('ara~o',-1,1),new a('era~o',-1,1),new a('ira~o',-1,1),new a('ar',-1,1),new a('er',-1,1),new a('ir',-1,1),new a('as',-1,1),new a('adas',47,1),new a('idas',47,1),new a('ias',47,1),new a('arias',50,1),new a('erias',50,1),new a('irias',50,1),new a('aras',47,1),new a('eras',47,1),new a('iras',47,1),new a('avas',47,1),new a('es',-1,1),new a('ardes',58,1),new a('erdes',58,1),new a('irdes',58,1),new a('ares',58,1),new a('eres',58,1),new a('ires',58,1),new a('asses',58,1),new a('esses',58,1),new a('isses',58,1),new a('astes',58,1),new a('estes',58,1),new a('istes',58,1),new a('is',-1,1),new a('ais',71,1),new a('eis',71,1),new a('areis',73,1),new a('ereis',73,1),new a('ireis',73,1),new a('áreis',73,1),new a('éreis',73,1),new a('íreis',73,1),new a('ásseis',73,1),new a('ésseis',73,1),new a('ísseis',73,1),new a('áveis',73,1),new a('íeis',73,1),new a('aríeis',84,1),new a('eríeis',84,1),new a('iríeis',84,1),new a('ados',-1,1),new a('idos',-1,1),new a('amos',-1,1),new a('áramos',90,1),new a('éramos',90,1),new a('íramos',90,1),new a('ávamos',90,1),new a('íamos',90,1),new a('aríamos',95,1),new a('eríamos',95,1),new a('iríamos',95,1),new a('emos',-1,1),new a('aremos',99,1),new a('eremos',99,1),new a('iremos',99,1),new a('ássemos',99,1),new a('êssemos',99,1),new a('íssemos',99,1),new a('imos',-1,1),new a('armos',-1,1),new a('ermos',-1,1),new a('irmos',-1,1),new a('ámos',-1,1),new a('arás',-1,1),new a('erás',-1,1),new a('irás',-1,1),new a('eu',-1,1),new a('iu',-1,1),new a('ou',-1,1),new a('ará',-1,1),new a('erá',-1,1),new a('irá',-1,1)]});h(b,'a_7',function(){return[new a('a',-1,1),new a('i',-1,1),new a('o',-1,1),new a('os',-1,1),new a('á',-1,1),new a('í',-1,1),new a('ó',-1,1)]});h(b,'a_8',function(){return[new a('e',-1,1),new a('ç',-1,2),new a('é',-1,1),new a('ê',-1,1)]});h(b,'g_v',function(){return[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,3,19,12,2]});var o={'src/stemmer.jsx':{Stemmer:n},'src/portuguese-stemmer.jsx':{PortugueseStemmer:b}}}(JSX))
+var Stemmer = JSX.require("src/portuguese-stemmer.jsx").PortugueseStemmer;
+"""
+
+
+class SearchPortuguese(SearchLanguage):
+ lang = 'pt'
+ language_name = 'Portuguese'
+ js_stemmer_code = js_stemmer
+ stopwords = portuguese_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('portuguese')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/ro.py b/sphinx/search/ro.py
new file mode 100644
index 00000000..c4336f8b
--- /dev/null
+++ b/sphinx/search/ro.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.ro
+ ~~~~~~~~~~~~~~~~
+
+ Romanian search language: includes the JS Romanian stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage
+
+import snowballstemmer
+
+js_stemmer = u"""
+var JSX={};(function(j){function l(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function L(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function h(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function M(a,b,c){return a[b]=a[b]/c|0}var E=parseInt;var C=parseFloat;function N(a){return a!==a}var A=isFinite;var z=encodeURIComponent;var y=decodeURIComponent;var x=encodeURI;var w=decodeURI;var u=Object.prototype.toString;var D=Object.prototype.hasOwnProperty;function k(){}j.require=function(b){var a=r[b];return a!==undefined?a:null};j.profilerIsRunning=function(){return k.getResults!=null};j.getProfileResults=function(){return(k.getResults||function(){return{}})()};j.postProfileResults=function(a,b){if(k.postResults==null)throw new Error('profiler has not been turned on');return k.postResults(a,b)};j.resetProfileResults=function(){if(k.resetResults==null)throw new Error('profiler has not been turned on');return k.resetResults()};j.DEBUG=false;function t(){};l([t],Error);function a(a,b,c){this.F=a.length;this.K=a;this.L=b;this.I=c;this.H=null;this.P=null};l([a],Object);function n(){};l([n],Object);function g(){var a;var b;var c;this.G={};a=this.E='';b=this._=0;c=this.A=a.length;this.D=0;this.B=b;this.C=c};l([g],n);function v(a,b){a.E=b.E;a._=b._;a.A=b.A;a.D=b.D;a.B=b.B;a.C=b.C};function d(b,d,c,e){var a;if(b._>=b.A){return false}a=b.E.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function e(a,d,c,e){var b;if(a._>=a.A){return false}b=a.E.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function p(a,d,c,e){var b;if(a._<=a.D){return false}b=a.E.charCodeAt(a._-1);if(b>e||b<c){a._--;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._--;return true}return false};function m(a,b,d){var c;if(a.A-a._<b){return false}if(a.E.slice(c=a._,c+b)!==d){return false}a._+=b;return true};function i(a,b,d){var c;if(a._-a.D<b){return false}if(a.E.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function q(f,m,p){var b;var d;var e;var n;var g;var k;var l;var i;var h;var c;var a;var j;var o;b=0;d=p;e=f._;n=f.A;g=0;k=0;l=false;while(true){i=b+(d-b>>>1);h=0;c=g<k?g:k;a=m[i];for(j=c;j<a.F;j++){if(e+c===n){h=-1;break}h=f.E.charCodeAt(e+c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){d=i;k=c}else{b=i;g=c}if(d-b<=1){if(b>0){break}if(d===b){break}if(l){break}l=true}}while(true){a=m[b];if(g>=a.F){f._=e+a.F|0;if(a.H==null){return a.I}o=a.H(a.P);f._=e+a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function f(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.D;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.F-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.E.charCodeAt(e-1-c)-a.K.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.F){d._=e-a.F|0;if(a.H==null){return a.I}o=a.H(d);d._=e-a.F|0;if(o){return a.I}}b=a.L;if(b<0){return 0}}return-1};function s(a,b,d,e){var c;c=e.length-(d-b);a.E=a.E.slice(0,b)+e+a.E.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function c(a,f){var b;var c;var d;var e;b=false;if((c=a.B)<0||c>(d=a.C)||d>(e=a.A)||e>a.E.length?false:true){s(a,a.B,a.C,f);b=true}return b};g.prototype.J=function(){return false};g.prototype.b=function(b){var a;var c;var d;var e;a=this.G['.'+b];if(a==null){c=this.E=b;d=this._=0;e=this.A=c.length;this.D=0;this.B=d;this.C=e;this.J();a=this.E;this.G['.'+b]=a}return a};g.prototype.stemWord=g.prototype.b;g.prototype.c=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.G['.'+c];if(a==null){f=this.E=c;g=this._=0;h=this.A=f.length;this.D=0;this.B=g;this.C=h;this.J();a=this.E;this.G['.'+c]=a}d.push(a)}return d};g.prototype.stemWords=g.prototype.c;function b(){g.call(this);this.B_standard_suffix_removed=false;this.I_p2=0;this.I_p1=0;this.I_pV=0};l([b],g);b.prototype.M=function(a){this.B_standard_suffix_removed=a.B_standard_suffix_removed;this.I_p2=a.I_p2;this.I_p1=a.I_p1;this.I_pV=a.I_pV;v(this,a)};b.prototype.copy_from=b.prototype.M;b.prototype.W=function(){var i;var a;var j;var e;var f;var g;var h;var k;b:while(true){i=this._;e=true;d:while(e===true){e=false;e:while(true){a=this._;f=true;a:while(f===true){f=false;if(!d(this,b.g_v,97,259)){break a}this.B=this._;g=true;f:while(g===true){g=false;j=this._;h=true;c:while(h===true){h=false;if(!m(this,1,'u')){break c}this.C=this._;if(!d(this,b.g_v,97,259)){break c}if(!c(this,'U')){return false}break f}this._=j;if(!m(this,1,'i')){break a}this.C=this._;if(!d(this,b.g_v,97,259)){break a}if(!c(this,'I')){return false}}this._=a;break e}k=this._=a;if(k>=this.A){break d}this._++}continue b}this._=i;break b}return true};b.prototype.r_prelude=b.prototype.W;function G(a){var j;var e;var k;var f;var g;var h;var i;var l;b:while(true){j=a._;f=true;d:while(f===true){f=false;e:while(true){e=a._;g=true;a:while(g===true){g=false;if(!d(a,b.g_v,97,259)){break a}a.B=a._;h=true;f:while(h===true){h=false;k=a._;i=true;c:while(i===true){i=false;if(!m(a,1,'u')){break c}a.C=a._;if(!d(a,b.g_v,97,259)){break c}if(!c(a,'U')){return false}break f}a._=k;if(!m(a,1,'i')){break a}a.C=a._;if(!d(a,b.g_v,97,259)){break a}if(!c(a,'I')){return false}}a._=e;break e}l=a._=e;if(l>=a.A){break d}a._++}continue b}a._=j;break b}return true};b.prototype.U=function(){var u;var w;var x;var y;var t;var l;var f;var g;var h;var i;var c;var j;var k;var a;var m;var n;var o;var p;var q;var r;var s;var v;this.I_pV=s=this.A;this.I_p1=s;this.I_p2=s;u=this._;l=true;a:while(l===true){l=false;f=true;g:while(f===true){f=false;w=this._;g=true;b:while(g===true){g=false;if(!d(this,b.g_v,97,259)){break b}h=true;f:while(h===true){h=false;x=this._;i=true;c:while(i===true){i=false;if(!e(this,b.g_v,97,259)){break c}d:while(true){c=true;e:while(c===true){c=false;if(!d(this,b.g_v,97,259)){break e}break d}if(this._>=this.A){break c}this._++}break f}this._=x;if(!d(this,b.g_v,97,259)){break b}c:while(true){j=true;d:while(j===true){j=false;if(!e(this,b.g_v,97,259)){break d}break c}if(this._>=this.A){break b}this._++}}break g}this._=w;if(!e(this,b.g_v,97,259)){break a}k=true;c:while(k===true){k=false;y=this._;a=true;b:while(a===true){a=false;if(!e(this,b.g_v,97,259)){break b}e:while(true){m=true;d:while(m===true){m=false;if(!d(this,b.g_v,97,259)){break d}break e}if(this._>=this.A){break b}this._++}break c}this._=y;if(!d(this,b.g_v,97,259)){break a}if(this._>=this.A){break a}this._++}}this.I_pV=this._}v=this._=u;t=v;n=true;a:while(n===true){n=false;b:while(true){o=true;c:while(o===true){o=false;if(!d(this,b.g_v,97,259)){break c}break b}if(this._>=this.A){break a}this._++}b:while(true){p=true;c:while(p===true){p=false;if(!e(this,b.g_v,97,259)){break c}break b}if(this._>=this.A){break a}this._++}this.I_p1=this._;b:while(true){q=true;c:while(q===true){q=false;if(!d(this,b.g_v,97,259)){break c}break b}if(this._>=this.A){break a}this._++}c:while(true){r=true;b:while(r===true){r=false;if(!e(this,b.g_v,97,259)){break b}break c}if(this._>=this.A){break a}this._++}this.I_p2=this._}this._=t;return true};b.prototype.r_mark_regions=b.prototype.U;function H(a){var x;var y;var z;var u;var v;var l;var f;var g;var h;var i;var j;var k;var c;var m;var n;var o;var p;var q;var r;var s;var t;var w;a.I_pV=t=a.A;a.I_p1=t;a.I_p2=t;x=a._;l=true;a:while(l===true){l=false;f=true;g:while(f===true){f=false;y=a._;g=true;b:while(g===true){g=false;if(!d(a,b.g_v,97,259)){break b}h=true;f:while(h===true){h=false;z=a._;i=true;c:while(i===true){i=false;if(!e(a,b.g_v,97,259)){break c}d:while(true){j=true;e:while(j===true){j=false;if(!d(a,b.g_v,97,259)){break e}break d}if(a._>=a.A){break c}a._++}break f}a._=z;if(!d(a,b.g_v,97,259)){break b}c:while(true){k=true;d:while(k===true){k=false;if(!e(a,b.g_v,97,259)){break d}break c}if(a._>=a.A){break b}a._++}}break g}a._=y;if(!e(a,b.g_v,97,259)){break a}c=true;c:while(c===true){c=false;u=a._;m=true;b:while(m===true){m=false;if(!e(a,b.g_v,97,259)){break b}e:while(true){n=true;d:while(n===true){n=false;if(!d(a,b.g_v,97,259)){break d}break e}if(a._>=a.A){break b}a._++}break c}a._=u;if(!d(a,b.g_v,97,259)){break a}if(a._>=a.A){break a}a._++}}a.I_pV=a._}w=a._=x;v=w;o=true;a:while(o===true){o=false;b:while(true){p=true;c:while(p===true){p=false;if(!d(a,b.g_v,97,259)){break c}break b}if(a._>=a.A){break a}a._++}b:while(true){q=true;c:while(q===true){q=false;if(!e(a,b.g_v,97,259)){break c}break b}if(a._>=a.A){break a}a._++}a.I_p1=a._;b:while(true){r=true;c:while(r===true){r=false;if(!d(a,b.g_v,97,259)){break c}break b}if(a._>=a.A){break a}a._++}c:while(true){s=true;b:while(s===true){s=false;if(!e(a,b.g_v,97,259)){break b}break c}if(a._>=a.A){break a}a._++}a.I_p2=a._}a._=v;return true};b.prototype.V=function(){var a;var e;var d;b:while(true){e=this._;d=true;a:while(d===true){d=false;this.B=this._;a=q(this,b.a_0,3);if(a===0){break a}this.C=this._;switch(a){case 0:break a;case 1:if(!c(this,'i')){return false}break;case 2:if(!c(this,'u')){return false}break;case 3:if(this._>=this.A){break a}this._++;break}continue b}this._=e;break b}return true};b.prototype.r_postlude=b.prototype.V;function I(a){var d;var f;var e;b:while(true){f=a._;e=true;a:while(e===true){e=false;a.B=a._;d=q(a,b.a_0,3);if(d===0){break a}a.C=a._;switch(d){case 0:break a;case 1:if(!c(a,'i')){return false}break;case 2:if(!c(a,'u')){return false}break;case 3:if(a._>=a.A){break a}a._++;break}continue b}a._=f;break b}return true};b.prototype.S=function(){return!(this.I_pV<=this._)?false:true};b.prototype.r_RV=b.prototype.S;b.prototype.Q=function(){return!(this.I_p1<=this._)?false:true};b.prototype.r_R1=b.prototype.Q;b.prototype.R=function(){return!(this.I_p2<=this._)?false:true};b.prototype.r_R2=b.prototype.R;b.prototype.Y=function(){var a;var e;var d;var g;this.C=this._;a=f(this,b.a_1,16);if(a===0){return false}this.B=g=this._;if(!(!(this.I_p1<=g)?false:true)){return false}switch(a){case 0:return false;case 1:if(!c(this,'')){return false}break;case 2:if(!c(this,'a')){return false}break;case 3:if(!c(this,'e')){return false}break;case 4:if(!c(this,'i')){return false}break;case 5:e=this.A-this._;d=true;a:while(d===true){d=false;if(!i(this,2,'ab')){break a}return false}this._=this.A-e;if(!c(this,'i')){return false}break;case 6:if(!c(this,'at')){return false}break;case 7:if(!c(this,'aţi')){return false}break}return true};b.prototype.r_step_0=b.prototype.Y;function J(a){var d;var g;var e;var h;a.C=a._;d=f(a,b.a_1,16);if(d===0){return false}a.B=h=a._;if(!(!(a.I_p1<=h)?false:true)){return false}switch(d){case 0:return false;case 1:if(!c(a,'')){return false}break;case 2:if(!c(a,'a')){return false}break;case 3:if(!c(a,'e')){return false}break;case 4:if(!c(a,'i')){return false}break;case 5:g=a.A-a._;e=true;a:while(e===true){e=false;if(!i(a,2,'ab')){break a}return false}a._=a.A-g;if(!c(a,'i')){return false}break;case 6:if(!c(a,'at')){return false}break;case 7:if(!c(a,'aţi')){return false}break}return true};b.prototype.T=function(){var a;var d;var e;var g;d=this.A-(e=this._);this.C=e;a=f(this,b.a_2,46);if(a===0){return false}this.B=g=this._;if(!(!(this.I_p1<=g)?false:true)){return false}switch(a){case 0:return false;case 1:if(!c(this,'abil')){return false}break;case 2:if(!c(this,'ibil')){return false}break;case 3:if(!c(this,'iv')){return false}break;case 4:if(!c(this,'ic')){return false}break;case 5:if(!c(this,'at')){return false}break;case 6:if(!c(this,'it')){return false}break}this.B_standard_suffix_removed=true;this._=this.A-d;return true};b.prototype.r_combo_suffix=b.prototype.T;function o(a){var d;var e;var g;var h;e=a.A-(g=a._);a.C=g;d=f(a,b.a_2,46);if(d===0){return false}a.B=h=a._;if(!(!(a.I_p1<=h)?false:true)){return false}switch(d){case 0:return false;case 1:if(!c(a,'abil')){return false}break;case 2:if(!c(a,'ibil')){return false}break;case 3:if(!c(a,'iv')){return false}break;case 4:if(!c(a,'ic')){return false}break;case 5:if(!c(a,'at')){return false}break;case 6:if(!c(a,'it')){return false}break}a.B_standard_suffix_removed=true;a._=a.A-e;return true};b.prototype.X=function(){var a;var e;var d;var g;this.B_standard_suffix_removed=false;a:while(true){e=this.A-this._;d=true;b:while(d===true){d=false;if(!o(this)){break b}continue a}this._=this.A-e;break a}this.C=this._;a=f(this,b.a_3,62);if(a===0){return false}this.B=g=this._;if(!(!(this.I_p2<=g)?false:true)){return false}switch(a){case 0:return false;case 1:if(!c(this,'')){return false}break;case 2:if(!i(this,1,'ţ')){return false}this.B=this._;if(!c(this,'t')){return false}break;case 3:if(!c(this,'ist')){return false}break}this.B_standard_suffix_removed=true;return true};b.prototype.r_standard_suffix=b.prototype.X;function K(a){var d;var g;var e;var h;a.B_standard_suffix_removed=false;a:while(true){g=a.A-a._;e=true;b:while(e===true){e=false;if(!o(a)){break b}continue a}a._=a.A-g;break a}a.C=a._;d=f(a,b.a_3,62);if(d===0){return false}a.B=h=a._;if(!(!(a.I_p2<=h)?false:true)){return false}switch(d){case 0:return false;case 1:if(!c(a,'')){return false}break;case 2:if(!i(a,1,'ţ')){return false}a.B=a._;if(!c(a,'t')){return false}break;case 3:if(!c(a,'ist')){return false}break}a.B_standard_suffix_removed=true;return true};b.prototype.Z=function(){var d;var h;var a;var j;var e;var g;var k;var l;var m;h=this.A-(k=this._);if(k<this.I_pV){return false}l=this._=this.I_pV;a=this.D;this.D=l;m=this._=this.A-h;this.C=m;d=f(this,b.a_4,94);if(d===0){this.D=a;return false}this.B=this._;switch(d){case 0:this.D=a;return false;case 1:e=true;a:while(e===true){e=false;j=this.A-this._;g=true;b:while(g===true){g=false;if(!p(this,b.g_v,97,259)){break b}break a}this._=this.A-j;if(!i(this,1,'u')){this.D=a;return false}}if(!c(this,'')){return false}break;case 2:if(!c(this,'')){return false}break}this.D=a;return true};b.prototype.r_verb_suffix=b.prototype.Z;function F(a){var e;var l;var d;var j;var g;var h;var m;var n;var k;l=a.A-(m=a._);if(m<a.I_pV){return false}n=a._=a.I_pV;d=a.D;a.D=n;k=a._=a.A-l;a.C=k;e=f(a,b.a_4,94);if(e===0){a.D=d;return false}a.B=a._;switch(e){case 0:a.D=d;return false;case 1:g=true;a:while(g===true){g=false;j=a.A-a._;h=true;b:while(h===true){h=false;if(!p(a,b.g_v,97,259)){break b}break a}a._=a.A-j;if(!i(a,1,'u')){a.D=d;return false}}if(!c(a,'')){return false}break;case 2:if(!c(a,'')){return false}break}a.D=d;return true};b.prototype.a=function(){var a;var d;this.C=this._;a=f(this,b.a_5,5);if(a===0){return false}this.B=d=this._;if(!(!(this.I_pV<=d)?false:true)){return false}switch(a){case 0:return false;case 1:if(!c(this,'')){return false}break}return true};b.prototype.r_vowel_suffix=b.prototype.a;function B(a){var d;var e;a.C=a._;d=f(a,b.a_5,5);if(d===0){return false}a.B=e=a._;if(!(!(a.I_pV<=e)?false:true)){return false}switch(d){case 0:return false;case 1:if(!c(a,'')){return false}break}return true};b.prototype.J=function(){var n;var j;var k;var l;var m;var o;var p;var b;var c;var d;var e;var f;var a;var g;var h;var i;var r;var s;var t;var u;var v;var w;var x;var y;var q;n=this._;b=true;a:while(b===true){b=false;if(!G(this)){break a}}r=this._=n;j=r;c=true;a:while(c===true){c=false;if(!H(this)){break a}}s=this._=j;this.D=s;u=this._=t=this.A;k=t-u;d=true;a:while(d===true){d=false;if(!J(this)){break a}}w=this._=(v=this.A)-k;l=v-w;e=true;a:while(e===true){e=false;if(!K(this)){break a}}y=this._=(x=this.A)-l;m=x-y;f=true;a:while(f===true){f=false;a=true;b:while(a===true){a=false;o=this.A-this._;g=true;c:while(g===true){g=false;if(!this.B_standard_suffix_removed){break c}break b}this._=this.A-o;if(!F(this)){break a}}}this._=this.A-m;h=true;a:while(h===true){h=false;if(!B(this)){break a}}q=this._=this.D;p=q;i=true;a:while(i===true){i=false;if(!I(this)){break a}}this._=p;return true};b.prototype.stem=b.prototype.J;b.prototype.N=function(a){return a instanceof b};b.prototype.equals=b.prototype.N;b.prototype.O=function(){var c;var a;var b;var d;c='RomanianStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};b.prototype.hashCode=b.prototype.O;b.serialVersionUID=1;h(b,'methodObject',function(){return new b});h(b,'a_0',function(){return[new a('',-1,3),new a('I',0,1),new a('U',0,2)]});h(b,'a_1',function(){return[new a('ea',-1,3),new a('aţia',-1,7),new a('aua',-1,2),new a('iua',-1,4),new a('aţie',-1,7),new a('ele',-1,3),new a('ile',-1,5),new a('iile',6,4),new a('iei',-1,4),new a('atei',-1,6),new a('ii',-1,4),new a('ului',-1,1),new a('ul',-1,1),new a('elor',-1,3),new a('ilor',-1,4),new a('iilor',14,4)]});h(b,'a_2',function(){return[new a('icala',-1,4),new a('iciva',-1,4),new a('ativa',-1,5),new a('itiva',-1,6),new a('icale',-1,4),new a('aţiune',-1,5),new a('iţiune',-1,6),new a('atoare',-1,5),new a('itoare',-1,6),new a('ătoare',-1,5),new a('icitate',-1,4),new a('abilitate',-1,1),new a('ibilitate',-1,2),new a('ivitate',-1,3),new a('icive',-1,4),new a('ative',-1,5),new a('itive',-1,6),new a('icali',-1,4),new a('atori',-1,5),new a('icatori',18,4),new a('itori',-1,6),new a('ători',-1,5),new a('icitati',-1,4),new a('abilitati',-1,1),new a('ivitati',-1,3),new a('icivi',-1,4),new a('ativi',-1,5),new a('itivi',-1,6),new a('icităi',-1,4),new a('abilităi',-1,1),new a('ivităi',-1,3),new a('icităţi',-1,4),new a('abilităţi',-1,1),new a('ivităţi',-1,3),new a('ical',-1,4),new a('ator',-1,5),new a('icator',35,4),new a('itor',-1,6),new a('ător',-1,5),new a('iciv',-1,4),new a('ativ',-1,5),new a('itiv',-1,6),new a('icală',-1,4),new a('icivă',-1,4),new a('ativă',-1,5),new a('itivă',-1,6)]});h(b,'a_3',function(){return[new a('ica',-1,1),new a('abila',-1,1),new a('ibila',-1,1),new a('oasa',-1,1),new a('ata',-1,1),new a('ita',-1,1),new a('anta',-1,1),new a('ista',-1,3),new a('uta',-1,1),new a('iva',-1,1),new a('ic',-1,1),new a('ice',-1,1),new a('abile',-1,1),new a('ibile',-1,1),new a('isme',-1,3),new a('iune',-1,2),new a('oase',-1,1),new a('ate',-1,1),new a('itate',17,1),new a('ite',-1,1),new a('ante',-1,1),new a('iste',-1,3),new a('ute',-1,1),new a('ive',-1,1),new a('ici',-1,1),new a('abili',-1,1),new a('ibili',-1,1),new a('iuni',-1,2),new a('atori',-1,1),new a('osi',-1,1),new a('ati',-1,1),new a('itati',30,1),new a('iti',-1,1),new a('anti',-1,1),new a('isti',-1,3),new a('uti',-1,1),new a('işti',-1,3),new a('ivi',-1,1),new a('ităi',-1,1),new a('oşi',-1,1),new a('ităţi',-1,1),new a('abil',-1,1),new a('ibil',-1,1),new a('ism',-1,3),new a('ator',-1,1),new a('os',-1,1),new a('at',-1,1),new a('it',-1,1),new a('ant',-1,1),new a('ist',-1,3),new a('ut',-1,1),new a('iv',-1,1),new a('ică',-1,1),new a('abilă',-1,1),new a('ibilă',-1,1),new a('oasă',-1,1),new a('ată',-1,1),new a('ită',-1,1),new a('antă',-1,1),new a('istă',-1,3),new a('ută',-1,1),new a('ivă',-1,1)]});h(b,'a_4',function(){return[new a('ea',-1,1),new a('ia',-1,1),new a('esc',-1,1),new a('ăsc',-1,1),new a('ind',-1,1),new a('ând',-1,1),new a('are',-1,1),new a('ere',-1,1),new a('ire',-1,1),new a('âre',-1,1),new a('se',-1,2),new a('ase',10,1),new a('sese',10,2),new a('ise',10,1),new a('use',10,1),new a('âse',10,1),new a('eşte',-1,1),new a('ăşte',-1,1),new a('eze',-1,1),new a('ai',-1,1),new a('eai',19,1),new a('iai',19,1),new a('sei',-1,2),new a('eşti',-1,1),new a('ăşti',-1,1),new a('ui',-1,1),new a('ezi',-1,1),new a('âi',-1,1),new a('aşi',-1,1),new a('seşi',-1,2),new a('aseşi',29,1),new a('seseşi',29,2),new a('iseşi',29,1),new a('useşi',29,1),new a('âseşi',29,1),new a('işi',-1,1),new a('uşi',-1,1),new a('âşi',-1,1),new a('aţi',-1,2),new a('eaţi',38,1),new a('iaţi',38,1),new a('eţi',-1,2),new a('iţi',-1,2),new a('âţi',-1,2),new a('arăţi',-1,1),new a('serăţi',-1,2),new a('aserăţi',45,1),new a('seserăţi',45,2),new a('iserăţi',45,1),new a('userăţi',45,1),new a('âserăţi',45,1),new a('irăţi',-1,1),new a('urăţi',-1,1),new a('ârăţi',-1,1),new a('am',-1,1),new a('eam',54,1),new a('iam',54,1),new a('em',-1,2),new a('asem',57,1),new a('sesem',57,2),new a('isem',57,1),new a('usem',57,1),new a('âsem',57,1),new a('im',-1,2),new a('âm',-1,2),new a('ăm',-1,2),new a('arăm',65,1),new a('serăm',65,2),new a('aserăm',67,1),new a('seserăm',67,2),new a('iserăm',67,1),new a('userăm',67,1),new a('âserăm',67,1),new a('irăm',65,1),new a('urăm',65,1),new a('ârăm',65,1),new a('au',-1,1),new a('eau',76,1),new a('iau',76,1),new a('indu',-1,1),new a('ându',-1,1),new a('ez',-1,1),new a('ească',-1,1),new a('ară',-1,1),new a('seră',-1,2),new a('aseră',84,1),new a('seseră',84,2),new a('iseră',84,1),new a('useră',84,1),new a('âseră',84,1),new a('iră',-1,1),new a('ură',-1,1),new a('âră',-1,1),new a('ează',-1,1)]});h(b,'a_5',function(){return[new a('a',-1,1),new a('e',-1,1),new a('ie',1,1),new a('i',-1,1),new a('ă',-1,1)]});h(b,'g_v',function(){return[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,2,32,0,0,4]});var r={'src/stemmer.jsx':{Stemmer:n},'src/romanian-stemmer.jsx':{RomanianStemmer:b}}}(JSX))
+var Stemmer = JSX.require("src/romanian-stemmer.jsx").RomanianStemmer;
+"""
+
+
+class SearchRomanian(SearchLanguage):
+ lang = 'ro'
+ language_name = 'Romanian'
+ js_stemmer_code = js_stemmer
+ stopwords = []
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('romanian')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/ru.py b/sphinx/search/ru.py
new file mode 100644
index 00000000..af019ea2
--- /dev/null
+++ b/sphinx/search/ru.py
@@ -0,0 +1,261 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.ru
+ ~~~~~~~~~~~~~~~~
+
+ Russian search language: includes the JS Russian stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+russian_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/russian/stop.txt
+и | and
+в | in/into
+во | alternative form
+не | not
+что | what/that
+он | he
+на | on/onto
+Ñ | i
+Ñ | from
+Ñо | alternative form
+как | how
+а | milder form of `no' (but)
+то | conjunction and form of `that'
+вÑе | all
+она | she
+так | so, thus
+его | him
+но | but
+да | yes/and
+Ñ‚Ñ‹ | thou
+к | towards, by
+у | around, chez
+же | intensifier particle
+вы | you
+за | beyond, behind
+бы | conditional/subj. particle
+по | up to, along
+только | only
+ее | her
+мне | to me
+было | it was
+вот | here is/are, particle
+от | away from
+Ð¼ÐµÐ½Ñ | me
+еще | still, yet, more
+нет | no, there isnt/arent
+о | about
+из | out of
+ему | to him
+теперь | now
+когда | when
+даже | even
+ну | so, well
+вдруг | suddenly
+ли | interrogative particle
+еÑли | if
+уже | already, but homonym of `narrower'
+или | or
+ни | neither
+быть | to be
+был | he was
+него | prepositional form of его
+до | up to
+Ð²Ð°Ñ | you accusative
+нибудь | indef. suffix preceded by hyphen
+опÑÑ‚ÑŒ | again
+уж | already, but homonym of `adder'
+вам | to you
+Ñказал | he said
+ведь | particle `after all'
+там | there
+потом | then
+ÑÐµÐ±Ñ | oneself
+ничего | nothing
+ей | to her
+может | usually with `быть' as `maybe'
+они | they
+тут | here
+где | where
+еÑÑ‚ÑŒ | there is/are
+надо | got to, must
+ней | prepositional form of ей
+Ð´Ð»Ñ | for
+мы | we
+Ñ‚ÐµÐ±Ñ | thee
+их | them, their
+чем | than
+была | she was
+Ñам | self
+чтоб | in order to
+без | without
+будто | as if
+человек | man, person, one
+чего | genitive form of `what'
+раз | once
+тоже | also
+Ñебе | to oneself
+под | beneath
+жизнь | life
+будет | will be
+ж | short form of intensifer particle `же'
+тогда | then
+кто | who
+Ñтот | this
+говорил | was saying
+того | genitive form of `that'
+потому | for that reason
+Ñтого | genitive form of `this'
+какой | which
+ÑовÑем | altogether
+ним | prepositional form of `его', `они'
+здеÑÑŒ | here
+Ñтом | prepositional form of `Ñтот'
+один | one
+почти | almost
+мой | my
+тем | instrumental/dative plural of `тот', `то'
+чтобы | full form of `in order that'
+нее | her (acc.)
+кажетÑÑ | it seems
+ÑÐµÐ¹Ñ‡Ð°Ñ | now
+были | they were
+куда | where to
+зачем | why
+Ñказать | to say
+вÑех | all (acc., gen. preposn. plural)
+никогда | never
+ÑÐµÐ³Ð¾Ð´Ð½Ñ | today
+можно | possible, one can
+при | by
+наконец | finally
+два | two
+об | alternative form of `о', about
+другой | another
+хоть | even
+поÑле | after
+над | above
+больше | more
+тот | that one (masc.)
+через | across, in
+Ñти | these
+Ð½Ð°Ñ | us
+про | about
+вÑего | in all, only, of all
+них | prepositional form of `они' (they)
+ÐºÐ°ÐºÐ°Ñ | which, feminine
+много | lots
+разве | interrogative particle
+Ñказала | she said
+три | three
+Ñту | this, acc. fem. sing.
+Ð¼Ð¾Ñ | my, feminine
+впрочем | moreover, besides
+хорошо | good
+Ñвою | ones own, acc. fem. sing.
+Ñтой | oblique form of `Ñта', fem. `this'
+перед | in front of
+иногда | sometimes
+лучше | better
+чуть | a little
+том | preposn. form of `that one'
+Ð½ÐµÐ»ÑŒÐ·Ñ | one must not
+такой | such a one
+им | to them
+более | more
+вÑегда | always
+конечно | of course
+вÑÑŽ | acc. fem. sing of `all'
+между | between
+
+
+ | b: some paradigms
+ |
+ | personal pronouns
+ |
+ | Ñ Ð¼ÐµÐ½Ñ Ð¼Ð½Ðµ мной [мною]
+ | Ñ‚Ñ‹ Ñ‚ÐµÐ±Ñ Ñ‚ÐµÐ±Ðµ тобой [тобою]
+ | он его ему им [него, нему, ним]
+ | она ее Ñи ею [нее, нÑи, нею]
+ | оно его ему им [него, нему, ним]
+ |
+ | мы Ð½Ð°Ñ Ð½Ð°Ð¼ нами
+ | вы Ð²Ð°Ñ Ð²Ð°Ð¼ вами
+ | они их им ими [них, ним, ними]
+ |
+ | ÑÐµÐ±Ñ Ñебе Ñобой [Ñобою]
+ |
+ | demonstrative pronouns: Ñтот (this), тот (that)
+ |
+ | Ñтот Ñта Ñто Ñти
+ | Ñтого ÑÑ‚Ñ‹ Ñто Ñти
+ | Ñтого Ñтой Ñтого Ñтих
+ | Ñтому Ñтой Ñтому Ñтим
+ | Ñтим Ñтой Ñтим [Ñтою] Ñтими
+ | Ñтом Ñтой Ñтом Ñтих
+ |
+ | тот та то те
+ | того ту то те
+ | того той того тех
+ | тому той тому тем
+ | тем той тем [тою] теми
+ | том той том тех
+ |
+ | determinative pronouns
+ |
+ | (a) веÑÑŒ (all)
+ |
+ | веÑÑŒ вÑÑ Ð²Ñе вÑе
+ | вÑего вÑÑŽ вÑе вÑе
+ | вÑего вÑей вÑего вÑех
+ | вÑему вÑей вÑему вÑем
+ | вÑем вÑей вÑем [вÑею] вÑеми
+ | вÑем вÑей вÑем вÑех
+ |
+ | (b) Ñам (himself etc)
+ |
+ | Ñам Ñама Ñамо Ñами
+ | Ñамого Ñаму Ñамо Ñамих
+ | Ñамого Ñамой Ñамого Ñамих
+ | Ñамому Ñамой Ñамому Ñамим
+ | Ñамим Ñамой Ñамим [Ñамою] Ñамими
+ | Ñамом Ñамой Ñамом Ñамих
+ |
+ | stems of verbs `to be', `to have', `to do' and modal
+ |
+ | быть бы буд быв еÑÑ‚ÑŒ Ñуть
+ | име
+ | дел
+ | мог мож мочь
+ | уме
+ | хоч хот
+ | долж
+ | можн
+ | нужн
+ | нельзÑ
+''')
+
+js_stemmer = u"""
+var JSX={};(function(h){function j(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function J(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function f(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function K(a,b,c){return a[b]=a[b]/c|0}var p=parseInt;var z=parseFloat;function L(a){return a!==a}var x=isFinite;var w=encodeURIComponent;var u=decodeURIComponent;var t=encodeURI;var s=decodeURI;var B=Object.prototype.toString;var q=Object.prototype.hasOwnProperty;function i(){}h.require=function(b){var a=o[b];return a!==undefined?a:null};h.profilerIsRunning=function(){return i.getResults!=null};h.getProfileResults=function(){return(i.getResults||function(){return{}})()};h.postProfileResults=function(a,b){if(i.postResults==null)throw new Error('profiler has not been turned on');return i.postResults(a,b)};h.resetProfileResults=function(){if(i.resetResults==null)throw new Error('profiler has not been turned on');return i.resetResults()};h.DEBUG=false;function r(){};j([r],Error);function a(a,b,c){this.G=a.length;this.X=a;this.a=b;this.J=c;this.I=null;this.b=null};j([a],Object);function m(){};j([m],Object);function g(){var a;var b;var c;this.F={};a=this.D='';b=this._=0;c=this.A=a.length;this.E=0;this.B=b;this.C=c};j([g],m);function v(a,b){a.D=b.D;a._=b._;a.A=b.A;a.E=b.E;a.B=b.B;a.C=b.C};function k(b,d,c,e){var a;if(b._>=b.A){return false}a=b.D.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function l(a,d,c,e){var b;if(a._>=a.A){return false}b=a.D.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function d(a,b,d){var c;if(a._-a.E<b){return false}if(a.D.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function e(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.E;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.G-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.D.charCodeAt(e-1-c)-a.X.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.G){d._=e-a.G|0;if(a.I==null){return a.J}o=a.I(d);d._=e-a.G|0;if(o){return a.J}}b=a.a;if(b<0){return 0}}return-1};function A(a,b,d,e){var c;c=e.length-(d-b);a.D=a.D.slice(0,b)+e+a.D.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function c(a,f){var b;var c;var d;var e;b=false;if((c=a.B)<0||c>(d=a.C)||d>(e=a.A)||e>a.D.length?false:true){A(a,a.B,a.C,f);b=true}return b};g.prototype.H=function(){return false};g.prototype.Y=function(b){var a;var c;var d;var e;a=this.F['.'+b];if(a==null){c=this.D=b;d=this._=0;e=this.A=c.length;this.E=0;this.B=d;this.C=e;this.H();a=this.D;this.F['.'+b]=a}return a};g.prototype.stemWord=g.prototype.Y;g.prototype.Z=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.F['.'+c];if(a==null){f=this.D=c;g=this._=0;h=this.A=f.length;this.E=0;this.B=g;this.C=h;this.H();a=this.D;this.F['.'+c]=a}d.push(a)}return d};g.prototype.stemWords=g.prototype.Z;function b(){g.call(this);this.I_p2=0;this.I_pV=0};j([b],g);b.prototype.K=function(a){this.I_p2=a.I_p2;this.I_pV=a.I_pV;v(this,a)};b.prototype.copy_from=b.prototype.K;b.prototype.R=function(){var g;var a;var c;var d;var e;var f;var h;this.I_pV=h=this.A;this.I_p2=h;g=this._;a=true;a:while(a===true){a=false;b:while(true){c=true;c:while(c===true){c=false;if(!k(this,b.g_v,1072,1103)){break c}break b}if(this._>=this.A){break a}this._++}this.I_pV=this._;b:while(true){d=true;c:while(d===true){d=false;if(!l(this,b.g_v,1072,1103)){break c}break b}if(this._>=this.A){break a}this._++}b:while(true){e=true;c:while(e===true){e=false;if(!k(this,b.g_v,1072,1103)){break c}break b}if(this._>=this.A){break a}this._++}b:while(true){f=true;c:while(f===true){f=false;if(!l(this,b.g_v,1072,1103)){break c}break b}if(this._>=this.A){break a}this._++}this.I_p2=this._}this._=g;return true};b.prototype.r_mark_regions=b.prototype.R;function D(a){var h;var c;var d;var e;var f;var g;var i;a.I_pV=i=a.A;a.I_p2=i;h=a._;c=true;a:while(c===true){c=false;b:while(true){d=true;c:while(d===true){d=false;if(!k(a,b.g_v,1072,1103)){break c}break b}if(a._>=a.A){break a}a._++}a.I_pV=a._;b:while(true){e=true;c:while(e===true){e=false;if(!l(a,b.g_v,1072,1103)){break c}break b}if(a._>=a.A){break a}a._++}b:while(true){f=true;c:while(f===true){f=false;if(!k(a,b.g_v,1072,1103)){break c}break b}if(a._>=a.A){break a}a._++}b:while(true){g=true;c:while(g===true){g=false;if(!l(a,b.g_v,1072,1103)){break c}break b}if(a._>=a.A){break a}a._++}a.I_p2=a._}a._=h;return true};b.prototype.N=function(){return!(this.I_p2<=this._)?false:true};b.prototype.r_R2=b.prototype.N;b.prototype.T=function(){var a;var h;var f;var g;this.C=this._;a=e(this,b.a_0,9);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:f=true;a:while(f===true){f=false;h=this.A-this._;g=true;b:while(g===true){g=false;if(!d(this,1,'а')){break b}break a}this._=this.A-h;if(!d(this,1,'Ñ')){return false}}if(!c(this,'')){return false}break;case 2:if(!c(this,'')){return false}break}return true};b.prototype.r_perfective_gerund=b.prototype.T;function E(a){var f;var i;var g;var h;a.C=a._;f=e(a,b.a_0,9);if(f===0){return false}a.B=a._;switch(f){case 0:return false;case 1:g=true;a:while(g===true){g=false;i=a.A-a._;h=true;b:while(h===true){h=false;if(!d(a,1,'а')){break b}break a}a._=a.A-i;if(!d(a,1,'Ñ')){return false}}if(!c(a,'')){return false}break;case 2:if(!c(a,'')){return false}break}return true};b.prototype.P=function(){var a;this.C=this._;a=e(this,b.a_1,26);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:if(!c(this,'')){return false}break}return true};b.prototype.r_adjective=b.prototype.P;function n(a){var d;a.C=a._;d=e(a,b.a_1,26);if(d===0){return false}a.B=a._;switch(d){case 0:return false;case 1:if(!c(a,'')){return false}break}return true};b.prototype.O=function(){var f;var a;var j;var g;var h;var i;if(!n(this)){return false}a=this.A-this._;g=true;a:while(g===true){g=false;this.C=this._;f=e(this,b.a_2,8);if(f===0){this._=this.A-a;break a}this.B=this._;switch(f){case 0:this._=this.A-a;break a;case 1:h=true;b:while(h===true){h=false;j=this.A-this._;i=true;c:while(i===true){i=false;if(!d(this,1,'а')){break c}break b}this._=this.A-j;if(!d(this,1,'Ñ')){this._=this.A-a;break a}}if(!c(this,'')){return false}break;case 2:if(!c(this,'')){return false}break}}return true};b.prototype.r_adjectival=b.prototype.O;function G(a){var g;var f;var k;var h;var i;var j;if(!n(a)){return false}f=a.A-a._;h=true;a:while(h===true){h=false;a.C=a._;g=e(a,b.a_2,8);if(g===0){a._=a.A-f;break a}a.B=a._;switch(g){case 0:a._=a.A-f;break a;case 1:i=true;b:while(i===true){i=false;k=a.A-a._;j=true;c:while(j===true){j=false;if(!d(a,1,'а')){break c}break b}a._=a.A-k;if(!d(a,1,'Ñ')){a._=a.A-f;break a}}if(!c(a,'')){return false}break;case 2:if(!c(a,'')){return false}break}}return true};b.prototype.U=function(){var a;this.C=this._;a=e(this,b.a_3,2);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:if(!c(this,'')){return false}break}return true};b.prototype.r_reflexive=b.prototype.U;function H(a){var d;a.C=a._;d=e(a,b.a_3,2);if(d===0){return false}a.B=a._;switch(d){case 0:return false;case 1:if(!c(a,'')){return false}break}return true};b.prototype.W=function(){var a;var h;var f;var g;this.C=this._;a=e(this,b.a_4,46);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:f=true;a:while(f===true){f=false;h=this.A-this._;g=true;b:while(g===true){g=false;if(!d(this,1,'а')){break b}break a}this._=this.A-h;if(!d(this,1,'Ñ')){return false}}if(!c(this,'')){return false}break;case 2:if(!c(this,'')){return false}break}return true};b.prototype.r_verb=b.prototype.W;function I(a){var f;var i;var g;var h;a.C=a._;f=e(a,b.a_4,46);if(f===0){return false}a.B=a._;switch(f){case 0:return false;case 1:g=true;a:while(g===true){g=false;i=a.A-a._;h=true;b:while(h===true){h=false;if(!d(a,1,'а')){break b}break a}a._=a.A-i;if(!d(a,1,'Ñ')){return false}}if(!c(a,'')){return false}break;case 2:if(!c(a,'')){return false}break}return true};b.prototype.S=function(){var a;this.C=this._;a=e(this,b.a_5,36);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:if(!c(this,'')){return false}break}return true};b.prototype.r_noun=b.prototype.S;function F(a){var d;a.C=a._;d=e(a,b.a_5,36);if(d===0){return false}a.B=a._;switch(d){case 0:return false;case 1:if(!c(a,'')){return false}break}return true};b.prototype.Q=function(){var a;var d;this.C=this._;a=e(this,b.a_6,2);if(a===0){return false}this.B=d=this._;if(!(!(this.I_p2<=d)?false:true)){return false}switch(a){case 0:return false;case 1:if(!c(this,'')){return false}break}return true};b.prototype.r_derivational=b.prototype.Q;function C(a){var d;var f;a.C=a._;d=e(a,b.a_6,2);if(d===0){return false}a.B=f=a._;if(!(!(a.I_p2<=f)?false:true)){return false}switch(d){case 0:return false;case 1:if(!c(a,'')){return false}break}return true};b.prototype.V=function(){var a;this.C=this._;a=e(this,b.a_7,4);if(a===0){return false}this.B=this._;switch(a){case 0:return false;case 1:if(!c(this,'')){return false}this.C=this._;if(!d(this,1,'н')){return false}this.B=this._;if(!d(this,1,'н')){return false}if(!c(this,'')){return false}break;case 2:if(!d(this,1,'н')){return false}if(!c(this,'')){return false}break;case 3:if(!c(this,'')){return false}break}return true};b.prototype.r_tidy_up=b.prototype.V;function y(a){var f;a.C=a._;f=e(a,b.a_7,4);if(f===0){return false}a.B=a._;switch(f){case 0:return false;case 1:if(!c(a,'')){return false}a.C=a._;if(!d(a,1,'н')){return false}a.B=a._;if(!d(a,1,'н')){return false}if(!c(a,'')){return false}break;case 2:if(!d(a,1,'н')){return false}if(!c(a,'')){return false}break;case 3:if(!c(a,'')){return false}break}return true};b.prototype.H=function(){var s;var v;var w;var A;var p;var q;var i;var t;var u;var e;var f;var g;var h;var a;var j;var b;var k;var l;var m;var n;var x;var z;var o;var B;var J;var K;var L;var M;var N;var O;var r;s=this._;e=true;a:while(e===true){e=false;if(!D(this)){break a}}x=this._=s;this.E=x;o=this._=z=this.A;v=z-o;if(o<this.I_pV){return false}K=this._=this.I_pV;w=this.E;this.E=K;M=this._=(L=this.A)-v;A=L-M;f=true;c:while(f===true){f=false;g=true;b:while(g===true){g=false;p=this.A-this._;h=true;a:while(h===true){h=false;if(!E(this)){break a}break b}J=this._=(B=this.A)-p;q=B-J;a=true;a:while(a===true){a=false;if(!H(this)){this._=this.A-q;break a}}j=true;a:while(j===true){j=false;i=this.A-this._;b=true;d:while(b===true){b=false;if(!G(this)){break d}break a}this._=this.A-i;k=true;d:while(k===true){k=false;if(!I(this)){break d}break a}this._=this.A-i;if(!F(this)){break c}}}}O=this._=(N=this.A)-A;t=N-O;l=true;a:while(l===true){l=false;this.C=this._;if(!d(this,1,'и')){this._=this.A-t;break a}this.B=this._;if(!c(this,'')){return false}}u=this.A-this._;m=true;a:while(m===true){m=false;if(!C(this)){break a}}this._=this.A-u;n=true;a:while(n===true){n=false;if(!y(this)){break a}}r=this.E=w;this._=r;return true};b.prototype.stem=b.prototype.H;b.prototype.L=function(a){return a instanceof b};b.prototype.equals=b.prototype.L;b.prototype.M=function(){var c;var a;var b;var d;c='RussianStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};b.prototype.hashCode=b.prototype.M;b.serialVersionUID=1;f(b,'methodObject',function(){return new b});f(b,'a_0',function(){return[new a('в',-1,1),new a('ив',0,2),new a('ыв',0,2),new a('вши',-1,1),new a('ивши',3,2),new a('ывши',3,2),new a('вшиÑÑŒ',-1,1),new a('ившиÑÑŒ',6,2),new a('ывшиÑÑŒ',6,2)]});f(b,'a_1',function(){return[new a('ее',-1,1),new a('ие',-1,1),new a('ое',-1,1),new a('ые',-1,1),new a('ими',-1,1),new a('ыми',-1,1),new a('ей',-1,1),new a('ий',-1,1),new a('ой',-1,1),new a('ый',-1,1),new a('ем',-1,1),new a('им',-1,1),new a('ом',-1,1),new a('ым',-1,1),new a('его',-1,1),new a('ого',-1,1),new a('ему',-1,1),new a('ому',-1,1),new a('их',-1,1),new a('Ñ‹Ñ…',-1,1),new a('ею',-1,1),new a('ою',-1,1),new a('ую',-1,1),new a('ÑŽÑŽ',-1,1),new a('аÑ',-1,1),new a('ÑÑ',-1,1)]});f(b,'a_2',function(){return[new a('ем',-1,1),new a('нн',-1,1),new a('вш',-1,1),new a('ивш',2,2),new a('ывш',2,2),new a('щ',-1,1),new a('ющ',5,1),new a('ующ',6,2)]});f(b,'a_3',function(){return[new a('ÑÑŒ',-1,1),new a('ÑÑ',-1,1)]});f(b,'a_4',function(){return[new a('ла',-1,1),new a('ила',0,2),new a('ыла',0,2),new a('на',-1,1),new a('ена',3,2),new a('ете',-1,1),new a('ите',-1,2),new a('йте',-1,1),new a('ейте',7,2),new a('уйте',7,2),new a('ли',-1,1),new a('или',10,2),new a('ыли',10,2),new a('й',-1,1),new a('ей',13,2),new a('уй',13,2),new a('л',-1,1),new a('ил',16,2),new a('ыл',16,2),new a('ем',-1,1),new a('им',-1,2),new a('ым',-1,2),new a('н',-1,1),new a('ен',22,2),new a('ло',-1,1),new a('ило',24,2),new a('ыло',24,2),new a('но',-1,1),new a('ено',27,2),new a('нно',27,1),new a('ет',-1,1),new a('ует',30,2),new a('ит',-1,2),new a('Ñ‹Ñ‚',-1,2),new a('ÑŽÑ‚',-1,1),new a('уют',34,2),new a('ÑÑ‚',-1,2),new a('ны',-1,1),new a('ены',37,2),new a('Ñ‚ÑŒ',-1,1),new a('ить',39,2),new a('Ñ‹Ñ‚ÑŒ',39,2),new a('ешь',-1,1),new a('ишь',-1,2),new a('ÑŽ',-1,2),new a('ую',44,2)]});f(b,'a_5',function(){return[new a('а',-1,1),new a('ев',-1,1),new a('ов',-1,1),new a('е',-1,1),new a('ие',3,1),new a('ье',3,1),new a('и',-1,1),new a('еи',6,1),new a('ии',6,1),new a('ами',6,1),new a('Ñми',6,1),new a('иÑми',10,1),new a('й',-1,1),new a('ей',12,1),new a('ией',13,1),new a('ий',12,1),new a('ой',12,1),new a('ам',-1,1),new a('ем',-1,1),new a('ием',18,1),new a('ом',-1,1),new a('Ñм',-1,1),new a('иÑм',21,1),new a('о',-1,1),new a('у',-1,1),new a('ах',-1,1),new a('ÑÑ…',-1,1),new a('иÑÑ…',26,1),new a('Ñ‹',-1,1),new a('ÑŒ',-1,1),new a('ÑŽ',-1,1),new a('ию',30,1),new a('ью',30,1),new a('Ñ',-1,1),new a('иÑ',33,1),new a('ÑŒÑ',33,1)]});f(b,'a_6',function(){return[new a('оÑÑ‚',-1,1),new a('оÑÑ‚ÑŒ',-1,1)]});f(b,'a_7',function(){return[new a('ейше',-1,1),new a('н',-1,2),new a('ейш',-1,1),new a('ÑŒ',-1,3)]});f(b,'g_v',function(){return[33,65,8,232]});var o={'src/stemmer.jsx':{Stemmer:m},'src/russian-stemmer.jsx':{RussianStemmer:b}}}(JSX))
+var Stemmer = JSX.require("src/russian-stemmer.jsx").RussianStemmer;
+"""
+
+
+class SearchRussian(SearchLanguage):
+ lang = 'ru'
+ language_name = 'Russian'
+ js_stemmer_code = js_stemmer
+ stopwords = russian_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('russian')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/sv.py b/sphinx/search/sv.py
new file mode 100644
index 00000000..eb4ab2ee
--- /dev/null
+++ b/sphinx/search/sv.py
@@ -0,0 +1,150 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.sv
+ ~~~~~~~~~~~~~~~~
+
+ Swedish search language: includes the JS Swedish stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage, parse_stop_word
+
+import snowballstemmer
+
+swedish_stopwords = parse_stop_word(u'''
+| source: http://snowball.tartarus.org/algorithms/swedish/stop.txt
+och | and
+det | it, this/that
+att | to (with infinitive)
+i | in, at
+en | a
+jag | I
+hon | she
+som | who, that
+han | he
+på | on
+den | it, this/that
+med | with
+var | where, each
+sig | him(self) etc
+för | for
+så | so (also: seed)
+till | to
+är | is
+men | but
+ett | a
+om | if; around, about
+hade | had
+de | they, these/those
+av | of
+icke | not, no
+mig | me
+du | you
+henne | her
+då | then, when
+sin | his
+nu | now
+har | have
+inte | inte någon = no one
+hans | his
+honom | him
+skulle | 'sake'
+hennes | her
+där | there
+min | my
+man | one (pronoun)
+ej | nor
+vid | at, by, on (also: vast)
+kunde | could
+något | some etc
+från | from, off
+ut | out
+när | when
+efter | after, behind
+upp | up
+vi | we
+dem | them
+vara | be
+vad | what
+över | over
+än | than
+dig | you
+kan | can
+sina | his
+här | here
+ha | have
+mot | towards
+alla | all
+under | under (also: wonder)
+någon | some etc
+eller | or (else)
+allt | all
+mycket | much
+sedan | since
+ju | why
+denna | this/that
+själv | myself, yourself etc
+detta | this/that
+Ã¥t | to
+utan | without
+varit | was
+hur | how
+ingen | no
+mitt | my
+ni | you
+bli | to be, become
+blev | from bli
+oss | us
+din | thy
+dessa | these/those
+några | some etc
+deras | their
+blir | from bli
+mina | my
+samma | (the) same
+vilken | who, that
+er | you, your
+sådan | such a
+vår | our
+blivit | from bli
+dess | its
+inom | within
+mellan | between
+sådant | such a
+varför | why
+varje | each
+vilka | who, that
+ditt | thy
+vem | who
+vilket | who, that
+sitta | his
+sådana | such a
+vart | each
+dina | thy
+vars | whose
+vårt | our
+våra | our
+ert | your
+era | your
+vilkas | whose
+''')
+
+js_stemmer = u"""
+var JSX={};(function(e){function i(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function G(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function h(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function F(a,b,c){return a[b]=a[b]/c|0}var t=parseInt;var u=parseFloat;function E(a){return a!==a}var x=isFinite;var y=encodeURIComponent;var z=decodeURIComponent;var B=encodeURI;var C=decodeURI;var o=Object.prototype.toString;var p=Object.prototype.hasOwnProperty;function f(){}e.require=function(b){var a=n[b];return a!==undefined?a:null};e.profilerIsRunning=function(){return f.getResults!=null};e.getProfileResults=function(){return(f.getResults||function(){return{}})()};e.postProfileResults=function(a,b){if(f.postResults==null)throw new Error('profiler has not been turned on');return f.postResults(a,b)};e.resetProfileResults=function(){if(f.resetResults==null)throw new Error('profiler has not been turned on');return f.resetResults()};e.DEBUG=false;function r(){};i([r],Error);function a(a,b,c){this.G=a.length;this.R=a;this.U=b;this.J=c;this.I=null;this.V=null};i([a],Object);function j(){};i([j],Object);function d(){var a;var b;var c;this.F={};a=this.C='';b=this._=0;c=this.B=a.length;this.A=0;this.D=b;this.E=c};i([d],j);function v(a,b){a.C=b.C;a._=b._;a.B=b.B;a.A=b.A;a.D=b.D;a.E=b.E};function k(b,d,c,e){var a;if(b._>=b.B){return false}a=b.C.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function l(b,d,c,e){var a;if(b._<=b.A){return false}a=b.C.charCodeAt(b._-1);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._--;return true};function m(a,d,c,e){var b;if(a._>=a.B){return false}b=a.C.charCodeAt(a._);if(b>e||b<c){a._++;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._++;return true}return false};function g(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.A;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.G-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.C.charCodeAt(e-1-c)-a.R.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.G){d._=e-a.G|0;if(a.I==null){return a.J}o=a.I(d);d._=e-a.G|0;if(o){return a.J}}b=a.U;if(b<0){return 0}}return-1};function A(a,b,d,e){var c;c=e.length-(d-b);a.C=a.C.slice(0,b)+e+a.C.slice(d);a.B+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function c(a,f){var b;var c;var d;var e;b=false;if((c=a.D)<0||c>(d=a.E)||d>(e=a.B)||e>a.C.length?false:true){A(a,a.D,a.E,f);b=true}return b};d.prototype.H=function(){return false};d.prototype.S=function(b){var a;var c;var d;var e;a=this.F['.'+b];if(a==null){c=this.C=b;d=this._=0;e=this.B=c.length;this.A=0;this.D=d;this.E=e;this.H();a=this.C;this.F['.'+b]=a}return a};d.prototype.stemWord=d.prototype.S;d.prototype.T=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.F['.'+c];if(a==null){f=this.C=c;g=this._=0;h=this.B=f.length;this.A=0;this.D=g;this.E=h;this.H();a=this.C;this.F['.'+c]=a}d.push(a)}return d};d.prototype.stemWords=d.prototype.T;function b(){d.call(this);this.I_x=0;this.I_p1=0};i([b],d);b.prototype.K=function(a){this.I_x=a.I_x;this.I_p1=a.I_p1;v(this,a)};b.prototype.copy_from=b.prototype.K;b.prototype.P=function(){var g;var d;var a;var e;var c;var f;var i;var j;var l;var h;this.I_p1=j=this.B;g=i=this._;a=i+3|0;if(0>a||a>j){return false}h=this._=a;this.I_x=h;this._=g;a:while(true){d=this._;e=true;b:while(e===true){e=false;if(!k(this,b.g_v,97,246)){break b}this._=d;break a}l=this._=d;if(l>=this.B){return false}this._++}a:while(true){c=true;b:while(c===true){c=false;if(!m(this,b.g_v,97,246)){break b}break a}if(this._>=this.B){return false}this._++}this.I_p1=this._;f=true;a:while(f===true){f=false;if(!(this.I_p1<this.I_x)){break a}this.I_p1=this.I_x}return true};b.prototype.r_mark_regions=b.prototype.P;function D(a){var h;var e;var c;var f;var d;var g;var j;var l;var n;var i;a.I_p1=l=a.B;h=j=a._;c=j+3|0;if(0>c||c>l){return false}i=a._=c;a.I_x=i;a._=h;a:while(true){e=a._;f=true;b:while(f===true){f=false;if(!k(a,b.g_v,97,246)){break b}a._=e;break a}n=a._=e;if(n>=a.B){return false}a._++}a:while(true){d=true;b:while(d===true){d=false;if(!m(a,b.g_v,97,246)){break b}break a}if(a._>=a.B){return false}a._++}a.I_p1=a._;g=true;a:while(g===true){g=false;if(!(a.I_p1<a.I_x)){break a}a.I_p1=a.I_x}return true};b.prototype.O=function(){var a;var e;var d;var f;var h;var i;e=this.B-(f=this._);if(f<this.I_p1){return false}h=this._=this.I_p1;d=this.A;this.A=h;i=this._=this.B-e;this.E=i;a=g(this,b.a_0,37);if(a===0){this.A=d;return false}this.D=this._;this.A=d;switch(a){case 0:return false;case 1:if(!c(this,'')){return false}break;case 2:if(!l(this,b.g_s_ending,98,121)){return false}if(!c(this,'')){return false}break}return true};b.prototype.r_main_suffix=b.prototype.O;function w(a){var d;var f;var e;var h;var i;var j;f=a.B-(h=a._);if(h<a.I_p1){return false}i=a._=a.I_p1;e=a.A;a.A=i;j=a._=a.B-f;a.E=j;d=g(a,b.a_0,37);if(d===0){a.A=e;return false}a.D=a._;a.A=e;switch(d){case 0:return false;case 1:if(!c(a,'')){return false}break;case 2:if(!l(a,b.g_s_ending,98,121)){return false}if(!c(a,'')){return false}break}return true};b.prototype.N=function(){var e;var a;var f;var h;var i;var j;var k;var d;e=this.B-(h=this._);if(h<this.I_p1){return false}i=this._=this.I_p1;a=this.A;this.A=i;k=this._=(j=this.B)-e;f=j-k;if(g(this,b.a_1,7)===0){this.A=a;return false}d=this._=this.B-f;this.E=d;if(d<=this.A){this.A=a;return false}this._--;this.D=this._;if(!c(this,'')){return false}this.A=a;return true};b.prototype.r_consonant_pair=b.prototype.N;function s(a){var f;var d;var h;var i;var j;var k;var l;var e;f=a.B-(i=a._);if(i<a.I_p1){return false}j=a._=a.I_p1;d=a.A;a.A=j;l=a._=(k=a.B)-f;h=k-l;if(g(a,b.a_1,7)===0){a.A=d;return false}e=a._=a.B-h;a.E=e;if(e<=a.A){a.A=d;return false}a._--;a.D=a._;if(!c(a,'')){return false}a.A=d;return true};b.prototype.Q=function(){var d;var e;var a;var f;var h;var i;e=this.B-(f=this._);if(f<this.I_p1){return false}h=this._=this.I_p1;a=this.A;this.A=h;i=this._=this.B-e;this.E=i;d=g(this,b.a_2,5);if(d===0){this.A=a;return false}this.D=this._;switch(d){case 0:this.A=a;return false;case 1:if(!c(this,'')){return false}break;case 2:if(!c(this,'lös')){return false}break;case 3:if(!c(this,'full')){return false}break}this.A=a;return true};b.prototype.r_other_suffix=b.prototype.Q;function q(a){var e;var f;var d;var h;var i;var j;f=a.B-(h=a._);if(h<a.I_p1){return false}i=a._=a.I_p1;d=a.A;a.A=i;j=a._=a.B-f;a.E=j;e=g(a,b.a_2,5);if(e===0){a.A=d;return false}a.D=a._;switch(e){case 0:a.A=d;return false;case 1:if(!c(a,'')){return false}break;case 2:if(!c(a,'lös')){return false}break;case 3:if(!c(a,'full')){return false}break}a.A=d;return true};b.prototype.H=function(){var g;var f;var h;var b;var c;var a;var d;var i;var j;var k;var l;var e;g=this._;b=true;a:while(b===true){b=false;if(!D(this)){break a}}i=this._=g;this.A=i;k=this._=j=this.B;f=j-k;c=true;a:while(c===true){c=false;if(!w(this)){break a}}e=this._=(l=this.B)-f;h=l-e;a=true;a:while(a===true){a=false;if(!s(this)){break a}}this._=this.B-h;d=true;a:while(d===true){d=false;if(!q(this)){break a}}this._=this.A;return true};b.prototype.stem=b.prototype.H;b.prototype.L=function(a){return a instanceof b};b.prototype.equals=b.prototype.L;b.prototype.M=function(){var c;var a;var b;var d;c='SwedishStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};b.prototype.hashCode=b.prototype.M;b.serialVersionUID=1;h(b,'methodObject',function(){return new b});h(b,'a_0',function(){return[new a('a',-1,1),new a('arna',0,1),new a('erna',0,1),new a('heterna',2,1),new a('orna',0,1),new a('ad',-1,1),new a('e',-1,1),new a('ade',6,1),new a('ande',6,1),new a('arne',6,1),new a('are',6,1),new a('aste',6,1),new a('en',-1,1),new a('anden',12,1),new a('aren',12,1),new a('heten',12,1),new a('ern',-1,1),new a('ar',-1,1),new a('er',-1,1),new a('heter',18,1),new a('or',-1,1),new a('s',-1,2),new a('as',21,1),new a('arnas',22,1),new a('ernas',22,1),new a('ornas',22,1),new a('es',21,1),new a('ades',26,1),new a('andes',26,1),new a('ens',21,1),new a('arens',29,1),new a('hetens',29,1),new a('erns',21,1),new a('at',-1,1),new a('andet',-1,1),new a('het',-1,1),new a('ast',-1,1)]});h(b,'a_1',function(){return[new a('dd',-1,-1),new a('gd',-1,-1),new a('nn',-1,-1),new a('dt',-1,-1),new a('gt',-1,-1),new a('kt',-1,-1),new a('tt',-1,-1)]});h(b,'a_2',function(){return[new a('ig',-1,1),new a('lig',0,1),new a('els',-1,1),new a('fullt',-1,3),new a('löst',-1,2)]});h(b,'g_v',function(){return[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32]});h(b,'g_s_ending',function(){return[119,127,149]});var n={'src/stemmer.jsx':{Stemmer:j},'src/swedish-stemmer.jsx':{SwedishStemmer:b}}}(JSX))
+var Stemmer = JSX.require("src/swedish-stemmer.jsx").SwedishStemmer;
+"""
+
+
+class SearchSwedish(SearchLanguage):
+ lang = 'sv'
+ language_name = 'Swedish'
+ js_stemmer_code = js_stemmer
+ stopwords = swedish_stopwords
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('swedish')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/search/tr.py b/sphinx/search/tr.py
new file mode 100644
index 00000000..52c5bb2a
--- /dev/null
+++ b/sphinx/search/tr.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.search.tr
+ ~~~~~~~~~~~~~~~~
+
+ Turkish search language: includes the JS Turkish stemmer.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.search import SearchLanguage
+
+import snowballstemmer
+
+js_stemmer = u"""
+var JSX={};(function(q){function r(b,e){var a=function(){};a.prototype=e.prototype;var c=new a;for(var d in b){b[d].prototype=c}}function Q(c,b){for(var a in b.prototype)if(b.prototype.hasOwnProperty(a))c.prototype[a]=b.prototype[a]}function j(a,b,d){function c(a,b,c){delete a[b];a[b]=c;return c}Object.defineProperty(a,b,{get:function(){return c(a,b,d())},set:function(d){c(a,b,d)},enumerable:true,configurable:true})}function R(a,b,c){return a[b]=a[b]/c|0}var M=parseInt;var K=parseFloat;function P(a){return a!==a}var A=isFinite;var G=encodeURIComponent;var F=decodeURIComponent;var E=encodeURI;var D=decodeURI;var C=Object.prototype.toString;var H=Object.prototype.hasOwnProperty;function p(){}q.require=function(b){var a=y[b];return a!==undefined?a:null};q.profilerIsRunning=function(){return p.getResults!=null};q.getProfileResults=function(){return(p.getResults||function(){return{}})()};q.postProfileResults=function(a,b){if(p.postResults==null)throw new Error('profiler has not been turned on');return p.postResults(a,b)};q.resetProfileResults=function(){if(p.resetResults==null)throw new Error('profiler has not been turned on');return p.resetResults()};q.DEBUG=false;function I(){};r([I],Error);function d(a,b,c){this.G=a.length;this.A_=a;this.D_=b;this.J=c;this.I=null;this.E_=null};r([d],Object);function u(){};r([u],Object);function m(){var a;var b;var c;this.F={};a=this.E='';b=this._=0;c=this.A=a.length;this.D=0;this.B=b;this.C=c};r([m],u);function B(a,b){a.E=b.E;a._=b._;a.A=b.A;a.D=b.D;a.B=b.B;a.C=b.C};function v(b,d,c,e){var a;if(b._>=b.A){return false}a=b.E.charCodeAt(b._);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._++;return true};function f(b,d,c,e){var a;if(b._<=b.D){return false}a=b.E.charCodeAt(b._-1);if(a>e||a<c){return false}a-=c;if((d[a>>>3]&1<<(a&7))===0){return false}b._--;return true};function t(a,d,c,e){var b;if(a._<=a.D){return false}b=a.E.charCodeAt(a._-1);if(b>e||b<c){a._--;return true}b-=c;if((d[b>>>3]&1<<(b&7))===0){a._--;return true}return false};function s(a,b,d){var c;if(a.A-a._<b){return false}if(a.E.slice(c=a._,c+b)!==d){return false}a._+=b;return true};function g(a,b,d){var c;if(a._-a.D<b){return false}if(a.E.slice((c=a._)-b,c)!==d){return false}a._-=b;return true};function b(d,m,p){var b;var g;var e;var n;var f;var k;var l;var i;var h;var c;var a;var j;var o;b=0;g=p;e=d._;n=d.D;f=0;k=0;l=false;while(true){i=b+(g-b>>1);h=0;c=f<k?f:k;a=m[i];for(j=a.G-1-c;j>=0;j--){if(e-c===n){h=-1;break}h=d.E.charCodeAt(e-1-c)-a.A_.charCodeAt(j);if(h!==0){break}c++}if(h<0){g=i;k=c}else{b=i;f=c}if(g-b<=1){if(b>0){break}if(g===b){break}if(l){break}l=true}}while(true){a=m[b];if(f>=a.G){d._=e-a.G|0;if(a.I==null){return a.J}o=a.I(d);d._=e-a.G|0;if(o){return a.J}}b=a.D_;if(b<0){return 0}}return-1};function n(a,b,d,e){var c;c=e.length-(d-b);a.E=a.E.slice(0,b)+e+a.E.slice(d);a.A+=c|0;if(a._>=d){a._+=c|0}else if(a._>b){a._=b}return c|0};function e(a,f){var b;var c;var d;var e;b=false;if((c=a.B)<0||c>(d=a.C)||d>(e=a.A)||e>a.E.length?false:true){n(a,a.B,a.C,f);b=true}return b};m.prototype.H=function(){return false};m.prototype.B_=function(b){var a;var c;var d;var e;a=this.F['.'+b];if(a==null){c=this.E=b;d=this._=0;e=this.A=c.length;this.D=0;this.B=d;this.C=e;this.H();a=this.E;this.F['.'+b]=a}return a};m.prototype.stemWord=m.prototype.B_;m.prototype.C_=function(e){var d;var b;var c;var a;var f;var g;var h;d=[];for(b=0;b<e.length;b++){c=e[b];a=this.F['.'+c];if(a==null){f=this.E=c;g=this._=0;h=this.A=f.length;this.D=0;this.B=g;this.C=h;this.H();a=this.E;this.F['.'+c]=a}d.push(a)}return d};m.prototype.stemWords=m.prototype.C_;function a(){m.call(this);this.B_continue_stemming_noun_suffixes=false;this.I_strlen=0};r([a],m);a.prototype.K=function(a){this.B_continue_stemming_noun_suffixes=a.B_continue_stemming_noun_suffixes;this.I_strlen=a.I_strlen;B(this,a)};a.prototype.copy_from=a.prototype.K;a.prototype.O=function(){var E;var q;var b;var e;var h;var i;var j;var k;var l;var m;var n;var o;var p;var c;var r;var s;var t;var u;var d;var v;var w;var x;var y;var z;var A;var B;var C;var D;var G;var H;var I;var J;var K;var L;var M;var N;var F;E=this.A-this._;b:while(true){q=this.A-this._;o=true;a:while(o===true){o=false;if(!f(this,a.g_vowel,97,305)){break a}this._=this.A-q;break b}G=this._=this.A-q;if(G<=this.D){return false}this._--}p=true;a:while(p===true){p=false;b=this.A-this._;c=true;b:while(c===true){c=false;if(!g(this,1,'a')){break b}c:while(true){e=this.A-this._;r=true;d:while(r===true){r=false;if(!f(this,a.g_vowel1,97,305)){break d}this._=this.A-e;break c}H=this._=this.A-e;if(H<=this.D){break b}this._--}break a}this._=this.A-b;s=true;b:while(s===true){s=false;if(!g(this,1,'e')){break b}c:while(true){h=this.A-this._;t=true;d:while(t===true){t=false;if(!f(this,a.g_vowel2,101,252)){break d}this._=this.A-h;break c}I=this._=this.A-h;if(I<=this.D){break b}this._--}break a}this._=this.A-b;u=true;b:while(u===true){u=false;if(!g(this,1,'ı')){break b}c:while(true){i=this.A-this._;d=true;d:while(d===true){d=false;if(!f(this,a.g_vowel3,97,305)){break d}this._=this.A-i;break c}J=this._=this.A-i;if(J<=this.D){break b}this._--}break a}this._=this.A-b;v=true;b:while(v===true){v=false;if(!g(this,1,'i')){break b}c:while(true){j=this.A-this._;w=true;d:while(w===true){w=false;if(!f(this,a.g_vowel4,101,105)){break d}this._=this.A-j;break c}K=this._=this.A-j;if(K<=this.D){break b}this._--}break a}this._=this.A-b;x=true;b:while(x===true){x=false;if(!g(this,1,'o')){break b}c:while(true){k=this.A-this._;y=true;d:while(y===true){y=false;if(!f(this,a.g_vowel5,111,117)){break d}this._=this.A-k;break c}L=this._=this.A-k;if(L<=this.D){break b}this._--}break a}this._=this.A-b;z=true;b:while(z===true){z=false;if(!g(this,1,'ö')){break b}c:while(true){l=this.A-this._;A=true;d:while(A===true){A=false;if(!f(this,a.g_vowel6,246,252)){break d}this._=this.A-l;break c}M=this._=this.A-l;if(M<=this.D){break b}this._--}break a}this._=this.A-b;B=true;b:while(B===true){B=false;if(!g(this,1,'u')){break b}c:while(true){m=this.A-this._;C=true;d:while(C===true){C=false;if(!f(this,a.g_vowel5,111,117)){break d}this._=this.A-m;break c}N=this._=this.A-m;if(N<=this.D){break b}this._--}break a}this._=this.A-b;if(!g(this,1,'ü')){return false}b:while(true){n=this.A-this._;D=true;c:while(D===true){D=false;if(!f(this,a.g_vowel6,246,252)){break c}this._=this.A-n;break b}F=this._=this.A-n;if(F<=this.D){return false}this._--}}this._=this.A-E;return true};a.prototype.r_check_vowel_harmony=a.prototype.O;function c(b){var F;var r;var c;var e;var h;var i;var j;var k;var l;var m;var n;var o;var p;var q;var d;var s;var t;var u;var v;var w;var x;var y;var z;var A;var B;var C;var D;var E;var H;var I;var J;var K;var L;var M;var N;var O;var G;F=b.A-b._;b:while(true){r=b.A-b._;o=true;a:while(o===true){o=false;if(!f(b,a.g_vowel,97,305)){break a}b._=b.A-r;break b}H=b._=b.A-r;if(H<=b.D){return false}b._--}p=true;a:while(p===true){p=false;c=b.A-b._;q=true;b:while(q===true){q=false;if(!g(b,1,'a')){break b}c:while(true){e=b.A-b._;d=true;d:while(d===true){d=false;if(!f(b,a.g_vowel1,97,305)){break d}b._=b.A-e;break c}I=b._=b.A-e;if(I<=b.D){break b}b._--}break a}b._=b.A-c;s=true;b:while(s===true){s=false;if(!g(b,1,'e')){break b}c:while(true){h=b.A-b._;t=true;d:while(t===true){t=false;if(!f(b,a.g_vowel2,101,252)){break d}b._=b.A-h;break c}J=b._=b.A-h;if(J<=b.D){break b}b._--}break a}b._=b.A-c;u=true;b:while(u===true){u=false;if(!g(b,1,'ı')){break b}c:while(true){i=b.A-b._;v=true;d:while(v===true){v=false;if(!f(b,a.g_vowel3,97,305)){break d}b._=b.A-i;break c}K=b._=b.A-i;if(K<=b.D){break b}b._--}break a}b._=b.A-c;w=true;b:while(w===true){w=false;if(!g(b,1,'i')){break b}c:while(true){j=b.A-b._;x=true;d:while(x===true){x=false;if(!f(b,a.g_vowel4,101,105)){break d}b._=b.A-j;break c}L=b._=b.A-j;if(L<=b.D){break b}b._--}break a}b._=b.A-c;y=true;b:while(y===true){y=false;if(!g(b,1,'o')){break b}c:while(true){k=b.A-b._;z=true;d:while(z===true){z=false;if(!f(b,a.g_vowel5,111,117)){break d}b._=b.A-k;break c}M=b._=b.A-k;if(M<=b.D){break b}b._--}break a}b._=b.A-c;A=true;b:while(A===true){A=false;if(!g(b,1,'ö')){break b}c:while(true){l=b.A-b._;B=true;d:while(B===true){B=false;if(!f(b,a.g_vowel6,246,252)){break d}b._=b.A-l;break c}N=b._=b.A-l;if(N<=b.D){break b}b._--}break a}b._=b.A-c;C=true;b:while(C===true){C=false;if(!g(b,1,'u')){break b}c:while(true){m=b.A-b._;D=true;d:while(D===true){D=false;if(!f(b,a.g_vowel5,111,117)){break d}b._=b.A-m;break c}O=b._=b.A-m;if(O<=b.D){break b}b._--}break a}b._=b.A-c;if(!g(b,1,'ü')){return false}b:while(true){n=b.A-b._;E=true;c:while(E===true){E=false;if(!f(b,a.g_vowel6,246,252)){break c}b._=b.A-n;break b}G=b._=b.A-n;if(G<=b.D){return false}b._--}}b._=b.A-F;return true};a.prototype.j=function(){var k;var h;var l;var i;var m;var j;var b;var e;var d;var n;var o;var p;var q;var c;b=true;b:while(b===true){b=false;k=this.A-this._;e=true;a:while(e===true){e=false;h=this.A-this._;if(!g(this,1,'n')){break a}n=this._=this.A-h;if(n<=this.D){break a}this._--;l=this.A-this._;if(!f(this,a.g_vowel,97,305)){break a}this._=this.A-l;break b}p=this._=(o=this.A)-k;i=o-p;d=true;a:while(d===true){d=false;m=this.A-this._;if(!g(this,1,'n')){break a}this._=this.A-m;return false}c=this._=(q=this.A)-i;j=q-c;if(c<=this.D){return false}this._--;if(!f(this,a.g_vowel,97,305)){return false}this._=this.A-j}return true};a.prototype.r_mark_suffix_with_optional_n_consonant=a.prototype.j;function o(b){var i;var m;var l;var j;var n;var k;var c;var e;var d;var o;var p;var q;var r;var h;c=true;b:while(c===true){c=false;i=b.A-b._;e=true;a:while(e===true){e=false;m=b.A-b._;if(!g(b,1,'n')){break a}o=b._=b.A-m;if(o<=b.D){break a}b._--;l=b.A-b._;if(!f(b,a.g_vowel,97,305)){break a}b._=b.A-l;break b}q=b._=(p=b.A)-i;j=p-q;d=true;a:while(d===true){d=false;n=b.A-b._;if(!g(b,1,'n')){break a}b._=b.A-n;return false}h=b._=(r=b.A)-j;k=r-h;if(h<=b.D){return false}b._--;if(!f(b,a.g_vowel,97,305)){return false}b._=b.A-k}return true};a.prototype.k=function(){var k;var h;var l;var i;var m;var j;var b;var e;var d;var n;var o;var p;var q;var c;b=true;b:while(b===true){b=false;k=this.A-this._;e=true;a:while(e===true){e=false;h=this.A-this._;if(!g(this,1,'s')){break a}n=this._=this.A-h;if(n<=this.D){break a}this._--;l=this.A-this._;if(!f(this,a.g_vowel,97,305)){break a}this._=this.A-l;break b}p=this._=(o=this.A)-k;i=o-p;d=true;a:while(d===true){d=false;m=this.A-this._;if(!g(this,1,'s')){break a}this._=this.A-m;return false}c=this._=(q=this.A)-i;j=q-c;if(c<=this.D){return false}this._--;if(!f(this,a.g_vowel,97,305)){return false}this._=this.A-j}return true};a.prototype.r_mark_suffix_with_optional_s_consonant=a.prototype.k;function l(b){var i;var m;var l;var j;var n;var k;var c;var e;var d;var o;var p;var q;var r;var h;c=true;b:while(c===true){c=false;i=b.A-b._;e=true;a:while(e===true){e=false;m=b.A-b._;if(!g(b,1,'s')){break a}o=b._=b.A-m;if(o<=b.D){break a}b._--;l=b.A-b._;if(!f(b,a.g_vowel,97,305)){break a}b._=b.A-l;break b}q=b._=(p=b.A)-i;j=p-q;d=true;a:while(d===true){d=false;n=b.A-b._;if(!g(b,1,'s')){break a}b._=b.A-n;return false}h=b._=(r=b.A)-j;k=r-h;if(h<=b.D){return false}b._--;if(!f(b,a.g_vowel,97,305)){return false}b._=b.A-k}return true};a.prototype.l=function(){var k;var h;var l;var i;var m;var j;var b;var e;var d;var n;var o;var p;var q;var c;b=true;b:while(b===true){b=false;k=this.A-this._;e=true;a:while(e===true){e=false;h=this.A-this._;if(!g(this,1,'y')){break a}n=this._=this.A-h;if(n<=this.D){break a}this._--;l=this.A-this._;if(!f(this,a.g_vowel,97,305)){break a}this._=this.A-l;break b}p=this._=(o=this.A)-k;i=o-p;d=true;a:while(d===true){d=false;m=this.A-this._;if(!g(this,1,'y')){break a}this._=this.A-m;return false}c=this._=(q=this.A)-i;j=q-c;if(c<=this.D){return false}this._--;if(!f(this,a.g_vowel,97,305)){return false}this._=this.A-j}return true};a.prototype.r_mark_suffix_with_optional_y_consonant=a.prototype.l;function h(b){var i;var m;var l;var j;var n;var k;var c;var e;var d;var o;var p;var q;var r;var h;c=true;b:while(c===true){c=false;i=b.A-b._;e=true;a:while(e===true){e=false;m=b.A-b._;if(!g(b,1,'y')){break a}o=b._=b.A-m;if(o<=b.D){break a}b._--;l=b.A-b._;if(!f(b,a.g_vowel,97,305)){break a}b._=b.A-l;break b}q=b._=(p=b.A)-i;j=p-q;d=true;a:while(d===true){d=false;n=b.A-b._;if(!g(b,1,'y')){break a}b._=b.A-n;return false}h=b._=(r=b.A)-j;k=r-h;if(h<=b.D){return false}b._--;if(!f(b,a.g_vowel,97,305)){return false}b._=b.A-k}return true};a.prototype.i=function(){var j;var g;var k;var h;var l;var i;var b;var e;var d;var m;var n;var o;var p;var c;b=true;b:while(b===true){b=false;j=this.A-this._;e=true;a:while(e===true){e=false;g=this.A-this._;if(!f(this,a.g_U,105,305)){break a}m=this._=this.A-g;if(m<=this.D){break a}this._--;k=this.A-this._;if(!t(this,a.g_vowel,97,305)){break a}this._=this.A-k;break b}o=this._=(n=this.A)-j;h=n-o;d=true;a:while(d===true){d=false;l=this.A-this._;if(!f(this,a.g_U,105,305)){break a}this._=this.A-l;return false}c=this._=(p=this.A)-h;i=p-c;if(c<=this.D){return false}this._--;if(!t(this,a.g_vowel,97,305)){return false}this._=this.A-i}return true};a.prototype.r_mark_suffix_with_optional_U_vowel=a.prototype.i;function k(b){var h;var l;var k;var i;var m;var j;var c;var e;var d;var n;var o;var p;var q;var g;c=true;b:while(c===true){c=false;h=b.A-b._;e=true;a:while(e===true){e=false;l=b.A-b._;if(!f(b,a.g_U,105,305)){break a}n=b._=b.A-l;if(n<=b.D){break a}b._--;k=b.A-b._;if(!t(b,a.g_vowel,97,305)){break a}b._=b.A-k;break b}p=b._=(o=b.A)-h;i=o-p;d=true;a:while(d===true){d=false;m=b.A-b._;if(!f(b,a.g_U,105,305)){break a}b._=b.A-m;return false}g=b._=(q=b.A)-i;j=q-g;if(g<=b.D){return false}b._--;if(!t(b,a.g_vowel,97,305)){return false}b._=b.A-j}return true};a.prototype.e=function(){return b(this,a.a_0,10)===0?false:!k(this)?false:true};a.prototype.r_mark_possessives=a.prototype.e;a.prototype.f=function(){return!c(this)?false:!f(this,a.g_U,105,305)?false:!l(this)?false:true};a.prototype.r_mark_sU=a.prototype.f;a.prototype.W=function(){return b(this,a.a_1,2)===0?false:true};a.prototype.r_mark_lArI=a.prototype.W;a.prototype.o=function(){return!c(this)?false:!f(this,a.g_U,105,305)?false:!h(this)?false:true};a.prototype.r_mark_yU=a.prototype.o;a.prototype.Y=function(){return!c(this)?false:b(this,a.a_2,4)===0?false:true};a.prototype.r_mark_nU=a.prototype.Y;a.prototype.Z=function(){return!c(this)?false:b(this,a.a_3,4)===0?false:!o(this)?false:true};a.prototype.r_mark_nUn=a.prototype.Z;a.prototype.m=function(){return!c(this)?false:b(this,a.a_4,2)===0?false:!h(this)?false:true};a.prototype.r_mark_yA=a.prototype.m;a.prototype.X=function(){return!c(this)?false:b(this,a.a_5,2)===0?false:true};a.prototype.r_mark_nA=a.prototype.X;a.prototype.Q=function(){return!c(this)?false:b(this,a.a_6,4)===0?false:true};a.prototype.r_mark_DA=a.prototype.Q;a.prototype.c=function(){return!c(this)?false:b(this,a.a_7,2)===0?false:true};a.prototype.r_mark_ndA=a.prototype.c;a.prototype.R=function(){return!c(this)?false:b(this,a.a_8,4)===0?false:true};a.prototype.r_mark_DAn=a.prototype.R;a.prototype.d=function(){return!c(this)?false:b(this,a.a_9,2)===0?false:true};a.prototype.r_mark_ndAn=a.prototype.d;a.prototype.s=function(){return!c(this)?false:b(this,a.a_10,2)===0?false:!h(this)?false:true};a.prototype.r_mark_ylA=a.prototype.s;a.prototype.U=function(){return!g(this,2,'ki')?false:true};a.prototype.r_mark_ki=a.prototype.U;a.prototype.b=function(){return!c(this)?false:b(this,a.a_11,2)===0?false:!o(this)?false:true};a.prototype.r_mark_ncA=a.prototype.b;a.prototype.p=function(){return!c(this)?false:b(this,a.a_12,4)===0?false:!h(this)?false:true};a.prototype.r_mark_yUm=a.prototype.p;a.prototype.g=function(){return!c(this)?false:b(this,a.a_13,4)===0?false:true};a.prototype.r_mark_sUn=a.prototype.g;a.prototype.q=function(){return!c(this)?false:b(this,a.a_14,4)===0?false:!h(this)?false:true};a.prototype.r_mark_yUz=a.prototype.q;a.prototype.h=function(){return b(this,a.a_15,4)===0?false:true};a.prototype.r_mark_sUnUz=a.prototype.h;a.prototype.V=function(){return!c(this)?false:b(this,a.a_16,2)===0?false:true};a.prototype.r_mark_lAr=a.prototype.V;a.prototype.a=function(){return!c(this)?false:b(this,a.a_17,4)===0?false:true};a.prototype.r_mark_nUz=a.prototype.a;a.prototype.S=function(){return!c(this)?false:b(this,a.a_18,8)===0?false:true};a.prototype.r_mark_DUr=a.prototype.S;a.prototype.T=function(){return b(this,a.a_19,2)===0?false:true};a.prototype.r_mark_cAsInA=a.prototype.T;a.prototype.n=function(){return!c(this)?false:b(this,a.a_20,32)===0?false:!h(this)?false:true};a.prototype.r_mark_yDU=a.prototype.n;a.prototype.u=function(){return b(this,a.a_21,8)===0?false:!h(this)?false:true};a.prototype.r_mark_ysA=a.prototype.u;a.prototype.t=function(){return!c(this)?false:b(this,a.a_22,4)===0?false:!h(this)?false:true};a.prototype.r_mark_ymUs_=a.prototype.t;a.prototype.r=function(){return!g(this,3,'ken')?false:!h(this)?false:true};a.prototype.r_mark_yken=a.prototype.r;a.prototype.y=function(){var i;var j;var d;var Y;var k;var X;var l;var W;var V;var f;var r;var s;var t;var u;var v;var w;var x;var y;var z;var A;var B;var C;var m;var E;var F;var G;var H;var I;var J;var K;var L;var M;var N;var O;var P;var Q;var R;var S;var T;var U;var p;var o;var D;var n;var q;this.C=this._;this.B_continue_stemming_noun_suffixes=true;r=true;a:while(r===true){r=false;i=this.A-this._;s=true;d:while(s===true){s=false;t=true;b:while(t===true){t=false;j=this.A-this._;u=true;c:while(u===true){u=false;if(!(!c(this)?false:b(this,a.a_22,4)===0?false:!h(this)?false:true)){break c}break b}this._=this.A-j;v=true;c:while(v===true){v=false;if(!(!c(this)?false:b(this,a.a_20,32)===0?false:!h(this)?false:true)){break c}break b}this._=this.A-j;w=true;c:while(w===true){w=false;if(!(b(this,a.a_21,8)===0?false:!h(this)?false:true)){break c}break b}this._=this.A-j;if(!(!g(this,3,'ken')?false:!h(this)?false:true)){break d}}break a}this._=this.A-i;x=true;c:while(x===true){x=false;if(!(b(this,a.a_19,2)===0?false:true)){break c}y=true;b:while(y===true){y=false;d=this.A-this._;z=true;d:while(z===true){z=false;if(!(b(this,a.a_15,4)===0?false:true)){break d}break b}this._=this.A-d;A=true;d:while(A===true){A=false;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){break d}break b}this._=this.A-d;B=true;d:while(B===true){B=false;if(!(!c(this)?false:b(this,a.a_12,4)===0?false:!h(this)?false:true)){break d}break b}this._=this.A-d;C=true;d:while(C===true){C=false;if(!(!c(this)?false:b(this,a.a_13,4)===0?false:true)){break d}break b}this._=this.A-d;m=true;d:while(m===true){m=false;if(!(!c(this)?false:b(this,a.a_14,4)===0?false:!h(this)?false:true)){break d}break b}this._=this.A-d}if(!(!c(this)?false:b(this,a.a_22,4)===0?false:!h(this)?false:true)){break c}break a}this._=this.A-i;E=true;c:while(E===true){E=false;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){break c}this.B=this._;if(!e(this,'')){return false}Y=this.A-this._;F=true;d:while(F===true){F=false;this.C=this._;G=true;b:while(G===true){G=false;k=this.A-this._;H=true;e:while(H===true){H=false;if(!(!c(this)?false:b(this,a.a_18,8)===0?false:true)){break e}break b}this._=this.A-k;I=true;e:while(I===true){I=false;if(!(!c(this)?false:b(this,a.a_20,32)===0?false:!h(this)?false:true)){break e}break b}this._=this.A-k;J=true;e:while(J===true){J=false;if(!(b(this,a.a_21,8)===0?false:!h(this)?false:true)){break e}break b}this._=this.A-k;if(!(!c(this)?false:b(this,a.a_22,4)===0?false:!h(this)?false:true)){this._=this.A-Y;break d}}}this.B_continue_stemming_noun_suffixes=false;break a}this._=this.A-i;K=true;b:while(K===true){K=false;if(!(!c(this)?false:b(this,a.a_17,4)===0?false:true)){break b}L=true;c:while(L===true){L=false;X=this.A-this._;M=true;d:while(M===true){M=false;if(!(!c(this)?false:b(this,a.a_20,32)===0?false:!h(this)?false:true)){break d}break c}this._=this.A-X;if(!(b(this,a.a_21,8)===0?false:!h(this)?false:true)){break b}}break a}this._=this.A-i;N=true;c:while(N===true){N=false;O=true;b:while(O===true){O=false;l=this.A-this._;P=true;d:while(P===true){P=false;if(!(b(this,a.a_15,4)===0?false:true)){break d}break b}this._=this.A-l;Q=true;d:while(Q===true){Q=false;if(!(!c(this)?false:b(this,a.a_14,4)===0?false:!h(this)?false:true)){break d}break b}this._=this.A-l;R=true;d:while(R===true){R=false;if(!(!c(this)?false:b(this,a.a_13,4)===0?false:true)){break d}break b}this._=this.A-l;if(!(!c(this)?false:b(this,a.a_12,4)===0?false:!h(this)?false:true)){break c}}this.B=this._;if(!e(this,'')){return false}W=this.A-this._;S=true;b:while(S===true){S=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_22,4)===0?false:!h(this)?false:true)){this._=this.A-W;break b}}break a}this._=this.A-i;if(!(!c(this)?false:b(this,a.a_18,8)===0?false:true)){return false}this.B=this._;if(!e(this,'')){return false}V=this.A-this._;T=true;d:while(T===true){T=false;this.C=this._;U=true;b:while(U===true){U=false;f=this.A-this._;p=true;c:while(p===true){p=false;if(!(b(this,a.a_15,4)===0?false:true)){break c}break b}this._=this.A-f;o=true;c:while(o===true){o=false;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){break c}break b}this._=this.A-f;D=true;c:while(D===true){D=false;if(!(!c(this)?false:b(this,a.a_12,4)===0?false:!h(this)?false:true)){break c}break b}this._=this.A-f;n=true;c:while(n===true){n=false;if(!(!c(this)?false:b(this,a.a_13,4)===0?false:true)){break c}break b}this._=this.A-f;q=true;c:while(q===true){q=false;if(!(!c(this)?false:b(this,a.a_14,4)===0?false:!h(this)?false:true)){break c}break b}this._=this.A-f}if(!(!c(this)?false:b(this,a.a_22,4)===0?false:!h(this)?false:true)){this._=this.A-V;break d}}}this.B=this._;return!e(this,'')?false:true};a.prototype.r_stem_nominal_verb_suffixes=a.prototype.y;function J(d){var f;var k;var i;var Z;var l;var Y;var m;var X;var W;var j;var s;var t;var u;var v;var w;var x;var y;var z;var A;var B;var C;var n;var E;var F;var G;var H;var I;var J;var K;var L;var M;var N;var O;var P;var Q;var R;var S;var T;var U;var V;var q;var p;var D;var o;var r;d.C=d._;d.B_continue_stemming_noun_suffixes=true;s=true;a:while(s===true){s=false;f=d.A-d._;t=true;d:while(t===true){t=false;u=true;b:while(u===true){u=false;k=d.A-d._;v=true;c:while(v===true){v=false;if(!(!c(d)?false:b(d,a.a_22,4)===0?false:!h(d)?false:true)){break c}break b}d._=d.A-k;w=true;c:while(w===true){w=false;if(!(!c(d)?false:b(d,a.a_20,32)===0?false:!h(d)?false:true)){break c}break b}d._=d.A-k;x=true;c:while(x===true){x=false;if(!(b(d,a.a_21,8)===0?false:!h(d)?false:true)){break c}break b}d._=d.A-k;if(!(!g(d,3,'ken')?false:!h(d)?false:true)){break d}}break a}d._=d.A-f;y=true;c:while(y===true){y=false;if(!(b(d,a.a_19,2)===0?false:true)){break c}z=true;b:while(z===true){z=false;i=d.A-d._;A=true;d:while(A===true){A=false;if(!(b(d,a.a_15,4)===0?false:true)){break d}break b}d._=d.A-i;B=true;d:while(B===true){B=false;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){break d}break b}d._=d.A-i;C=true;d:while(C===true){C=false;if(!(!c(d)?false:b(d,a.a_12,4)===0?false:!h(d)?false:true)){break d}break b}d._=d.A-i;n=true;d:while(n===true){n=false;if(!(!c(d)?false:b(d,a.a_13,4)===0?false:true)){break d}break b}d._=d.A-i;E=true;d:while(E===true){E=false;if(!(!c(d)?false:b(d,a.a_14,4)===0?false:!h(d)?false:true)){break d}break b}d._=d.A-i}if(!(!c(d)?false:b(d,a.a_22,4)===0?false:!h(d)?false:true)){break c}break a}d._=d.A-f;F=true;c:while(F===true){F=false;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){break c}d.B=d._;if(!e(d,'')){return false}Z=d.A-d._;G=true;d:while(G===true){G=false;d.C=d._;H=true;b:while(H===true){H=false;l=d.A-d._;I=true;e:while(I===true){I=false;if(!(!c(d)?false:b(d,a.a_18,8)===0?false:true)){break e}break b}d._=d.A-l;J=true;e:while(J===true){J=false;if(!(!c(d)?false:b(d,a.a_20,32)===0?false:!h(d)?false:true)){break e}break b}d._=d.A-l;K=true;e:while(K===true){K=false;if(!(b(d,a.a_21,8)===0?false:!h(d)?false:true)){break e}break b}d._=d.A-l;if(!(!c(d)?false:b(d,a.a_22,4)===0?false:!h(d)?false:true)){d._=d.A-Z;break d}}}d.B_continue_stemming_noun_suffixes=false;break a}d._=d.A-f;L=true;b:while(L===true){L=false;if(!(!c(d)?false:b(d,a.a_17,4)===0?false:true)){break b}M=true;c:while(M===true){M=false;Y=d.A-d._;N=true;d:while(N===true){N=false;if(!(!c(d)?false:b(d,a.a_20,32)===0?false:!h(d)?false:true)){break d}break c}d._=d.A-Y;if(!(b(d,a.a_21,8)===0?false:!h(d)?false:true)){break b}}break a}d._=d.A-f;O=true;c:while(O===true){O=false;P=true;b:while(P===true){P=false;m=d.A-d._;Q=true;d:while(Q===true){Q=false;if(!(b(d,a.a_15,4)===0?false:true)){break d}break b}d._=d.A-m;R=true;d:while(R===true){R=false;if(!(!c(d)?false:b(d,a.a_14,4)===0?false:!h(d)?false:true)){break d}break b}d._=d.A-m;S=true;d:while(S===true){S=false;if(!(!c(d)?false:b(d,a.a_13,4)===0?false:true)){break d}break b}d._=d.A-m;if(!(!c(d)?false:b(d,a.a_12,4)===0?false:!h(d)?false:true)){break c}}d.B=d._;if(!e(d,'')){return false}X=d.A-d._;T=true;b:while(T===true){T=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_22,4)===0?false:!h(d)?false:true)){d._=d.A-X;break b}}break a}d._=d.A-f;if(!(!c(d)?false:b(d,a.a_18,8)===0?false:true)){return false}d.B=d._;if(!e(d,'')){return false}W=d.A-d._;U=true;d:while(U===true){U=false;d.C=d._;V=true;b:while(V===true){V=false;j=d.A-d._;q=true;c:while(q===true){q=false;if(!(b(d,a.a_15,4)===0?false:true)){break c}break b}d._=d.A-j;p=true;c:while(p===true){p=false;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){break c}break b}d._=d.A-j;D=true;c:while(D===true){D=false;if(!(!c(d)?false:b(d,a.a_12,4)===0?false:!h(d)?false:true)){break c}break b}d._=d.A-j;o=true;c:while(o===true){o=false;if(!(!c(d)?false:b(d,a.a_13,4)===0?false:true)){break c}break b}d._=d.A-j;r=true;c:while(r===true){r=false;if(!(!c(d)?false:b(d,a.a_14,4)===0?false:!h(d)?false:true)){break c}break b}d._=d.A-j}if(!(!c(d)?false:b(d,a.a_22,4)===0?false:!h(d)?false:true)){d._=d.A-W;break d}}}d.B=d._;return!e(d,'')?false:true};a.prototype.__=function(){var z;var N;var M;var L;var p;var K;var r;var J;var t;var u;var v;var w;var x;var y;var d;var A;var B;var C;var D;var E;var F;var G;var H;var I;var s;var q;var n;var m;var j;var h;this.C=this._;if(!(!g(this,2,'ki')?false:true)){return false}w=true;b:while(w===true){w=false;z=this.A-this._;x=true;c:while(x===true){x=false;if(!(!c(this)?false:b(this,a.a_6,4)===0?false:true)){break c}this.B=this._;if(!e(this,'')){return false}N=this.A-this._;y=true;f:while(y===true){y=false;this.C=this._;d=true;e:while(d===true){d=false;M=this.A-this._;A=true;d:while(A===true){A=false;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){break d}this.B=this._;if(!e(this,'')){return false}L=this.A-this._;B=true;a:while(B===true){B=false;if(!i(this)){this._=this.A-L;break a}}break e}this._=this.A-M;if(!(b(this,a.a_0,10)===0?false:!k(this)?false:true)){this._=this.A-N;break f}this.B=this._;if(!e(this,'')){return false}p=this.A-this._;C=true;a:while(C===true){C=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-p;break a}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-p;break a}}}}break b}this._=this.A-z;D=true;d:while(D===true){D=false;if(!(!c(this)?false:b(this,a.a_3,4)===0?false:!o(this)?false:true)){break d}this.B=this._;if(!e(this,'')){return false}K=this.A-this._;E=true;e:while(E===true){E=false;this.C=this._;F=true;a:while(F===true){F=false;r=this.A-this._;G=true;c:while(G===true){G=false;if(!(b(this,a.a_1,2)===0?false:true)){break c}this.B=this._;if(!e(this,'')){return false}break a}this._=this.A-r;H=true;f:while(H===true){H=false;this.C=this._;I=true;g:while(I===true){I=false;J=this.A-this._;s=true;c:while(s===true){s=false;if(!(b(this,a.a_0,10)===0?false:!k(this)?false:true)){break c}break g}this._=this.A-J;if(!(!c(this)?false:!f(this,a.g_U,105,305)?false:!l(this)?false:true)){break f}}this.B=this._;if(!e(this,'')){return false}t=this.A-this._;q=true;c:while(q===true){q=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-t;break c}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-t;break c}}break a}this._=this.A-r;if(!i(this)){this._=this.A-K;break e}}}break b}this._=this.A-z;if(!(!c(this)?false:b(this,a.a_7,2)===0?false:true)){return false}n=true;a:while(n===true){n=false;u=this.A-this._;m=true;c:while(m===true){m=false;if(!(b(this,a.a_1,2)===0?false:true)){break c}this.B=this._;if(!e(this,'')){return false}break a}this._=this.A-u;j=true;d:while(j===true){j=false;if(!(!c(this)?false:!f(this,a.g_U,105,305)?false:!l(this)?false:true)){break d}this.B=this._;if(!e(this,'')){return false}v=this.A-this._;h=true;c:while(h===true){h=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-v;break c}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-v;break c}}break a}this._=this.A-u;if(!i(this)){return false}}}return true};a.prototype.r_stem_suffix_chain_before_ki=a.prototype.__;function i(d){var j;var O;var N;var M;var q;var L;var s;var K;var u;var v;var w;var x;var y;var z;var h;var B;var C;var D;var E;var F;var G;var H;var I;var J;var t;var r;var p;var n;var m;var A;d.C=d._;if(!(!g(d,2,'ki')?false:true)){return false}x=true;b:while(x===true){x=false;j=d.A-d._;y=true;c:while(y===true){y=false;if(!(!c(d)?false:b(d,a.a_6,4)===0?false:true)){break c}d.B=d._;if(!e(d,'')){return false}O=d.A-d._;z=true;f:while(z===true){z=false;d.C=d._;h=true;e:while(h===true){h=false;N=d.A-d._;B=true;d:while(B===true){B=false;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){break d}d.B=d._;if(!e(d,'')){return false}M=d.A-d._;C=true;a:while(C===true){C=false;if(!i(d)){d._=d.A-M;break a}}break e}d._=d.A-N;if(!(b(d,a.a_0,10)===0?false:!k(d)?false:true)){d._=d.A-O;break f}d.B=d._;if(!e(d,'')){return false}q=d.A-d._;D=true;a:while(D===true){D=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-q;break a}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-q;break a}}}}break b}d._=d.A-j;E=true;d:while(E===true){E=false;if(!(!c(d)?false:b(d,a.a_3,4)===0?false:!o(d)?false:true)){break d}d.B=d._;if(!e(d,'')){return false}L=d.A-d._;F=true;e:while(F===true){F=false;d.C=d._;G=true;a:while(G===true){G=false;s=d.A-d._;H=true;c:while(H===true){H=false;if(!(b(d,a.a_1,2)===0?false:true)){break c}d.B=d._;if(!e(d,'')){return false}break a}d._=d.A-s;I=true;f:while(I===true){I=false;d.C=d._;J=true;g:while(J===true){J=false;K=d.A-d._;t=true;c:while(t===true){t=false;if(!(b(d,a.a_0,10)===0?false:!k(d)?false:true)){break c}break g}d._=d.A-K;if(!(!c(d)?false:!f(d,a.g_U,105,305)?false:!l(d)?false:true)){break f}}d.B=d._;if(!e(d,'')){return false}u=d.A-d._;r=true;c:while(r===true){r=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-u;break c}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-u;break c}}break a}d._=d.A-s;if(!i(d)){d._=d.A-L;break e}}}break b}d._=d.A-j;if(!(!c(d)?false:b(d,a.a_7,2)===0?false:true)){return false}p=true;a:while(p===true){p=false;v=d.A-d._;n=true;c:while(n===true){n=false;if(!(b(d,a.a_1,2)===0?false:true)){break c}d.B=d._;if(!e(d,'')){return false}break a}d._=d.A-v;m=true;d:while(m===true){m=false;if(!(!c(d)?false:!f(d,a.g_U,105,305)?false:!l(d)?false:true)){break d}d.B=d._;if(!e(d,'')){return false}w=d.A-d._;A=true;c:while(A===true){A=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-w;break c}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-w;break c}}break a}d._=d.A-v;if(!i(d)){return false}}}return true};a.prototype.z=function(){var d;var ar;var S;var j;var av;var m;var aq;var n;var p;var ax;var ay;var q;var ap;var r;var s;var as;var at;var au;var t;var aw;var u;var v;var w;var aA;var aB;var ao;var x;var y;var z;var A;var B;var C;var D;var E;var F;var G;var H;var I;var J;var K;var L;var M;var N;var O;var P;var Q;var R;var g;var T;var U;var V;var W;var X;var Y;var Z;var _;var $;var a0;var a1;var a2;var a3;var a4;var a5;var a6;var a7;var a8;var a9;var aa;var ab;var ac;var ad;var ae;var af;var ag;var ah;var ai;var aj;var ak;var al;var am;var an;var aC;var az;y=true;a:while(y===true){y=false;d=this.A-this._;z=true;b:while(z===true){z=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){break b}this.B=this._;if(!e(this,'')){return false}ar=this.A-this._;A=true;c:while(A===true){A=false;if(!i(this)){this._=this.A-ar;break c}}break a}this._=this.A-d;B=true;g:while(B===true){B=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_11,2)===0?false:!o(this)?false:true)){break g}this.B=this._;if(!e(this,'')){return false}S=this.A-this._;C=true;b:while(C===true){C=false;D=true;c:while(D===true){D=false;j=this.A-this._;E=true;d:while(E===true){E=false;this.C=this._;if(!(b(this,a.a_1,2)===0?false:true)){break d}this.B=this._;if(!e(this,'')){return false}break c}this._=this.A-j;F=true;f:while(F===true){F=false;this.C=this._;G=true;d:while(G===true){G=false;av=this.A-this._;H=true;e:while(H===true){H=false;if(!(b(this,a.a_0,10)===0?false:!k(this)?false:true)){break e}break d}this._=this.A-av;if(!(!c(this)?false:!f(this,a.g_U,105,305)?false:!l(this)?false:true)){break f}}this.B=this._;if(!e(this,'')){return false}m=this.A-this._;I=true;d:while(I===true){I=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-m;break d}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-m;break d}}break c}aC=this._=this.A-j;this.C=aC;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-S;break b}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-S;break b}}}break a}this._=this.A-d;J=true;b:while(J===true){J=false;this.C=this._;K=true;d:while(K===true){K=false;aq=this.A-this._;L=true;c:while(L===true){L=false;if(!(!c(this)?false:b(this,a.a_7,2)===0?false:true)){break c}break d}this._=this.A-aq;if(!(!c(this)?false:b(this,a.a_5,2)===0?false:true)){break b}}M=true;c:while(M===true){M=false;n=this.A-this._;N=true;d:while(N===true){N=false;if(!(b(this,a.a_1,2)===0?false:true)){break d}this.B=this._;if(!e(this,'')){return false}break c}this._=this.A-n;O=true;e:while(O===true){O=false;if(!(!c(this)?false:!f(this,a.g_U,105,305)?false:!l(this)?false:true)){break e}this.B=this._;if(!e(this,'')){return false}p=this.A-this._;P=true;d:while(P===true){P=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-p;break d}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-p;break d}}break c}this._=this.A-n;if(!i(this)){break b}}break a}this._=this.A-d;Q=true;c:while(Q===true){Q=false;this.C=this._;R=true;b:while(R===true){R=false;ax=this.A-this._;g=true;d:while(g===true){g=false;if(!(!c(this)?false:b(this,a.a_9,2)===0?false:true)){break d}break b}this._=this.A-ax;if(!(!c(this)?false:b(this,a.a_2,4)===0?false:true)){break c}}T=true;d:while(T===true){T=false;ay=this.A-this._;U=true;e:while(U===true){U=false;if(!(!c(this)?false:!f(this,a.g_U,105,305)?false:!l(this)?false:true)){break e}this.B=this._;if(!e(this,'')){return false}q=this.A-this._;V=true;b:while(V===true){V=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-q;break b}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-q;break b}}break d}this._=this.A-ay;if(!(b(this,a.a_1,2)===0?false:true)){break c}}break a}this._=this.A-d;W=true;d:while(W===true){W=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_8,4)===0?false:true)){break d}this.B=this._;if(!e(this,'')){return false}ap=this.A-this._;X=true;e:while(X===true){X=false;this.C=this._;Y=true;c:while(Y===true){Y=false;r=this.A-this._;Z=true;f:while(Z===true){Z=false;if(!(b(this,a.a_0,10)===0?false:!k(this)?false:true)){break f}this.B=this._;if(!e(this,'')){return false}s=this.A-this._;_=true;b:while(_===true){_=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-s;break b}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-s;break b}}break c}this._=this.A-r;$=true;b:while($===true){$=false;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){break b}this.B=this._;if(!e(this,'')){return false}as=this.A-this._;a0=true;f:while(a0===true){a0=false;if(!i(this)){this._=this.A-as;break f}}break c}this._=this.A-r;if(!i(this)){this._=this.A-ap;break e}}}break a}this._=this.A-d;a1=true;d:while(a1===true){a1=false;this.C=this._;a2=true;b:while(a2===true){a2=false;at=this.A-this._;a3=true;c:while(a3===true){a3=false;if(!(!c(this)?false:b(this,a.a_3,4)===0?false:!o(this)?false:true)){break c}break b}this._=this.A-at;if(!(!c(this)?false:b(this,a.a_10,2)===0?false:!h(this)?false:true)){break d}}this.B=this._;if(!e(this,'')){return false}au=this.A-this._;a4=true;e:while(a4===true){a4=false;a5=true;c:while(a5===true){a5=false;t=this.A-this._;a6=true;b:while(a6===true){a6=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){break b}this.B=this._;if(!e(this,'')){return false}if(!i(this)){break b}break c}this._=this.A-t;a7=true;f:while(a7===true){a7=false;this.C=this._;a8=true;b:while(a8===true){a8=false;aw=this.A-this._;a9=true;g:while(a9===true){a9=false;if(!(b(this,a.a_0,10)===0?false:!k(this)?false:true)){break g}break b}this._=this.A-aw;if(!(!c(this)?false:!f(this,a.g_U,105,305)?false:!l(this)?false:true)){break f}}this.B=this._;if(!e(this,'')){return false}u=this.A-this._;aa=true;b:while(aa===true){aa=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-u;break b}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-u;break b}}break c}this._=this.A-t;if(!i(this)){this._=this.A-au;break e}}}break a}this._=this.A-d;ab=true;b:while(ab===true){ab=false;this.C=this._;if(!(b(this,a.a_1,2)===0?false:true)){break b}this.B=this._;if(!e(this,'')){return false}break a}this._=this.A-d;ac=true;b:while(ac===true){ac=false;if(!i(this)){break b}break a}this._=this.A-d;ad=true;c:while(ad===true){ad=false;this.C=this._;ae=true;b:while(ae===true){ae=false;v=this.A-this._;af=true;d:while(af===true){af=false;if(!(!c(this)?false:b(this,a.a_6,4)===0?false:true)){break d}break b}this._=this.A-v;ag=true;d:while(ag===true){ag=false;if(!(!c(this)?false:!f(this,a.g_U,105,305)?false:!h(this)?false:true)){break d}break b}this._=this.A-v;if(!(!c(this)?false:b(this,a.a_4,2)===0?false:!h(this)?false:true)){break c}}this.B=this._;if(!e(this,'')){return false}w=this.A-this._;ah=true;b:while(ah===true){ah=false;this.C=this._;ai=true;d:while(ai===true){ai=false;aA=this.A-this._;aj=true;e:while(aj===true){aj=false;if(!(b(this,a.a_0,10)===0?false:!k(this)?false:true)){break e}this.B=this._;if(!e(this,'')){return false}aB=this.A-this._;ak=true;f:while(ak===true){ak=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-aB;break f}}break d}this._=this.A-aA;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-w;break b}}this.B=this._;if(!e(this,'')){return false}this.C=this._;if(!i(this)){this._=this.A-w;break b}}break a}az=this._=this.A-d;this.C=az;al=true;b:while(al===true){al=false;ao=this.A-this._;am=true;c:while(am===true){am=false;if(!(b(this,a.a_0,10)===0?false:!k(this)?false:true)){break c}break b}this._=this.A-ao;if(!(!c(this)?false:!f(this,a.g_U,105,305)?false:!l(this)?false:true)){return false}}this.B=this._;if(!e(this,'')){return false}x=this.A-this._;an=true;b:while(an===true){an=false;this.C=this._;if(!(!c(this)?false:b(this,a.a_16,2)===0?false:true)){this._=this.A-x;break b}this.B=this._;if(!e(this,'')){return false}if(!i(this)){this._=this.A-x;break b}}}return true};a.prototype.r_stem_noun_suffixes=a.prototype.z;function L(d){var g;var as;var S;var m;var aw;var n;var ar;var p;var q;var ay;var az;var r;var aq;var s;var t;var at;var au;var av;var u;var ax;var v;var w;var x;var aB;var aC;var ap;var y;var z;var A;var B;var C;var D;var E;var F;var G;var H;var I;var J;var K;var L;var M;var N;var O;var P;var Q;var R;var j;var T;var U;var V;var W;var X;var Y;var Z;var _;var $;var a0;var a1;var a2;var a3;var a4;var a5;var a6;var a7;var a8;var a9;var aa;var ab;var ac;var ad;var ae;var af;var ag;var ah;var ai;var aj;var ak;var al;var am;var an;var ao;var aD;var aA;z=true;a:while(z===true){z=false;g=d.A-d._;A=true;b:while(A===true){A=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){break b}d.B=d._;if(!e(d,'')){return false}as=d.A-d._;B=true;c:while(B===true){B=false;if(!i(d)){d._=d.A-as;break c}}break a}d._=d.A-g;C=true;g:while(C===true){C=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_11,2)===0?false:!o(d)?false:true)){break g}d.B=d._;if(!e(d,'')){return false}S=d.A-d._;D=true;b:while(D===true){D=false;E=true;c:while(E===true){E=false;m=d.A-d._;F=true;d:while(F===true){F=false;d.C=d._;if(!(b(d,a.a_1,2)===0?false:true)){break d}d.B=d._;if(!e(d,'')){return false}break c}d._=d.A-m;G=true;f:while(G===true){G=false;d.C=d._;H=true;d:while(H===true){H=false;aw=d.A-d._;I=true;e:while(I===true){I=false;if(!(b(d,a.a_0,10)===0?false:!k(d)?false:true)){break e}break d}d._=d.A-aw;if(!(!c(d)?false:!f(d,a.g_U,105,305)?false:!l(d)?false:true)){break f}}d.B=d._;if(!e(d,'')){return false}n=d.A-d._;J=true;d:while(J===true){J=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-n;break d}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-n;break d}}break c}aD=d._=d.A-m;d.C=aD;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-S;break b}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-S;break b}}}break a}d._=d.A-g;K=true;b:while(K===true){K=false;d.C=d._;L=true;d:while(L===true){L=false;ar=d.A-d._;M=true;c:while(M===true){M=false;if(!(!c(d)?false:b(d,a.a_7,2)===0?false:true)){break c}break d}d._=d.A-ar;if(!(!c(d)?false:b(d,a.a_5,2)===0?false:true)){break b}}N=true;c:while(N===true){N=false;p=d.A-d._;O=true;d:while(O===true){O=false;if(!(b(d,a.a_1,2)===0?false:true)){break d}d.B=d._;if(!e(d,'')){return false}break c}d._=d.A-p;P=true;e:while(P===true){P=false;if(!(!c(d)?false:!f(d,a.g_U,105,305)?false:!l(d)?false:true)){break e}d.B=d._;if(!e(d,'')){return false}q=d.A-d._;Q=true;d:while(Q===true){Q=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-q;break d}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-q;break d}}break c}d._=d.A-p;if(!i(d)){break b}}break a}d._=d.A-g;R=true;c:while(R===true){R=false;d.C=d._;j=true;b:while(j===true){j=false;ay=d.A-d._;T=true;d:while(T===true){T=false;if(!(!c(d)?false:b(d,a.a_9,2)===0?false:true)){break d}break b}d._=d.A-ay;if(!(!c(d)?false:b(d,a.a_2,4)===0?false:true)){break c}}U=true;d:while(U===true){U=false;az=d.A-d._;V=true;e:while(V===true){V=false;if(!(!c(d)?false:!f(d,a.g_U,105,305)?false:!l(d)?false:true)){break e}d.B=d._;if(!e(d,'')){return false}r=d.A-d._;W=true;b:while(W===true){W=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-r;break b}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-r;break b}}break d}d._=d.A-az;if(!(b(d,a.a_1,2)===0?false:true)){break c}}break a}d._=d.A-g;X=true;d:while(X===true){X=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_8,4)===0?false:true)){break d}d.B=d._;if(!e(d,'')){return false}aq=d.A-d._;Y=true;e:while(Y===true){Y=false;d.C=d._;Z=true;c:while(Z===true){Z=false;s=d.A-d._;_=true;f:while(_===true){_=false;if(!(b(d,a.a_0,10)===0?false:!k(d)?false:true)){break f}d.B=d._;if(!e(d,'')){return false}t=d.A-d._;$=true;b:while($===true){$=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-t;break b}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-t;break b}}break c}d._=d.A-s;a0=true;b:while(a0===true){a0=false;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){break b}d.B=d._;if(!e(d,'')){return false}at=d.A-d._;a1=true;f:while(a1===true){a1=false;if(!i(d)){d._=d.A-at;break f}}break c}d._=d.A-s;if(!i(d)){d._=d.A-aq;break e}}}break a}d._=d.A-g;a2=true;d:while(a2===true){a2=false;d.C=d._;a3=true;b:while(a3===true){a3=false;au=d.A-d._;a4=true;c:while(a4===true){a4=false;if(!(!c(d)?false:b(d,a.a_3,4)===0?false:!o(d)?false:true)){break c}break b}d._=d.A-au;if(!(!c(d)?false:b(d,a.a_10,2)===0?false:!h(d)?false:true)){break d}}d.B=d._;if(!e(d,'')){return false}av=d.A-d._;a5=true;e:while(a5===true){a5=false;a6=true;c:while(a6===true){a6=false;u=d.A-d._;a7=true;b:while(a7===true){a7=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){break b}d.B=d._;if(!e(d,'')){return false}if(!i(d)){break b}break c}d._=d.A-u;a8=true;f:while(a8===true){a8=false;d.C=d._;a9=true;b:while(a9===true){a9=false;ax=d.A-d._;aa=true;g:while(aa===true){aa=false;if(!(b(d,a.a_0,10)===0?false:!k(d)?false:true)){break g}break b}d._=d.A-ax;if(!(!c(d)?false:!f(d,a.g_U,105,305)?false:!l(d)?false:true)){break f}}d.B=d._;if(!e(d,'')){return false}v=d.A-d._;ab=true;b:while(ab===true){ab=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-v;break b}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-v;break b}}break c}d._=d.A-u;if(!i(d)){d._=d.A-av;break e}}}break a}d._=d.A-g;ac=true;b:while(ac===true){ac=false;d.C=d._;if(!(b(d,a.a_1,2)===0?false:true)){break b}d.B=d._;if(!e(d,'')){return false}break a}d._=d.A-g;ad=true;b:while(ad===true){ad=false;if(!i(d)){break b}break a}d._=d.A-g;ae=true;c:while(ae===true){ae=false;d.C=d._;af=true;b:while(af===true){af=false;w=d.A-d._;ag=true;d:while(ag===true){ag=false;if(!(!c(d)?false:b(d,a.a_6,4)===0?false:true)){break d}break b}d._=d.A-w;ah=true;d:while(ah===true){ah=false;if(!(!c(d)?false:!f(d,a.g_U,105,305)?false:!h(d)?false:true)){break d}break b}d._=d.A-w;if(!(!c(d)?false:b(d,a.a_4,2)===0?false:!h(d)?false:true)){break c}}d.B=d._;if(!e(d,'')){return false}x=d.A-d._;ai=true;b:while(ai===true){ai=false;d.C=d._;aj=true;d:while(aj===true){aj=false;aB=d.A-d._;ak=true;e:while(ak===true){ak=false;if(!(b(d,a.a_0,10)===0?false:!k(d)?false:true)){break e}d.B=d._;if(!e(d,'')){return false}aC=d.A-d._;al=true;f:while(al===true){al=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-aC;break f}}break d}d._=d.A-aB;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-x;break b}}d.B=d._;if(!e(d,'')){return false}d.C=d._;if(!i(d)){d._=d.A-x;break b}}break a}aA=d._=d.A-g;d.C=aA;am=true;b:while(am===true){am=false;ap=d.A-d._;an=true;c:while(an===true){an=false;if(!(b(d,a.a_0,10)===0?false:!k(d)?false:true)){break c}break b}d._=d.A-ap;if(!(!c(d)?false:!f(d,a.g_U,105,305)?false:!l(d)?false:true)){return false}}d.B=d._;if(!e(d,'')){return false}y=d.A-d._;ao=true;b:while(ao===true){ao=false;d.C=d._;if(!(!c(d)?false:b(d,a.a_16,2)===0?false:true)){d._=d.A-y;break b}d.B=d._;if(!e(d,'')){return false}if(!i(d)){d._=d.A-y;break b}}}return true};a.prototype.w=function(){var c;this.C=this._;c=b(this,a.a_23,4);if(c===0){return false}this.B=this._;switch(c){case 0:return false;case 1:if(!e(this,'p')){return false}break;case 2:if(!e(this,'ç')){return false}break;case 3:if(!e(this,'t')){return false}break;case 4:if(!e(this,'k')){return false}break}return true};a.prototype.r_post_process_last_consonants=a.prototype.w;function w(c){var d;c.C=c._;d=b(c,a.a_23,4);if(d===0){return false}c.B=c._;switch(d){case 0:return false;case 1:if(!e(c,'p')){return false}break;case 2:if(!e(c,'ç')){return false}break;case 3:if(!e(c,'t')){return false}break;case 4:if(!e(c,'k')){return false}break}return true};a.prototype.N=function(){var L;var _;var i;var Y;var B;var W;var K;var l;var S;var Q;var p;var O;var M;var s;var U;var u;var v;var w;var x;var y;var z;var A;var b;var C;var D;var j;var F;var G;var H;var I;var J;var E;var t;var r;var N;var q;var P;var o;var R;var m;var T;var k;var V;var h;var X;var e;var Z;var d;var $;var a0;var a1;var c;L=this.A-this._;u=true;a:while(u===true){u=false;_=this.A-this._;v=true;b:while(v===true){v=false;if(!g(this,1,'d')){break b}break a}this._=this.A-_;if(!g(this,1,'g')){return false}}this._=this.A-L;w=true;a:while(w===true){w=false;i=this.A-this._;x=true;b:while(x===true){x=false;Y=this.A-this._;d:while(true){B=this.A-this._;y=true;c:while(y===true){y=false;if(!f(this,a.g_vowel,97,305)){break c}this._=this.A-B;break d}V=this._=this.A-B;if(V<=this.D){break b}this._--}z=true;c:while(z===true){z=false;W=this.A-this._;A=true;d:while(A===true){A=false;if(!g(this,1,'a')){break d}break c}this._=this.A-W;if(!g(this,1,'ı')){break b}}h=this._=this.A-Y;b=h;N=h;q=n(this,h,h,'ı');if(h<=this.B){this.B+=q|0}if(N<=this.C){this.C+=q|0}this._=b;break a}this._=this.A-i;C=true;b:while(C===true){C=false;K=this.A-this._;c:while(true){l=this.A-this._;D=true;d:while(D===true){D=false;if(!f(this,a.g_vowel,97,305)){break d}this._=this.A-l;break c}X=this._=this.A-l;if(X<=this.D){break b}this._--}j=true;c:while(j===true){j=false;S=this.A-this._;F=true;d:while(F===true){F=false;if(!g(this,1,'e')){break d}break c}this._=this.A-S;if(!g(this,1,'i')){break b}}e=this._=this.A-K;b=e;P=e;o=n(this,e,e,'i');if(e<=this.B){this.B+=o|0}if(P<=this.C){this.C+=o|0}this._=b;break a}this._=this.A-i;G=true;b:while(G===true){G=false;Q=this.A-this._;c:while(true){p=this.A-this._;H=true;d:while(H===true){H=false;if(!f(this,a.g_vowel,97,305)){break d}this._=this.A-p;break c}Z=this._=this.A-p;if(Z<=this.D){break b}this._--}I=true;c:while(I===true){I=false;O=this.A-this._;J=true;d:while(J===true){J=false;if(!g(this,1,'o')){break d}break c}this._=this.A-O;if(!g(this,1,'u')){break b}}d=this._=this.A-Q;b=d;R=d;m=n(this,d,d,'u');if(d<=this.B){this.B+=m|0}if(R<=this.C){this.C+=m|0}this._=b;break a}a1=this._=(a0=this.A)-i;M=a0-a1;b:while(true){s=this.A-this._;E=true;c:while(E===true){E=false;if(!f(this,a.g_vowel,97,305)){break c}this._=this.A-s;break b}$=this._=this.A-s;if($<=this.D){return false}this._--}t=true;b:while(t===true){t=false;U=this.A-this._;r=true;c:while(r===true){r=false;if(!g(this,1,'ö')){break c}break b}this._=this.A-U;if(!g(this,1,'ü')){return false}}c=this._=this.A-M;b=c;T=c;k=n(this,c,c,'ü');if(c<=this.B){this.B+=k|0}if(T<=this.C){this.C+=k|0}this._=b}return true};a.prototype.r_append_U_to_stems_ending_with_d_or_g=a.prototype.N;function z(b){var $;var Z;var j;var X;var F;var L;var T;var m;var R;var P;var q;var N;var V;var t;var M;var v;var w;var x;var y;var z;var A;var B;var c;var D;var E;var C;var G;var H;var I;var J;var K;var u;var s;var r;var O;var p;var Q;var o;var S;var l;var U;var k;var W;var i;var Y;var h;var _;var e;var a0;var a1;var a2;var d;$=b.A-b._;v=true;a:while(v===true){v=false;Z=b.A-b._;w=true;b:while(w===true){w=false;if(!g(b,1,'d')){break b}break a}b._=b.A-Z;if(!g(b,1,'g')){return false}}b._=b.A-$;x=true;a:while(x===true){x=false;j=b.A-b._;y=true;b:while(y===true){y=false;X=b.A-b._;d:while(true){F=b.A-b._;z=true;c:while(z===true){z=false;if(!f(b,a.g_vowel,97,305)){break c}b._=b.A-F;break d}W=b._=b.A-F;if(W<=b.D){break b}b._--}A=true;c:while(A===true){A=false;L=b.A-b._;B=true;d:while(B===true){B=false;if(!g(b,1,'a')){break d}break c}b._=b.A-L;if(!g(b,1,'ı')){break b}}i=b._=b.A-X;c=i;O=i;p=n(b,i,i,'ı');if(i<=b.B){b.B+=p|0}if(O<=b.C){b.C+=p|0}b._=c;break a}b._=b.A-j;D=true;b:while(D===true){D=false;T=b.A-b._;c:while(true){m=b.A-b._;E=true;d:while(E===true){E=false;if(!f(b,a.g_vowel,97,305)){break d}b._=b.A-m;break c}Y=b._=b.A-m;if(Y<=b.D){break b}b._--}C=true;c:while(C===true){C=false;R=b.A-b._;G=true;d:while(G===true){G=false;if(!g(b,1,'e')){break d}break c}b._=b.A-R;if(!g(b,1,'i')){break b}}h=b._=b.A-T;c=h;Q=h;o=n(b,h,h,'i');if(h<=b.B){b.B+=o|0}if(Q<=b.C){b.C+=o|0}b._=c;break a}b._=b.A-j;H=true;b:while(H===true){H=false;P=b.A-b._;c:while(true){q=b.A-b._;I=true;d:while(I===true){I=false;if(!f(b,a.g_vowel,97,305)){break d}b._=b.A-q;break c}_=b._=b.A-q;if(_<=b.D){break b}b._--}J=true;c:while(J===true){J=false;N=b.A-b._;K=true;d:while(K===true){K=false;if(!g(b,1,'o')){break d}break c}b._=b.A-N;if(!g(b,1,'u')){break b}}e=b._=b.A-P;c=e;S=e;l=n(b,e,e,'u');if(e<=b.B){b.B+=l|0}if(S<=b.C){b.C+=l|0}b._=c;break a}a2=b._=(a1=b.A)-j;V=a1-a2;b:while(true){t=b.A-b._;u=true;c:while(u===true){u=false;if(!f(b,a.g_vowel,97,305)){break c}b._=b.A-t;break b}a0=b._=b.A-t;if(a0<=b.D){return false}b._--}s=true;b:while(s===true){s=false;M=b.A-b._;r=true;c:while(r===true){r=false;if(!g(b,1,'ö')){break c}break b}b._=b.A-M;if(!g(b,1,'ü')){return false}}d=b._=b.A-V;c=d;U=d;k=n(b,d,d,'ü');if(d<=b.B){b.B+=k|0}if(U<=b.C){b.C+=k|0}b._=c}return true};a.prototype.v=function(){var e;var f;var b;var c;var d;e=this._;b=2;a:while(true){f=this._;c=true;b:while(c===true){c=false;c:while(true){d=true;d:while(d===true){d=false;if(!v(this,a.g_vowel,97,305)){break d}break c}if(this._>=this.A){break b}this._++}b--;continue a}this._=f;break a}if(b>0){return false}this._=e;return true};a.prototype.r_more_than_one_syllable_word=a.prototype.v;function N(b){var f;var g;var c;var d;var e;f=b._;c=2;a:while(true){g=b._;d=true;b:while(d===true){d=false;c:while(true){e=true;d:while(e===true){e=false;if(!v(b,a.g_vowel,97,305)){break d}break c}if(b._>=b.A){break b}b._++}c--;continue a}b._=g;break a}if(c>0){return false}b._=f;return true};a.prototype.P=function(){var f;var g;var h;var b;var a;var c;var d;var i;var j;var e;b=true;b:while(b===true){b=false;f=this._;a=true;a:while(a===true){a=false;g=this._;c:while(true){c=true;d:while(c===true){c=false;if(!s(this,2,'ad')){break d}break c}if(this._>=this.A){break a}this._++}i=this.I_strlen=2;if(!(i===this.A)){break a}this._=g;break b}j=this._=f;h=j;a:while(true){d=true;c:while(d===true){d=false;if(!s(this,5,'soyad')){break c}break a}if(this._>=this.A){return false}this._++}e=this.I_strlen=5;if(!(e===this.A)){return false}this._=h}return true};a.prototype.r_is_reserved_word=a.prototype.P;function x(a){var g;var h;var i;var c;var b;var d;var e;var j;var k;var f;c=true;b:while(c===true){c=false;g=a._;b=true;a:while(b===true){b=false;h=a._;c:while(true){d=true;d:while(d===true){d=false;if(!s(a,2,'ad')){break d}break c}if(a._>=a.A){break a}a._++}j=a.I_strlen=2;if(!(j===a.A)){break a}a._=h;break b}k=a._=g;i=k;a:while(true){e=true;c:while(e===true){e=false;if(!s(a,5,'soyad')){break c}break a}if(a._>=a.A){return false}a._++}f=a.I_strlen=5;if(!(f===a.A)){return false}a._=i}return true};a.prototype.x=function(){var d;var e;var a;var b;var c;var f;var g;var h;d=this._;a=true;a:while(a===true){a=false;if(!x(this)){break a}return false}f=this._=d;this.D=f;h=this._=g=this.A;e=g-h;b=true;a:while(b===true){b=false;if(!z(this)){break a}}this._=this.A-e;c=true;a:while(c===true){c=false;if(!w(this)){break a}}this._=this.D;return true};a.prototype.r_postlude=a.prototype.x;function O(a){var e;var f;var b;var c;var d;var g;var h;var i;e=a._;b=true;a:while(b===true){b=false;if(!x(a)){break a}return false}g=a._=e;a.D=g;i=a._=h=a.A;f=h-i;c=true;a:while(c===true){c=false;if(!z(a)){break a}}a._=a.A-f;d=true;a:while(d===true){d=false;if(!w(a)){break a}}a._=a.D;return true};a.prototype.H=function(){var c;var a;var b;var d;var e;if(!N(this)){return false}this.D=this._;e=this._=d=this.A;c=d-e;a=true;a:while(a===true){a=false;if(!J(this)){break a}}this._=this.A-c;if(!this.B_continue_stemming_noun_suffixes){return false}b=true;a:while(b===true){b=false;if(!L(this)){break a}}this._=this.D;return!O(this)?false:true};a.prototype.stem=a.prototype.H;a.prototype.L=function(b){return b instanceof a};a.prototype.equals=a.prototype.L;a.prototype.M=function(){var c;var a;var b;var d;c='TurkishStemmer';a=0;for(b=0;b<c.length;b++){d=c.charCodeAt(b);a=(a<<5)-a+d;a=a&a}return a|0};a.prototype.hashCode=a.prototype.M;a.serialVersionUID=1;j(a,'methodObject',function(){return new a});j(a,'a_0',function(){return[new d('m',-1,-1),new d('n',-1,-1),new d('miz',-1,-1),new d('niz',-1,-1),new d('muz',-1,-1),new d('nuz',-1,-1),new d('müz',-1,-1),new d('nüz',-1,-1),new d('mız',-1,-1),new d('nız',-1,-1)]});j(a,'a_1',function(){return[new d('leri',-1,-1),new d('ları',-1,-1)]});j(a,'a_2',function(){return[new d('ni',-1,-1),new d('nu',-1,-1),new d('nü',-1,-1),new d('nı',-1,-1)]});j(a,'a_3',function(){return[new d('in',-1,-1),new d('un',-1,-1),new d('ün',-1,-1),new d('ın',-1,-1)]});j(a,'a_4',function(){return[new d('a',-1,-1),new d('e',-1,-1)]});j(a,'a_5',function(){return[new d('na',-1,-1),new d('ne',-1,-1)]});j(a,'a_6',function(){return[new d('da',-1,-1),new d('ta',-1,-1),new d('de',-1,-1),new d('te',-1,-1)]});j(a,'a_7',function(){return[new d('nda',-1,-1),new d('nde',-1,-1)]});j(a,'a_8',function(){return[new d('dan',-1,-1),new d('tan',-1,-1),new d('den',-1,-1),new d('ten',-1,-1)]});j(a,'a_9',function(){return[new d('ndan',-1,-1),new d('nden',-1,-1)]});j(a,'a_10',function(){return[new d('la',-1,-1),new d('le',-1,-1)]});j(a,'a_11',function(){return[new d('ca',-1,-1),new d('ce',-1,-1)]});j(a,'a_12',function(){return[new d('im',-1,-1),new d('um',-1,-1),new d('üm',-1,-1),new d('ım',-1,-1)]});j(a,'a_13',function(){return[new d('sin',-1,-1),new d('sun',-1,-1),new d('sün',-1,-1),new d('sın',-1,-1)]});j(a,'a_14',function(){return[new d('iz',-1,-1),new d('uz',-1,-1),new d('üz',-1,-1),new d('ız',-1,-1)]});j(a,'a_15',function(){return[new d('siniz',-1,-1),new d('sunuz',-1,-1),new d('sünüz',-1,-1),new d('sınız',-1,-1)]});j(a,'a_16',function(){return[new d('lar',-1,-1),new d('ler',-1,-1)]});j(a,'a_17',function(){return[new d('niz',-1,-1),new d('nuz',-1,-1),new d('nüz',-1,-1),new d('nız',-1,-1)]});j(a,'a_18',function(){return[new d('dir',-1,-1),new d('tir',-1,-1),new d('dur',-1,-1),new d('tur',-1,-1),new d('dür',-1,-1),new d('tür',-1,-1),new d('dır',-1,-1),new d('tır',-1,-1)]});j(a,'a_19',function(){return[new d('casına',-1,-1),new d('cesine',-1,-1)]});j(a,'a_20',function(){return[new d('di',-1,-1),new d('ti',-1,-1),new d('dik',-1,-1),new d('tik',-1,-1),new d('duk',-1,-1),new d('tuk',-1,-1),new d('dük',-1,-1),new d('tük',-1,-1),new d('dık',-1,-1),new d('tık',-1,-1),new d('dim',-1,-1),new d('tim',-1,-1),new d('dum',-1,-1),new d('tum',-1,-1),new d('düm',-1,-1),new d('tüm',-1,-1),new d('dım',-1,-1),new d('tım',-1,-1),new d('din',-1,-1),new d('tin',-1,-1),new d('dun',-1,-1),new d('tun',-1,-1),new d('dün',-1,-1),new d('tün',-1,-1),new d('dın',-1,-1),new d('tın',-1,-1),new d('du',-1,-1),new d('tu',-1,-1),new d('dü',-1,-1),new d('tü',-1,-1),new d('dı',-1,-1),new d('tı',-1,-1)]});j(a,'a_21',function(){return[new d('sa',-1,-1),new d('se',-1,-1),new d('sak',-1,-1),new d('sek',-1,-1),new d('sam',-1,-1),new d('sem',-1,-1),new d('san',-1,-1),new d('sen',-1,-1)]});j(a,'a_22',function(){return[new d('miş',-1,-1),new d('muş',-1,-1),new d('müş',-1,-1),new d('mış',-1,-1)]});j(a,'a_23',function(){return[new d('b',-1,1),new d('c',-1,2),new d('d',-1,3),new d('ğ',-1,4)]});j(a,'g_vowel',function(){return[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,8,0,0,0,0,0,0,1]});j(a,'g_U',function(){return[1,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,1]});j(a,'g_vowel1',function(){return[1,64,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]});j(a,'g_vowel2',function(){return[17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130]});j(a,'g_vowel3',function(){return[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]});j(a,'g_vowel4',function(){return[17]});j(a,'g_vowel5',function(){return[65]});j(a,'g_vowel6',function(){return[65]});var y={'src/stemmer.jsx':{Stemmer:u},'src/turkish-stemmer.jsx':{TurkishStemmer:a}}}(JSX))
+var Stemmer = JSX.require("src/turkish-stemmer.jsx").TurkishStemmer;
+"""
+
+
+class SearchTurkish(SearchLanguage):
+ lang = 'tr'
+ language_name = 'Turkish'
+ js_stemmer_code = js_stemmer
+ stopwords = []
+
+ def init(self, options):
+ self.stemmer = snowballstemmer.stemmer('turkish')
+
+ def stem(self, word):
+ return self.stemmer.stemWord(word)
diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py
index a487b2a2..22f2727d 100644
--- a/sphinx/setup_command.py
+++ b/sphinx/setup_command.py
@@ -11,14 +11,15 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
import sys
import os
-import types
-from StringIO import StringIO
from distutils.cmd import Command
from distutils.errors import DistutilsOptionError, DistutilsExecError
+from six import StringIO, string_types
+
from sphinx.application import Sphinx
from sphinx.util.console import darkred, nocolor, color_terminal
from sphinx.util.osutil import abspath
@@ -108,7 +109,7 @@ class BuildDoc(Command):
if val is None:
setattr(self, option, default)
return default
- elif not isinstance(val, types.StringTypes):
+ elif not isinstance(val, string_types):
raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
% (option, what, val))
return val
@@ -137,7 +138,6 @@ class BuildDoc(Command):
def run(self):
if not color_terminal():
- # Windows' poor cmd box doesn't understand ANSI sequences
nocolor()
if not self.verbose:
status_stream = StringIO()
@@ -162,12 +162,12 @@ class BuildDoc(Command):
if app.statuscode:
raise DistutilsExecError(
'caused by %s builder.' % app.builder.name)
- except Exception, err:
+ except Exception as 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')
+ print(darkred('reST markup error:'), file=sys.stderr)
+ print(err.args[0].encode('ascii', 'backslashreplace'),
+ file=sys.stderr)
else:
raise
diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile
index 6b87ad88..5e6030c0 100644
--- a/sphinx/texinputs/Makefile
+++ b/sphinx/texinputs/Makefile
@@ -9,6 +9,10 @@ ARCHIVEPRREFIX =
# Additional LaTeX options
LATEXOPTS =
+LATEX = latex
+PDFLATEX = pdflatex
+MAKEINDEX = makeindex
+
all: $(ALLPDF)
all-pdf: $(ALLPDF)
all-dvi: $(ALLDVI)
@@ -43,20 +47,20 @@ bz2: 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) '$<'
+ $(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) '$<'
+ $(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
diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty
index ee0a923d..d617c62b 100644
--- a/sphinx/texinputs/sphinx.sty
+++ b/sphinx/texinputs/sphinx.sty
@@ -522,3 +522,9 @@
\gdef\@chappos{}
}
\fi
+
+% Define literal-block environment
+\RequirePackage{float}
+\floatstyle{plaintop}
+\newfloat{literal-block}{htbp}{loc}[chapter]
+\floatname{literal-block}{List}
diff --git a/sphinx/themes/agogo/layout.html b/sphinx/themes/agogo/layout.html
index c6960fb0..a29299b9 100644
--- a/sphinx/themes/agogo/layout.html
+++ b/sphinx/themes/agogo/layout.html
@@ -11,7 +11,7 @@
{%- extends "basic/layout.html" %}
{% block header %}
- <div class="header-wrapper">
+ <div class="header-wrapper" role="banner">
<div class="header">
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc) }}">
@@ -22,7 +22,7 @@
<div class="headertitle"><a
href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a></div>
{%- endblock %}
- <div class="rel">
+ <div class="rel" role="navigation" aria-label="related navigation">
{%- for rellink in rellinks|reverse %}
<a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
{{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
@@ -47,16 +47,18 @@
{{ 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>
+ <div role="search">
+ <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>
+ </div>
{%- endblock %}
</div>
<div class="clearer"></div>
@@ -68,16 +70,20 @@
<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 role="navigation" aria-label="related navigaton">
+ {%- 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 role="note" aria-label="source link">
+ {%- if show_source and has_source and sourcename %}
+ <br/>
+ <a href="{{ pathto('_sources/' + sourcename, true)|e }}"
+ rel="nofollow">{{ _('Show Source') }}</a>
+ {%- endif %}
+ </div>
</div>
<div class="right">
diff --git a/sphinx/themes/agogo/static/agogo.css_t b/sphinx/themes/agogo/static/agogo.css_t
index 1ec21470..686b1312 100644
--- a/sphinx/themes/agogo/static/agogo.css_t
+++ b/sphinx/themes/agogo/static/agogo.css_t
@@ -97,7 +97,10 @@ h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
-dt:hover > a.headerlink {
+dt:hover > a.headerlink,
+caption:hover > a.headerlink,
+p.caption:hover > a.headerlink,
+div.code-block-caption:hover > a.headerlink {
visibility: visible;
}
@@ -223,6 +226,10 @@ div.document .descname {
font-weight: bold;
}
+div.document .sig-paren {
+ font-size: larger;
+}
+
div.document .docutils.literal {
background-color: #eeeeec;
padding: 1px;
@@ -462,3 +469,10 @@ div.viewcode-block:target {
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
+
+div.code-block-caption {
+ background-color: #ddd;
+ color: #333;
+ padding: 2px 5px;
+ font-size: small;
+}
diff --git a/sphinx/themes/basic/domainindex.html b/sphinx/themes/basic/domainindex.html
index ac5aed9f..4ee62d55 100644
--- a/sphinx/themes/basic/domainindex.html
+++ b/sphinx/themes/basic/domainindex.html
@@ -44,7 +44,7 @@
{%- endif %}</td>
<td>{% if grouptype == 2 %}&nbsp;&nbsp;&nbsp;{% endif %}
{% if page %}<a href="{{ pathto(page) }}#{{ anchor }}">{% endif -%}
- <tt class="xref">{{ name|e }}</tt>
+ <code class="xref">{{ name|e }}</code>
{%- if page %}</a>{% endif %}
{%- if extra %} <em>({{ extra|e }})</em>{% endif -%}
</td><td>{% if qualifier %}<strong>{{ qualifier|e }}:</strong>{% endif %}
diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html
index 552da638..a7bbbb9a 100644
--- a/sphinx/themes/basic/layout.html
+++ b/sphinx/themes/basic/layout.html
@@ -25,7 +25,7 @@
{%- endif %}
{%- macro relbar() %}
- <div class="related">
+ <div class="related" role="navigation" aria-label="related navigation">
<h3>{{ _('Navigation') }}</h3>
<ul>
{%- for rellink in rellinks %}
@@ -47,7 +47,7 @@
{%- macro sidebar() %}
{%- if render_sidebar %}
- <div class="sphinxsidebar">
+ <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
{%- block sidebarlogo %}
{%- if logo %}
@@ -152,7 +152,7 @@
{%- endblock %}
{%- block extrahead %} {% endblock %}
</head>
- <body>
+ <body role="document">
{%- block header %}{% endblock %}
{%- block relbar1 %}{{ relbar() }}{% endblock %}
@@ -166,7 +166,7 @@
{%- if render_sidebar %}
<div class="bodywrapper">
{%- endif %}
- <div class="body">
+ <div class="body" role="main">
{% block body %} {% endblock %}
</div>
{%- if render_sidebar %}
@@ -183,7 +183,7 @@
{%- block relbar2 %}{{ relbar() }}{% endblock %}
{%- block footer %}
- <div class="footer">
+ <div class="footer" role="contentinfo">
{%- if show_copyright %}
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
diff --git a/sphinx/themes/basic/searchbox.html b/sphinx/themes/basic/searchbox.html
index 0a746f57..ffcce73e 100644
--- a/sphinx/themes/basic/searchbox.html
+++ b/sphinx/themes/basic/searchbox.html
@@ -8,7 +8,7 @@
:license: BSD, see LICENSE for details.
#}
{%- if pagename != "search" and builder != "singlehtml" %}
-<div id="searchbox" style="display: none">
+<div id="searchbox" style="display: none" role="search">
<h3>{{ _('Quick search') }}</h3>
<form class="search" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" />
diff --git a/sphinx/themes/basic/sourcelink.html b/sphinx/themes/basic/sourcelink.html
index f3cb71fd..abd6a97f 100644
--- a/sphinx/themes/basic/sourcelink.html
+++ b/sphinx/themes/basic/sourcelink.html
@@ -8,9 +8,11 @@
: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>
+ <div role="note" aria-label="source link">
+ <h3>{{ _('This Page') }}</h3>
+ <ul class="this-page-menu">
+ <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
+ rel="nofollow">{{ _('Show Source') }}</a></li>
+ </ul>
+ </div>
{%- endif %}
diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t
index 7ffa4664..1d1c5e59 100644
--- a/sphinx/themes/basic/static/basic.css_t
+++ b/sphinx/themes/basic/static/basic.css_t
@@ -197,7 +197,10 @@ h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
-dt:hover > a.headerlink {
+dt:hover > a.headerlink,
+caption:hover > a.headerlink,
+p.caption:hover > a.headerlink,
+div.code-block-caption:hover > a.headerlink {
visibility: visible;
}
@@ -406,6 +409,10 @@ dl.glossary dt {
font-size: 1.3em;
}
+.sig-paren {
+ font-size: larger;
+}
+
.versionmodified {
font-style: italic;
}
@@ -471,22 +478,35 @@ table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
-tt.descname {
+div.code-block-caption {
+ padding: 2px 5px;
+ font-size: small;
+}
+
+div.code-block-filename code {
+ background-color: transparent;
+}
+
+div.code-block-caption + div > div.highlight > pre {
+ margin-top: 0;
+}
+
+code.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
-tt.descclassname {
+code.descclassname {
background-color: transparent;
}
-tt.xref, a tt {
+code.xref, a code {
background-color: transparent;
font-weight: bold;
}
-h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
background-color: transparent;
}
diff --git a/sphinx/themes/basic/static/doctools.js b/sphinx/themes/basic/static/doctools.js
index c5455c90..8c9b995d 100644
--- a/sphinx/themes/basic/static/doctools.js
+++ b/sphinx/themes/basic/static/doctools.js
@@ -91,6 +91,30 @@ jQuery.fn.highlightText = function(text, className) {
});
};
+/*
+ * backward compatibility for jQuery.browser
+ * This will be supported until firefox bug is fixed.
+ */
+if (!jQuery.browser) {
+ jQuery.uaMatch = function(ua) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
+ /(webkit)[ \/]([\w.]+)/.exec(ua) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
+ /(msie) ([\w.]+)/.exec(ua) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+ };
+ jQuery.browser = {};
+ jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
+}
+
/**
* Small JavaScript module for the documentation.
*/
@@ -152,6 +176,7 @@ var Documentation = {
/**
* workaround a firefox stupidity
+ * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash && $.browser.mozilla)
diff --git a/sphinx/themes/basic/static/down-pressed.png b/sphinx/themes/basic/static/down-pressed.png
index 6f7ad782..7c30d004 100644
--- a/sphinx/themes/basic/static/down-pressed.png
+++ b/sphinx/themes/basic/static/down-pressed.png
Binary files differ
diff --git a/sphinx/themes/basic/static/down.png b/sphinx/themes/basic/static/down.png
index 3003a887..f48098a4 100644
--- a/sphinx/themes/basic/static/down.png
+++ b/sphinx/themes/basic/static/down.png
Binary files differ
diff --git a/sphinx/themes/basic/static/file.png b/sphinx/themes/basic/static/file.png
index d18082e3..254c60bf 100644
--- a/sphinx/themes/basic/static/file.png
+++ b/sphinx/themes/basic/static/file.png
Binary files differ
diff --git a/sphinx/themes/basic/static/jquery-1.11.1.js b/sphinx/themes/basic/static/jquery-1.11.1.js
new file mode 100644
index 00000000..d4b67f7e
--- /dev/null
+++ b/sphinx/themes/basic/static/jquery-1.11.1.js
@@ -0,0 +1,10308 @@
+/*!
+ * jQuery JavaScript Library v1.11.1
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-05-01T17:42Z
+ */
+
+(function( global, factory ) {
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+ // For CommonJS and CommonJS-like environments where a proper window is present,
+ // execute the factory and get jQuery
+ // For environments that do not inherently posses a window with a document
+ // (such as Node.js), expose a jQuery-making factory as module.exports
+ // This accentuates the need for the creation of a real window
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//
+
+var deletedIds = [];
+
+var slice = deletedIds.slice;
+
+var concat = deletedIds.concat;
+
+var push = deletedIds.push;
+
+var indexOf = deletedIds.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+ version = "1.11.1",
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ // Need init if jQuery is called (just allow error to be thrown if not included)
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Support: Android<4.1, IE<9
+ // Make sure we trim BOM and NBSP
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+jQuery.fn = jQuery.prototype = {
+ // The current version of jQuery being used
+ jquery: version,
+
+ constructor: jQuery,
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num != null ?
+
+ // Return just the one element from the set
+ ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+ // Return all the elements in a clean array
+ slice.call( this );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: deletedIds.sort,
+ splice: deletedIds.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var src, copyIsArray, copy, name, options, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+
+ // skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( i === length ) {
+ target = this;
+ i--;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+ // Assume jQuery is ready without the ready module
+ isReady: true,
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ noop: function() {},
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ isWindow: function( obj ) {
+ /* jshint eqeqeq: false */
+ return obj != null && obj == obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ // parseFloat NaNs numeric-cast false positives (null|true|false|"")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ isPlainObject: function( obj ) {
+ var key;
+
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Support: IE<9
+ // Handle iteration over inherited properties before own properties.
+ if ( support.ownLast ) {
+ for ( key in obj ) {
+ return hasOwn.call( obj, key );
+ }
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call(obj) ] || "object" :
+ typeof obj;
+ },
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && jQuery.trim( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var value,
+ i = 0,
+ length = obj.length,
+ isArray = isArraylike( obj );
+
+ if ( args ) {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Support: Android<4.1, IE<9
+ trim: function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArraylike( Object(arr) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ var len;
+
+ if ( arr ) {
+ if ( indexOf ) {
+ return indexOf.call( arr, elem, i );
+ }
+
+ len = arr.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in arr && arr[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var len = +second.length,
+ j = 0,
+ i = first.length;
+
+ while ( j < len ) {
+ first[ i++ ] = second[ j++ ];
+ }
+
+ // Support: IE<9
+ // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
+ if ( len !== len ) {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, invert ) {
+ var callbackInverse,
+ matches = [],
+ i = 0,
+ length = elems.length,
+ callbackExpect = !invert;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ callbackInverse = !callback( elems[ i ], i );
+ if ( callbackInverse !== callbackExpect ) {
+ matches.push( elems[ i ] );
+ }
+ }
+
+ return matches;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value,
+ i = 0,
+ length = elems.length,
+ isArray = isArraylike( elems ),
+ ret = [];
+
+ // Go through the array, translating each of the items to their new values
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var args, proxy, tmp;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ now: function() {
+ return +( new Date() );
+ },
+
+ // jQuery.support is not used in Core but other projects attach their
+ // properties to it so it needs to exist.
+ support: support
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+ var length = obj.length,
+ type = jQuery.type( obj );
+
+ if ( type === "function" || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.nodeType === 1 && length ) {
+ return true;
+ }
+
+ return type === "array" || length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v1.10.19
+ * http://sizzlejs.com/
+ *
+ * Copyright 2013 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-04-18
+ */
+(function( window ) {
+
+var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + -(new Date()),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
+
+ // General-purpose constants
+ strundefined = typeof undefined,
+ MAX_NEGATIVE = 1 << 31,
+
+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf if we can't use a native one
+ indexOf = arr.indexOf || function( elem ) {
+ var i = 0,
+ len = this.length;
+ for ( ; i < len; i++ ) {
+ if ( this[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+ // Regular expressions
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
+
+ pseudos = ":(" + characterEncoding + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rsibling = /[+~]/,
+ rescape = /'|\\/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+ funescape = function( _, escaped, escapedWhitespace ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ };
+
+// Optimize for push.apply( _, NodeList )
+try {
+ push.apply(
+ (arr = slice.call( preferredDoc.childNodes )),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+ push = { apply: arr.length ?
+
+ // Leverage slice if possible
+ function( target, els ) {
+ push_native.apply( target, slice.call(els) );
+ } :
+
+ // Support: IE<9
+ // Otherwise append directly
+ function( target, els ) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ( (target[j++] = els[i++]) ) {}
+ target.length = j - 1;
+ }
+ };
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+
+ context = context || document;
+ results = results || [];
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( documentIsHTML && !seed ) {
+
+ // Shortcuts
+ if ( (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document (jQuery #6963)
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // QSA path
+ if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+ nid = old = expando;
+ newContext = context;
+ newSelector = nodeType === 9 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + toSelector( groups[i] );
+ }
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var keys = [];
+
+ function cache( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key + " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key + " " ] = value);
+ }
+ return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return !!fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if ( div.parentNode ) {
+ div.parentNode.removeChild( div );
+ }
+ // release memory in IE
+ div = null;
+ }
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+ var arr = attrs.split("|"),
+ i = attrs.length;
+
+ while ( i-- ) {
+ Expr.attrHandle[ arr[i] ] = handler;
+ }
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ ( ~b.sourceIndex || MAX_NEGATIVE ) -
+ ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+ return context && typeof context.getElementsByTagName !== strundefined && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var hasCompare,
+ doc = node ? node.ownerDocument || node : preferredDoc,
+ parent = doc.defaultView;
+
+ // If no document and documentElement is available, return
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
+
+ // Support tests
+ documentIsHTML = !isXML( doc );
+
+ // Support: IE>8
+ // If iframe document is assigned to "document" variable and if iframe has been reloaded,
+ // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+ // IE6-8 do not support the defaultView property so parent will be undefined
+ if ( parent && parent !== parent.top ) {
+ // IE11 does not have attachEvent, so all must suffer
+ if ( parent.addEventListener ) {
+ parent.addEventListener( "unload", function() {
+ setDocument();
+ }, false );
+ } else if ( parent.attachEvent ) {
+ parent.attachEvent( "onunload", function() {
+ setDocument();
+ });
+ }
+ }
+
+ /* Attributes
+ ---------------------------------------------------------------------- */
+
+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
+ support.attributes = assert(function( div ) {
+ div.className = "i";
+ return !div.getAttribute("className");
+ });
+
+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function( div ) {
+ div.appendChild( doc.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Check if getElementsByClassName can be trusted
+ support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
+ div.innerHTML = "<div class='a'></div><div class='a i'></div>";
+
+ // Support: Safari<4
+ // Catch class over-caching
+ div.firstChild.className = "i";
+ // Support: Opera<10
+ // Catch gEBCN failure to find non-leading classes
+ return div.getElementsByClassName("i").length === 2;
+ });
+
+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function( div ) {
+ docElem.appendChild( div ).id = expando;
+ return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+ });
+
+ // ID find and filter
+ if ( support.getById ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [ m ] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ // Support: IE6/7
+ // getElementById is not reliable as a find shortcut
+ delete Expr.find["ID"];
+
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== strundefined ) {
+ return context.getElementsByTagName( tag );
+ }
+ } :
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See http://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
+
+ if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ div.innerHTML = "<select msallowclip=''><option selected=''></option></select>";
+
+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( div.querySelectorAll("[msallowclip^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+ });
+
+ assert(function( div ) {
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = doc.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ div.appendChild( input ).setAttribute( "name", "D" );
+
+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if ( div.querySelectorAll("[name=d]").length ) {
+ rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+ docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+ /* Contains
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test( docElem.contains ) ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ /* Sorting
+ ---------------------------------------------------------------------- */
+
+ // Document order sorting
+ sortOrder = hasCompare ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if ( compare ) {
+ return compare;
+ }
+
+ // Calculate position if both inputs belong to the same document
+ compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+ a.compareDocumentPosition( b ) :
+
+ // Otherwise we know they are disconnected
+ 1;
+
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ } :
+ function( a, b ) {
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Parentless nodes are either documents or disconnected
+ if ( !aup || !bup ) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ if ( support.matchesSelector && documentIsHTML &&
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
+
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+ fn( elem, name, !documentIsHTML ) :
+ undefined;
+
+ return val !== undefined ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice( 0 );
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem === results[ i ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
+
+ return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ while ( (node = elem[i++]) ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (jQuery #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ attrHandle: {},
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[6] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] ) {
+ match[2] = match[4] || match[5] || "";
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeNameSelector ) {
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function() { return true; } :
+ function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
+ cache = outerCache[ type ] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ // Use previously-cached element index if available
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+ diff = cache[1];
+
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf.call( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifier
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeType < 6 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+
+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( (tokens = []) );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ });
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var oldCache, outerCache,
+ newCache = [ dirruns, doneName ];
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+ if ( (oldCache = outerCache[ dir ]) &&
+ oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[ 2 ] = oldCache[ 2 ]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ outerCache[ dir ] = newCache;
+
+ // A match means we're done; a fail means we have to keep checking
+ if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf.call( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+ ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, outermost ) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+ for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !match ) {
+ match = tokenize( selector );
+ }
+ i = match.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( match[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+ results = results || [];
+
+ // Try to minimize operations if there is no seed and only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ support.getById && context.nodeType === 9 && documentIsHTML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+ if ( !context ) {
+ return results;
+
+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if ( compiled ) {
+ context = context.parentNode;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, seed );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ ( compiled || compile( selector, match ) )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ rsibling.test( selector ) && testContext( context.parentNode ) || context
+ );
+ return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome<14
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+ // Should return 1, but returns 4 (following)
+ return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+ div.innerHTML = "<a href='#'></a>";
+ return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+ }
+ });
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+ div.innerHTML = "<input/>";
+ div.firstChild.setAttribute( "value", "" );
+ return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+ addHandle( "value", function( elem, name, isXML ) {
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+ return elem.defaultValue;
+ }
+ });
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+ return div.getAttribute("disabled") == null;
+}) ) {
+ addHandle( booleans, function( elem, name, isXML ) {
+ var val;
+ if ( !isXML ) {
+ return elem[ name ] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep( elements, function( elem, i ) {
+ /* jshint -W018 */
+ return !!qualifier.call( elem, i, elem ) !== not;
+ });
+
+ }
+
+ if ( qualifier.nodeType ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( elem === qualifier ) !== not;
+ });
+
+ }
+
+ if ( typeof qualifier === "string" ) {
+ if ( risSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ qualifier = jQuery.filter( qualifier, elements );
+ }
+
+ return jQuery.grep( elements, function( elem ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
+ });
+}
+
+jQuery.filter = function( expr, elems, not ) {
+ var elem = elems[ 0 ];
+
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 && elem.nodeType === 1 ?
+ jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+ jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+ return elem.nodeType === 1;
+ }));
+};
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var i,
+ ret = [],
+ self = this,
+ len = self.length;
+
+ if ( typeof selector !== "string" ) {
+ return this.pushStack( jQuery( selector ).filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ }) );
+ }
+
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, self[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = this.selector ? this.selector + " " + selector : selector;
+ return ret;
+ },
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], false) );
+ },
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], true) );
+ },
+ is: function( selector ) {
+ return !!winnow(
+ this,
+
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ typeof selector === "string" && rneedsContext.test( selector ) ?
+ jQuery( selector ) :
+ selector || [],
+ false
+ ).length;
+ }
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ init = jQuery.fn.init = function( selector, context ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+
+ // scripts is true for back-compat
+ // Intentionally let the error be thrown if parseHTML is not present
+ jQuery.merge( this, jQuery.parseHTML(
+ match[1],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return typeof rootjQuery.ready !== "undefined" ?
+ rootjQuery.ready( selector ) :
+ // Execute immediately if ready is not present
+ selector( jQuery );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ };
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.extend({
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+jQuery.fn.extend({
+ has: function( target ) {
+ var i,
+ targets = jQuery( target, this ),
+ len = targets.length;
+
+ return this.filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ matched = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && (pos ?
+ pos.index(cur) > -1 :
+
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector(cur, selectors)) ) {
+
+ matched.push( cur );
+ break;
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ return this.pushStack(
+ jQuery.unique(
+ jQuery.merge( this.get(), jQuery( selector, context ) )
+ )
+ );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+});
+
+function sibling( cur, dir ) {
+ do {
+ cur = cur[ dir ];
+ } while ( cur && cur.nodeType !== 1 );
+
+ return cur;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( name.slice( -5 ) !== "Until" ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ if ( this.length > 1 ) {
+ // Remove duplicates
+ if ( !guaranteedUnique[ name ] ) {
+ ret = jQuery.unique( ret );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+ }
+
+ return this.pushStack( ret );
+ };
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away
+ } else if ( memory ) {
+ firingStart = start;
+ fire( memory );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+ // Handle firing indexes
+ if ( firing ) {
+ if ( index <= firingLength ) {
+ firingLength--;
+ }
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ });
+ }
+ return this;
+ },
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ firingLength = 0;
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( list && ( !fired || stack ) ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ if ( firing ) {
+ stack.push( args );
+ } else {
+ fire( args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+
+
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var tuples = [
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[1] ](function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+ }
+ });
+ });
+ fns = null;
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[1] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(function() {
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ]
+ deferred[ tuple[0] ] = function() {
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+ return this;
+ };
+ deferred[ tuple[0] + "With" ] = list.fireWith;
+ });
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+ if ( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+
+ } else if ( !(--remaining) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject )
+ .progress( updateFunc( i, progressContexts, progressValues ) );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // if we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+});
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+};
+
+jQuery.extend({
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.triggerHandler ) {
+ jQuery( document ).triggerHandler( "ready" );
+ jQuery( document ).off( "ready" );
+ }
+ }
+});
+
+/**
+ * Clean-up method for dom ready events
+ */
+function detach() {
+ if ( document.addEventListener ) {
+ document.removeEventListener( "DOMContentLoaded", completed, false );
+ window.removeEventListener( "load", completed, false );
+
+ } else {
+ document.detachEvent( "onreadystatechange", completed );
+ window.detachEvent( "onload", completed );
+ }
+}
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+ // readyState === "complete" is good enough for us to call the dom ready in oldIE
+ if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+ detach();
+ jQuery.ready();
+ }
+}
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ setTimeout( jQuery.ready );
+
+ // Standards-based browsers support DOMContentLoaded
+ } else if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed, false );
+
+ // If IE event model is used
+ } else {
+ // Ensure firing before onload, maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", completed );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", completed );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var top = false;
+
+ try {
+ top = window.frameElement == null && document.documentElement;
+ } catch(e) {}
+
+ if ( top && top.doScroll ) {
+ (function doScrollCheck() {
+ if ( !jQuery.isReady ) {
+
+ try {
+ // Use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ top.doScroll("left");
+ } catch(e) {
+ return setTimeout( doScrollCheck, 50 );
+ }
+
+ // detach all dom ready events
+ detach();
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+ })();
+ }
+ }
+ }
+ return readyList.promise( obj );
+};
+
+
+var strundefined = typeof undefined;
+
+
+
+// Support: IE<9
+// Iteration over object's inherited properties before its own
+var i;
+for ( i in jQuery( support ) ) {
+ break;
+}
+support.ownLast = i !== "0";
+
+// Note: most support tests are defined in their respective modules.
+// false until the test is run
+support.inlineBlockNeedsLayout = false;
+
+// Execute ASAP in case we need to set body.style.zoom
+jQuery(function() {
+ // Minified: var a,b,c,d
+ var val, div, body, container;
+
+ body = document.getElementsByTagName( "body" )[ 0 ];
+ if ( !body || !body.style ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ // Setup
+ div = document.createElement( "div" );
+ container = document.createElement( "div" );
+ container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+ body.appendChild( container ).appendChild( div );
+
+ if ( typeof div.style.zoom !== strundefined ) {
+ // Support: IE<8
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
+
+ support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
+ if ( val ) {
+ // Prevent IE 6 from affecting layout for positioned elements #11048
+ // Prevent IE from shrinking the body in IE 7 mode #12869
+ // Support: IE<8
+ body.style.zoom = 1;
+ }
+ }
+
+ body.removeChild( container );
+});
+
+
+
+
+(function() {
+ var div = document.createElement( "div" );
+
+ // Execute the test only if not already executed in another module.
+ if (support.deleteExpando == null) {
+ // Support: IE<9
+ support.deleteExpando = true;
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+ }
+
+ // Null elements to avoid leaks in IE.
+ div = null;
+})();
+
+
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( elem ) {
+ var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
+ nodeType = +elem.nodeType || 1;
+
+ // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
+ return nodeType !== 1 && nodeType !== 9 ?
+ false :
+
+ // Nodes accept data unless otherwise specified; rejection can be conditional
+ !noData || noData !== true && elem.getAttribute("classid") === noData;
+};
+
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ var name;
+ for ( name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var ret, thisCache,
+ internalKey = jQuery.expando,
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ // Avoid exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( typeof name === "string" ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, i,
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split(" ");
+ }
+ }
+ } else {
+ // If "name" is an array of keys...
+ // When data is initially created, via ("key", "val") signature,
+ // keys will be converted to camelCase.
+ // Since there is no way to tell _how_ a key was added, remove
+ // both plain key and camelCase key. #12786
+ // This will only penalize the array argument path.
+ name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+ }
+
+ i = name.length;
+ while ( i-- ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
+ return;
+ }
+ }
+
+ // Destroy the cache
+ if ( isNode ) {
+ jQuery.cleanData( [ elem ], true );
+
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+ /* jshint eqeqeq: false */
+ } else if ( support.deleteExpando || cache != cache.window ) {
+ /* jshint eqeqeq: true */
+ delete cache[ id ];
+
+ // When all else fails, null
+ } else {
+ cache[ id ] = null;
+ }
+}
+
+jQuery.extend({
+ cache: {},
+
+ // The following elements (space-suffixed to avoid Object.prototype collisions)
+ // throw uncatchable exceptions if you attempt to set expando properties
+ noData: {
+ "applet ": true,
+ "embed ": true,
+ // ...but Flash objects (which have this classid) *can* handle expandos
+ "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return internalData( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ return internalRemoveData( elem, name );
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return internalData( elem, name, data, true );
+ },
+
+ _removeData: function( elem, name ) {
+ return internalRemoveData( elem, name, true );
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var i, name, data,
+ elem = this[0],
+ attrs = elem && elem.attributes;
+
+ // Special expections of .data basically thwart jQuery.access,
+ // so implement the relevant behavior ourselves
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ i = attrs.length;
+ while ( i-- ) {
+
+ // Support: IE11+
+ // The attrs elements can be null (#14894)
+ if ( attrs[ i ] ) {
+ name = attrs[ i ].name;
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.slice(5) );
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ return arguments.length > 1 ?
+
+ // Sets one value
+ this.each(function() {
+ jQuery.data( this, key, value );
+ }) :
+
+ // Gets one value
+ // Try to fetch any internally stored data first
+ elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray(data) ) {
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+ empty: jQuery.Callbacks("once memory").add(function() {
+ jQuery._removeData( elem, type + "queue" );
+ jQuery._removeData( elem, key );
+ })
+ });
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while ( i-- ) {
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+});
+var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+ // isHidden might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+ };
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ length = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < length; i++ ) {
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+};
+var rcheckableType = (/^(?:checkbox|radio)$/i);
+
+
+
+(function() {
+ // Minified: var a,b,c
+ var input = document.createElement( "input" ),
+ div = document.createElement( "div" ),
+ fragment = document.createDocumentFragment();
+
+ // Setup
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+ // IE strips leading whitespace when .innerHTML is used
+ support.leadingWhitespace = div.firstChild.nodeType === 3;
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ support.tbody = !div.getElementsByTagName( "tbody" ).length;
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ support.html5Clone =
+ document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ input.type = "checkbox";
+ input.checked = true;
+ fragment.appendChild( input );
+ support.appendChecked = input.checked;
+
+ // Make sure textarea (and checkbox) defaultValue is properly cloned
+ // Support: IE6-IE11+
+ div.innerHTML = "<textarea>x</textarea>";
+ support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ fragment.appendChild( div );
+ div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
+
+ // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
+ // old WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE<9
+ // Opera does not clone events (and typeof div.attachEvent === undefined).
+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+ support.noCloneEvent = true;
+ if ( div.attachEvent ) {
+ div.attachEvent( "onclick", function() {
+ support.noCloneEvent = false;
+ });
+
+ div.cloneNode( true ).click();
+ }
+
+ // Execute the test only if not already executed in another module.
+ if (support.deleteExpando == null) {
+ // Support: IE<9
+ support.deleteExpando = true;
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+ }
+})();
+
+
+(function() {
+ var i, eventName,
+ div = document.createElement( "div" );
+
+ // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
+ for ( i in { submit: true, change: true, focusin: true }) {
+ eventName = "on" + i;
+
+ if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
+ div.setAttribute( eventName, "t" );
+ support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
+ }
+ }
+
+ // Null elements to avoid leaks in IE.
+ div = null;
+})();
+
+
+var rformElems = /^(?:input|select|textarea)$/i,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch ( err ) { }
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+ var tmp, events, t, handleObjIn,
+ special, eventHandle, handleObj,
+ handlers, type, namespaces, origType,
+ elemData = jQuery._data( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !(events = elemData.events) ) {
+ events = elemData.events = {};
+ }
+ if ( !(eventHandle = elemData.handle) ) {
+ eventHandle = elemData.handle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // There *must* be a type, no attaching namespace-only handlers
+ if ( !type ) {
+ continue;
+ }
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !(handlers = events[ type ]) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+ var j, handleObj, tmp,
+ origCount, t, events,
+ special, handlers, type,
+ namespaces, origType,
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ delete elemData.handle;
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery._removeData( elem, "events" );
+ }
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ var handle, ontype, cur,
+ bubbleType, special, tmp, i,
+ eventPath = [ elem || document ],
+ type = hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf(".") >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf(":") < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+ event.isTrigger = onlyHandlers ? 2 : 3;
+ event.namespace = namespaces.join(".");
+ event.namespace_re = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === (elem.ownerDocument || document) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
+ event.result = handle.apply( cur, data );
+ if ( event.result === false ) {
+ event.preventDefault();
+ }
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+ jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ try {
+ elem[ type ]();
+ } catch ( e ) {
+ // IE<9 dies on focus/blur to hidden element (#1486,#12518)
+ // only reproducible on winXP IE8 native, not IE9 in IE8 mode
+ }
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event );
+
+ var i, ret, handleObj, matched, j,
+ handlerQueue = [],
+ args = slice.call( arguments ),
+ handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( (event.result = ret) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var sel, handleObj, matches, i,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ // Black-hole SVG <use> instance trees (#13180)
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+ /* jshint eqeqeq: false */
+ for ( ; cur != this; cur = cur.parentNode || this ) {
+ /* jshint eqeqeq: true */
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matches[ sel ] === undefined ) {
+ matches[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) >= 0 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matches[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, handlers: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+ }
+
+ return handlerQueue;
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop, copy,
+ type = event.type,
+ originalEvent = event,
+ fixHook = this.fixHooks[ type ];
+
+ if ( !fixHook ) {
+ this.fixHooks[ type ] = fixHook =
+ rmouseEvent.test( type ) ? this.mouseHooks :
+ rkeyEvent.test( type ) ? this.keyHooks :
+ {};
+ }
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = new jQuery.Event( originalEvent );
+
+ i = copy.length;
+ while ( i-- ) {
+ prop = copy[ i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Support: IE<9
+ // Fix target property (#1925)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Support: Chrome 23+, Safari?
+ // Target should not be a text node (#504, #13143)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // Support: IE<9
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+ event.metaKey = !!event.metaKey;
+
+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var body, eventDoc, doc,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ special: {
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ focus: {
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== safeActiveElement() && this.focus ) {
+ try {
+ this.focus();
+ return false;
+ } catch ( e ) {
+ // Support: IE<9
+ // If we error on focus to hidden element (#1486, #12518),
+ // let .trigger() run the handlers
+ }
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === safeActiveElement() && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+ click: {
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+ this.click();
+ return false;
+ }
+ },
+
+ // For cross-browser consistency, don't fire native .click() on links
+ _default: function( event ) {
+ return jQuery.nodeName( event.target, "a" );
+ }
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Support: Firefox 20+
+ // Firefox doesn't alert if the returnValue field is not set.
+ if ( event.result !== undefined && event.originalEvent ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ {
+ type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ var name = "on" + type;
+
+ if ( elem.detachEvent ) {
+
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
+ if ( typeof elem[ name ] === strundefined ) {
+ elem[ name ] = null;
+ }
+
+ elem.detachEvent( name, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = src.defaultPrevented ||
+ src.defaultPrevented === undefined &&
+ // Support: IE < 9, Android < 4.0
+ src.returnValue === false ?
+ returnTrue :
+ returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+ if ( !e ) {
+ return;
+ }
+
+ // If preventDefault exists, run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // Support: IE
+ // Otherwise set the returnValue property of the original event to false
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+ if ( !e ) {
+ return;
+ }
+ // If stopPropagation exists, run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+
+ // Support: IE
+ // Set the cancelBubble property of the original event to true
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ var e = this.originalEvent;
+
+ this.isImmediatePropagationStopped = returnTrue;
+
+ if ( e && e.stopImmediatePropagation ) {
+ e.stopImmediatePropagation();
+ }
+
+ this.stopPropagation();
+ }
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout",
+ pointerenter: "pointerover",
+ pointerleave: "pointerout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ event._submit_bubble = true;
+ });
+ jQuery._data( form, "submitBubbles", true );
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ postDispatch: function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( event._submit_bubble ) {
+ delete event._submit_bubble;
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ }
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ }
+ // Allow triggered, simulated change events (#11500)
+ jQuery.event.simulate( "change", this, event, true );
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ jQuery._data( elem, "changeBubbles", true );
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return !rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler on the document while someone wants focusin/focusout
+ var handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ var doc = this.ownerDocument || this,
+ attaches = jQuery._data( doc, fix );
+
+ if ( !attaches ) {
+ doc.addEventListener( orig, handler, true );
+ }
+ jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
+ },
+ teardown: function() {
+ var doc = this.ownerDocument || this,
+ attaches = jQuery._data( doc, fix ) - 1;
+
+ if ( !attaches ) {
+ doc.removeEventListener( orig, handler, true );
+ jQuery._removeData( doc, fix );
+ } else {
+ jQuery._data( doc, fix, attaches );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var type, origFn;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[0];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+});
+
+
+function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style|link)/i,
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /^$|\/(?:java|ecma)script/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+ // We have to close these tags to support XHTML (#13200)
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ area: [ 1, "<map>", "</map>" ],
+ param: [ 1, "<object>", "</object>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+ // unless wrapped in a div with non-breaking characters in front of it.
+ _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
+ },
+ safeFragment = createSafeFragment( document ),
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+function getAll( context, tag ) {
+ var elems, elem,
+ i = 0,
+ found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
+ undefined;
+
+ if ( !found ) {
+ for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+ if ( !tag || jQuery.nodeName( elem, tag ) ) {
+ found.push( elem );
+ } else {
+ jQuery.merge( found, getAll( elem, tag ) );
+ }
+ }
+ }
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], found ) :
+ found;
+}
+
+// Used in buildFragment, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( rcheckableType.test( elem.type ) ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+
+// Support: IE<8
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+ return jQuery.nodeName( elem, "table" ) &&
+ jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
+
+ elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
+ elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+ elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
+ return elem;
+}
+function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+ if ( match ) {
+ elem.type = match[1];
+ } else {
+ elem.removeAttribute("type");
+ }
+ return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var elem,
+ i = 0;
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+ }
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function fixCloneNodeIssues( src, dest ) {
+ var nodeName, e, data;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 copies events bound via attachEvent when using cloneNode.
+ if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
+ data = jQuery._data( dest );
+
+ for ( e in data.events ) {
+ jQuery.removeEvent( dest, e, data.handle );
+ }
+
+ // Event data gets referenced instead of copied if the expando gets copied too
+ dest.removeAttribute( jQuery.expando );
+ }
+
+ // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+ if ( nodeName === "script" && dest.text !== src.text ) {
+ disableScript( dest ).text = src.text;
+ restoreScript( dest );
+
+ // IE6-10 improperly clones children of object elements using classid.
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
+ } else if ( nodeName === "object" ) {
+ if ( dest.parentNode ) {
+ dest.outerHTML = src.outerHTML;
+ }
+
+ // This path appears unavoidable for IE9. When cloning an object
+ // element in IE9, the outerHTML strategy above is not sufficient.
+ // If the src has innerHTML and the destination does not,
+ // copy the src.innerHTML into the dest.innerHTML. #10324
+ if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+ dest.innerHTML = src.innerHTML;
+ }
+
+ } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+
+ dest.defaultChecked = dest.checked = src.checked;
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.defaultSelected = dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var destElements, node, clone, i, srcElements,
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+ clone = elem.cloneNode( true );
+
+ // IE<=8 does not properly clone detached, unknown element nodes
+ } else {
+ fragmentDiv.innerHTML = elem.outerHTML;
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+ }
+
+ if ( (!support.noCloneEvent || !support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ // Fix all IE cloning issues
+ for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ fixCloneNodeIssues( node, destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+ cloneCopyEvent( node, destElements[i] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ destElements = srcElements = node = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ buildFragment: function( elems, context, scripts, selection ) {
+ var j, elem, contains,
+ tmp, tag, tbody, wrap,
+ l = elems.length,
+
+ // Ensure a safe fragment
+ safe = createSafeFragment( context ),
+
+ nodes = [],
+ i = 0;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || safe.appendChild( context.createElement("div") );
+
+ // Deserialize a standard representation
+ tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+
+ tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
+
+ // Descend through wrappers to the right content
+ j = wrap[0];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Manually add leading whitespace removed by IE
+ if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ elem = tag === "table" && !rtbody.test( elem ) ?
+ tmp.firstChild :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !rtbody.test( elem ) ?
+ tmp :
+ 0;
+
+ j = elem && elem.childNodes.length;
+ while ( j-- ) {
+ if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+ elem.removeChild( tbody );
+ }
+ }
+ }
+
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Fix #12392 for WebKit and IE > 9
+ tmp.textContent = "";
+
+ // Fix #12392 for oldIE
+ while ( tmp.firstChild ) {
+ tmp.removeChild( tmp.firstChild );
+ }
+
+ // Remember the top-level container for proper cleanup
+ tmp = safe.lastChild;
+ }
+ }
+ }
+
+ // Fix #11356: Clear elements from fragment
+ if ( tmp ) {
+ safe.removeChild( tmp );
+ }
+
+ // Reset defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ if ( !support.appendChecked ) {
+ jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+ }
+
+ i = 0;
+ while ( (elem = nodes[ i++ ]) ) {
+
+ // #4087 - If origin and destination elements are the same, and this is
+ // that element, do not do anything
+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( safe.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( (elem = tmp[ j++ ]) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ tmp = null;
+
+ return safe;
+ },
+
+ cleanData: function( elems, /* internal */ acceptData ) {
+ var elem, type, id, data,
+ i = 0,
+ internalKey = jQuery.expando,
+ cache = jQuery.cache,
+ deleteExpando = support.deleteExpando,
+ special = jQuery.event.special;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ if ( acceptData || jQuery.acceptData( elem ) ) {
+
+ id = elem[ internalKey ];
+ data = id && cache[ id ];
+
+ if ( data ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Remove cache only if it was not already removed by jQuery.event.remove
+ if ( cache[ id ] ) {
+
+ delete cache[ id ];
+
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( deleteExpando ) {
+ delete elem[ internalKey ];
+
+ } else if ( typeof elem.removeAttribute !== strundefined ) {
+ elem.removeAttribute( internalKey );
+
+ } else {
+ elem[ internalKey ] = null;
+ }
+
+ deletedIds.push( id );
+ }
+ }
+ }
+ }
+ }
+});
+
+jQuery.fn.extend({
+ text: function( value ) {
+ return access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
+
+ append: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.insertBefore( elem, target.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ });
+ },
+
+ after: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ });
+ },
+
+ remove: function( selector, keepData /* Internal Use Only */ ) {
+ var elem,
+ elems = selector ? jQuery.filter( selector, this ) : this,
+ i = 0;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem ) );
+ }
+
+ if ( elem.parentNode ) {
+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+ setGlobalEval( getAll( elem, "script" ) );
+ }
+ elem.parentNode.removeChild( elem );
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+
+ // If this is a select, ensure that it displays empty (#12336)
+ // Support: IE<9
+ if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+ elem.options.length = 0;
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map(function() {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ return access( this, function( value ) {
+ var elem = this[ 0 ] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined ) {
+ return elem.nodeType === 1 ?
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
+ undefined;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ ( support.htmlSerialize || !rnoshimcache.test( value ) ) &&
+ ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+ !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
+
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+ try {
+ for (; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ elem = this[i] || {};
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function() {
+ var arg = arguments[ 0 ];
+
+ // Make the changes, replacing each context element with the new content
+ this.domManip( arguments, function( elem ) {
+ arg = this.parentNode;
+
+ jQuery.cleanData( getAll( this ) );
+
+ if ( arg ) {
+ arg.replaceChild( elem, this );
+ }
+ });
+
+ // Force removal if there was no new content (e.g., from empty arguments)
+ return arg && (arg.length || arg.nodeType) ? this : this.remove();
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, callback ) {
+
+ // Flatten any nested arrays
+ args = concat.apply( [], args );
+
+ var first, node, hasScripts,
+ scripts, doc, fragment,
+ i = 0,
+ l = this.length,
+ set = this,
+ iNoClone = l - 1,
+ value = args[0],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction ||
+ ( l > 1 && typeof value === "string" &&
+ !support.checkClone && rchecked.test( value ) ) ) {
+ return this.each(function( index ) {
+ var self = set.eq( index );
+ if ( isFunction ) {
+ args[0] = value.call( this, index, self.html() );
+ }
+ self.domManip( args, callback );
+ });
+ }
+
+ if ( l ) {
+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ if ( first ) {
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call( this[i], node, i );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+ // Optional AJAX dependency, but won't run scripts if not present
+ if ( jQuery._evalUrl ) {
+ jQuery._evalUrl( node.src );
+ }
+ } else {
+ jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+ }
+ }
+ }
+ }
+
+ // Fix #11809: Avoid leaking memory
+ fragment = first = null;
+ }
+ }
+
+ return this;
+ }
+});
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ i = 0,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone(true);
+ jQuery( insert[i] )[ original ]( elems );
+
+ // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+ push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+});
+
+
+var iframe,
+ elemdisplay = {};
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+ var style,
+ elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+ // getDefaultComputedStyle might be reliably used only on attached element
+ display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
+
+ // Use of this method is a temporary fix (more like optmization) until something better comes along,
+ // since it was removed from specification and supported only in FF
+ style.display : jQuery.css( elem[ 0 ], "display" );
+
+ // We don't have any data stored on the element,
+ // so use "detach" method as fast way to get rid of the element
+ elem.detach();
+
+ return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+ var doc = document,
+ display = elemdisplay[ nodeName ];
+
+ if ( !display ) {
+ display = actualDisplay( nodeName, doc );
+
+ // If the simple way fails, read from inside an iframe
+ if ( display === "none" || !display ) {
+
+ // Use the already-created iframe if possible
+ iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
+
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+ doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
+
+ // Support: IE
+ doc.write();
+ doc.close();
+
+ display = actualDisplay( nodeName, doc );
+ iframe.detach();
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return display;
+}
+
+
+(function() {
+ var shrinkWrapBlocksVal;
+
+ support.shrinkWrapBlocks = function() {
+ if ( shrinkWrapBlocksVal != null ) {
+ return shrinkWrapBlocksVal;
+ }
+
+ // Will be changed later if needed.
+ shrinkWrapBlocksVal = false;
+
+ // Minified: var b,c,d
+ var div, body, container;
+
+ body = document.getElementsByTagName( "body" )[ 0 ];
+ if ( !body || !body.style ) {
+ // Test fired too early or in an unsupported environment, exit.
+ return;
+ }
+
+ // Setup
+ div = document.createElement( "div" );
+ container = document.createElement( "div" );
+ container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+ body.appendChild( container ).appendChild( div );
+
+ // Support: IE6
+ // Check if elements with layout shrink-wrap their children
+ if ( typeof div.style.zoom !== strundefined ) {
+ // Reset CSS: box-sizing; display; margin; border
+ div.style.cssText =
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+ "box-sizing:content-box;display:block;margin:0;border:0;" +
+ "padding:1px;width:1px;zoom:1";
+ div.appendChild( document.createElement( "div" ) ).style.width = "5px";
+ shrinkWrapBlocksVal = div.offsetWidth !== 3;
+ }
+
+ body.removeChild( container );
+
+ return shrinkWrapBlocksVal;
+ };
+
+})();
+var rmargin = (/^margin/);
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+
+
+var getStyles, curCSS,
+ rposition = /^(top|right|bottom|left)$/;
+
+if ( window.getComputedStyle ) {
+ getStyles = function( elem ) {
+ return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
+ };
+
+ curCSS = function( elem, name, computed ) {
+ var width, minWidth, maxWidth, ret,
+ style = elem.style;
+
+ computed = computed || getStyles( elem );
+
+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
+
+ if ( computed ) {
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ // Support: IE
+ // IE returns zIndex value as an integer.
+ return ret === undefined ?
+ ret :
+ ret + "";
+ };
+} else if ( document.documentElement.currentStyle ) {
+ getStyles = function( elem ) {
+ return elem.currentStyle;
+ };
+
+ curCSS = function( elem, name, computed ) {
+ var left, rs, rsLeft, ret,
+ style = elem.style;
+
+ computed = computed || getStyles( elem );
+ ret = computed ? computed[ name ] : undefined;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret == null && style && style[ name ] ) {
+ ret = style[ name ];
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ // but not position css attributes, as those are proportional to the parent element instead
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rs = elem.runtimeStyle;
+ rsLeft = rs && rs.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ rs.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ret;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ rs.left = rsLeft;
+ }
+ }
+
+ // Support: IE
+ // IE returns zIndex value as an integer.
+ return ret === undefined ?
+ ret :
+ ret + "" || "auto";
+ };
+}
+
+
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+ // Define the hook, we'll check on the first run if it's really needed.
+ return {
+ get: function() {
+ var condition = conditionFn();
+
+ if ( condition == null ) {
+ // The test was not ready at this point; screw the hook this time
+ // but check again when needed next time.
+ return;
+ }
+
+ if ( condition ) {
+ // Hook not needed (or it's not possible to use it due to missing dependency),
+ // remove it.
+ // Since there are no other hooks for marginRight, remove the whole object.
+ delete this.get;
+ return;
+ }
+
+ // Hook needed; redefine it so that the support test is not executed again.
+
+ return (this.get = hookFn).apply( this, arguments );
+ }
+ };
+}
+
+
+(function() {
+ // Minified: var b,c,d,e,f,g, h,i
+ var div, style, a, pixelPositionVal, boxSizingReliableVal,
+ reliableHiddenOffsetsVal, reliableMarginRightVal;
+
+ // Setup
+ div = document.createElement( "div" );
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+ a = div.getElementsByTagName( "a" )[ 0 ];
+ style = a && a.style;
+
+ // Finish early in limited (non-browser) environments
+ if ( !style ) {
+ return;
+ }
+
+ style.cssText = "float:left;opacity:.5";
+
+ // Support: IE<9
+ // Make sure that element opacity exists (as opposed to filter)
+ support.opacity = style.opacity === "0.5";
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ support.cssFloat = !!style.cssFloat;
+
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
+ style.WebkitBoxSizing === "";
+
+ jQuery.extend(support, {
+ reliableHiddenOffsets: function() {
+ if ( reliableHiddenOffsetsVal == null ) {
+ computeStyleTests();
+ }
+ return reliableHiddenOffsetsVal;
+ },
+
+ boxSizingReliable: function() {
+ if ( boxSizingReliableVal == null ) {
+ computeStyleTests();
+ }
+ return boxSizingReliableVal;
+ },
+
+ pixelPosition: function() {
+ if ( pixelPositionVal == null ) {
+ computeStyleTests();
+ }
+ return pixelPositionVal;
+ },
+
+ // Support: Android 2.3
+ reliableMarginRight: function() {
+ if ( reliableMarginRightVal == null ) {
+ computeStyleTests();
+ }
+ return reliableMarginRightVal;
+ }
+ });
+
+ function computeStyleTests() {
+ // Minified: var b,c,d,j
+ var div, body, container, contents;
+
+ body = document.getElementsByTagName( "body" )[ 0 ];
+ if ( !body || !body.style ) {
+ // Test fired too early or in an unsupported environment, exit.
+ return;
+ }
+
+ // Setup
+ div = document.createElement( "div" );
+ container = document.createElement( "div" );
+ container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+ body.appendChild( container ).appendChild( div );
+
+ div.style.cssText =
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
+ "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
+ "border:1px;padding:1px;width:4px;position:absolute";
+
+ // Support: IE<9
+ // Assume reasonable values in the absence of getComputedStyle
+ pixelPositionVal = boxSizingReliableVal = false;
+ reliableMarginRightVal = true;
+
+ // Check for getComputedStyle so that this code is not run in IE<9.
+ if ( window.getComputedStyle ) {
+ pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+ boxSizingReliableVal =
+ ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+ // Support: Android 2.3
+ // Div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container (#3333)
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ contents = div.appendChild( document.createElement( "div" ) );
+
+ // Reset CSS: box-sizing; display; margin; border; padding
+ contents.style.cssText = div.style.cssText =
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+ "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
+ contents.style.marginRight = contents.style.width = "0";
+ div.style.width = "1px";
+
+ reliableMarginRightVal =
+ !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
+ }
+
+ // Support: IE8
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+ contents = div.getElementsByTagName( "td" );
+ contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
+ reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+ if ( reliableHiddenOffsetsVal ) {
+ contents[ 0 ].style.display = "";
+ contents[ 1 ].style.display = "none";
+ reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+ }
+
+ body.removeChild( container );
+ }
+
+})();
+
+
+// A method for quickly swapping in/out CSS properties to get correct calculations.
+jQuery.swap = function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+};
+
+
+var
+ ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity\s*=\s*([^)]*)/,
+
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
+ rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: "0",
+ fontWeight: "400"
+ },
+
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+ // shortcut for names that are not vendor prefixed
+ if ( name in style ) {
+ return name;
+ }
+
+ // check for vendor prefixed names
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
+ origName = name,
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in style ) {
+ return name;
+ }
+ }
+
+ return origName;
+}
+
+function showHide( elements, show ) {
+ var display, elem, hidden,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ values[ index ] = jQuery._data( elem, "olddisplay" );
+ display = elem.style.display;
+ if ( show ) {
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !values[ index ] && display === "none" ) {
+ elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( elem.style.display === "" && isHidden( elem ) ) {
+ values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+ }
+ } else {
+ hidden = isHidden( elem );
+
+ if ( display && display !== "none" || !hidden ) {
+ jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( index = 0; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+ elem.style.display = show ? values[ index ] || "" : "none";
+ }
+ }
+
+ return elements;
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+ var matches = rnumsplit.exec( value );
+ return matches ?
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+ // both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+ // at this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles( elem ),
+ isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, styles );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+}
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Don't automatically add "px" to these possibly-unitless properties
+ cssNumber: {
+ "columnCount": true,
+ "fillOpacity": true,
+ "flexGrow": true,
+ "flexShrink": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "order": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that null and NaN values aren't set. See: #7116
+ if ( value == null || value !== value ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+ // but it would mean to define eight (for every problematic property) identical functions
+ if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+ // Support: IE
+ // Swallow errors from 'invalid' CSS values (#5509)
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var num, val, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ //convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+ }
+ return val;
+ }
+});
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ // certain elements can have dimension info if we invisibly show them
+ // however, it must have a current display style that would benefit from this
+ return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
+ jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ }) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var styles = extra && getStyles( elem );
+ return setPositiveNumber( elem, value, extra ?
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ ) : 0
+ );
+ }
+ };
+});
+
+if ( !support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ // if value === "", then remove inline opacity #12685
+ if ( ( value >= 1 || value === "" ) &&
+ jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+ style.removeAttribute ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there is no filter style applied in a css rule or unset inline opacity, we are done
+ if ( value === "" || currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+ function( elem, computed ) {
+ if ( computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" },
+ curCSS, [ elem, "marginRight" ] );
+ }
+ }
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+});
+
+jQuery.fn.extend({
+ css: function( name, value ) {
+ return access( this, function( elem, name, value ) {
+ var styles, len,
+ map = {},
+ i = 0;
+
+ if ( jQuery.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ },
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ if ( typeof state === "boolean" ) {
+ return state ? this.show() : this.hide();
+ }
+
+ return this.each(function() {
+ if ( isHidden( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ });
+ }
+});
+
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || "swing";
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ if ( tween.elem[ tween.prop ] != null &&
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails
+ // so, simple values such as "10px" are parsed to Float.
+ // complex values such as "rotate(1rad)" are returned as is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+ // use step hook for back compat - use cssHook if its there - use .style if its
+ // available and use plain properties where available
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Support: IE <=9
+// Panic based approach to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p * Math.PI ) / 2;
+ }
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+ fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
+ rrun = /queueHooks$/,
+ animationPrefilters = [ defaultPrefilter ],
+ tweeners = {
+ "*": [ function( prop, value ) {
+ var tween = this.createTween( prop, value ),
+ target = tween.cur(),
+ parts = rfxnum.exec( value ),
+ unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+ rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+ scale = 1,
+ maxIterations = 20;
+
+ if ( start && start[ 3 ] !== unit ) {
+ // Trust units reported by jQuery.css
+ unit = unit || start[ 3 ];
+
+ // Make sure we update the tween properties later on
+ parts = parts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ start = +target || 1;
+
+ do {
+ // If previous iteration zeroed out, double until we get *something*
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ start = start / scale;
+ jQuery.style( tween.elem, prop, start + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+ }
+
+ // Update tween properties
+ if ( parts ) {
+ start = tween.start = +start || +target || 0;
+ tween.unit = unit;
+ // If a +=/-= token was provided, we're doing a relative animation
+ tween.end = parts[ 1 ] ?
+ start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+ +parts[ 2 ];
+ }
+
+ return tween;
+ } ]
+ };
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout(function() {
+ fxNow = undefined;
+ });
+ return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ attrs = { height: type },
+ i = 0;
+
+ // if we include width, step value is 1 to do all cssExpand values,
+ // if we don't include width, step value is 2 to skip over Left and Right
+ includeWidth = includeWidth ? 1 : 0;
+ for ( ; i < 4 ; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+function createTween( value, prop, animation ) {
+ var tween,
+ collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+
+ // we're done with this property
+ return tween;
+ }
+ }
+}
+
+function defaultPrefilter( elem, props, opts ) {
+ /* jshint validthis: true */
+ var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+ anim = this,
+ orig = {},
+ style = elem.style,
+ hidden = elem.nodeType && isHidden( elem ),
+ dataShow = jQuery._data( elem, "fxshow" );
+
+ // handle queue: false promises
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always(function() {
+ // doing this makes sure that the complete handler will be called
+ // before this completes
+ anim.always(function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ });
+ });
+ }
+
+ // height/width overflow pass
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ display = jQuery.css( elem, "display" );
+
+ // Test default display if display is currently "none"
+ checkDisplay = display === "none" ?
+ jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+ if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
+ style.display = "inline-block";
+ } else {
+ style.zoom = 1;
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ if ( !support.shrinkWrapBlocks() ) {
+ anim.always(function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ });
+ }
+ }
+
+ // show/hide pass
+ for ( prop in props ) {
+ value = props[ prop ];
+ if ( rfxtypes.exec( value ) ) {
+ delete props[ prop ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+
+ // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+ if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+ hidden = true;
+ } else {
+ continue;
+ }
+ }
+ orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+
+ // Any non-fx value stops us from restoring the original display value
+ } else {
+ display = undefined;
+ }
+ }
+
+ if ( !jQuery.isEmptyObject( orig ) ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+ } else {
+ dataShow = jQuery._data( elem, "fxshow", {} );
+ }
+
+ // store state if its toggle - enables .stop().toggle() to "reverse"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+ if ( hidden ) {
+ jQuery( elem ).show();
+ } else {
+ anim.done(function() {
+ jQuery( elem ).hide();
+ });
+ }
+ anim.done(function() {
+ var prop;
+ jQuery._removeData( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ });
+ for ( prop in orig ) {
+ tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = tween.start;
+ if ( hidden ) {
+ tween.end = tween.start;
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+ }
+
+ // If this is a noop like .hide().hide(), restore an overwritten display value
+ } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
+ style.display = display;
+ }
+}
+
+function propFilter( props, specialEasing ) {
+ var index, name, easing, value, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'index' from above because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = animationPrefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+ // don't match elem in the :animated selector
+ delete tick.elem;
+ }),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise({
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+ // if we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // resolve when we played the last frame
+ // otherwise, reject
+ if ( gotoEnd ) {
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ }),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length ; index++ ) {
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ return result;
+ }
+ }
+
+ jQuery.map( props, createTween, animation );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ })
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.split(" ");
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ tweeners[ prop ] = tweeners[ prop ] || [];
+ tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ animationPrefilters.unshift( callback );
+ } else {
+ animationPrefilters.push( callback );
+ }
+ }
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.fn.extend({
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // show any hidden elements after setting opacity to 0
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+ // animate to the value specified
+ .end().animate({ opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+ // Empty animations, or finishing resolves immediately
+ if ( empty || jQuery._data( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each(function() {
+ var index,
+ data = jQuery._data( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // enable finishing flag on private data
+ data.finish = true;
+
+ // empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.stop ) {
+ hooks.stop.call( this, true );
+ }
+
+ // look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // turn off finishing flag
+ delete data.finish;
+ });
+ }
+});
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show"),
+ slideUp: genFx("hide"),
+ slideToggle: genFx("toggle"),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ jQuery.timers.push( timer );
+ if ( timer() ) {
+ jQuery.fx.start();
+ } else {
+ jQuery.timers.pop();
+ }
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+};
+
+jQuery.fx.stop = function() {
+ clearInterval( timerId );
+ timerId = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+};
+
+
+(function() {
+ // Minified: var a,b,c,d,e
+ var input, div, select, a, opt;
+
+ // Setup
+ div = document.createElement( "div" );
+ div.setAttribute( "className", "t" );
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+ a = div.getElementsByTagName("a")[ 0 ];
+
+ // First batch of tests.
+ select = document.createElement("select");
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName("input")[ 0 ];
+
+ a.style.cssText = "top:1px";
+
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ support.getSetAttribute = div.className !== "t";
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ support.style = /top/.test( a.getAttribute("style") );
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ support.hrefNormalized = a.getAttribute("href") === "/a";
+
+ // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+ support.checkOn = !!input.value;
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ support.optSelected = opt.selected;
+
+ // Tests for enctype support on a form (#6743)
+ support.enctype = !!document.createElement("form").enctype;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Support: IE8 only
+ // Check if we can trust getAttribute("value")
+ input = document.createElement( "input" );
+ input.setAttribute( "value", "" );
+ support.input = input.getAttribute( "value" ) === "";
+
+ // Check if an input maintains its value after becoming a radio
+ input.value = "t";
+ input.setAttribute( "type", "radio" );
+ support.radioValue = input.value === "t";
+})();
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend({
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, jQuery( this ).val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map( val, function( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ var val = jQuery.find.attr( elem, "value" );
+ return val != null ?
+ val :
+ // Support: IE10-11+
+ // option.text throws exceptions (#14686, #14858)
+ jQuery.trim( jQuery.text( elem ) );
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one" || index < 0,
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // oldIE doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+ // Don't return options that are disabled or in a disabled optgroup
+ ( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+ ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var optionSet, option,
+ options = elem.options,
+ values = jQuery.makeArray( value ),
+ i = options.length;
+
+ while ( i-- ) {
+ option = options[ i ];
+
+ if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
+
+ // Support: IE6
+ // When new option element is added to select box we need to
+ // force reflow of newly added node in order to workaround delay
+ // of initialization properties
+ try {
+ option.selected = optionSet = true;
+
+ } catch ( _ ) {
+
+ // Will be executed only in IE6
+ option.scrollHeight;
+ }
+
+ } else {
+ option.selected = false;
+ }
+ }
+
+ // Force browsers to behave consistently when non-matching value is set
+ if ( !optionSet ) {
+ elem.selectedIndex = -1;
+ }
+
+ return options;
+ }
+ }
+ }
+});
+
+// Radios and checkboxes getter/setter
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ };
+ if ( !support.checkOn ) {
+ jQuery.valHooks[ this ].get = function( elem ) {
+ // Support: Webkit
+ // "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ };
+ }
+});
+
+
+
+
+var nodeHook, boolHook,
+ attrHandle = jQuery.expr.attrHandle,
+ ruseDefault = /^(?:checked|selected)$/i,
+ getSetAttribute = support.getSetAttribute,
+ getSetInput = support.input;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ }
+});
+
+jQuery.extend({
+ attr: function( elem, name, value ) {
+ var hooks, ret,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === strundefined ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] ||
+ ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+
+ } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ ret = jQuery.find.attr( elem, name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name, propName,
+ i = 0,
+ attrNames = value && value.match( rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( (name = attrNames[i++]) ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // Boolean attributes get special treatment (#10870)
+ if ( jQuery.expr.match.bool.test( name ) ) {
+ // Set corresponding property to false
+ if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+ elem[ propName ] = false;
+ // Support: IE<9
+ // Also clear defaultChecked/defaultSelected (if appropriate)
+ } else {
+ elem[ jQuery.camelCase( "default-" + name ) ] =
+ elem[ propName ] = false;
+ }
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ } else {
+ jQuery.attr( elem, name, "" );
+ }
+
+ elem.removeAttribute( getSetAttribute ? name : propName );
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to default in case type is set after value during creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ }
+});
+
+// Hook for boolean attributes
+boolHook = {
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+ // IE<8 needs the *property* name
+ elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+ // Use defaultChecked and defaultSelected for oldIE
+ } else {
+ elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+ }
+
+ return name;
+ }
+};
+
+// Retrieve booleans specially
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+
+ var getter = attrHandle[ name ] || jQuery.find.attr;
+
+ attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
+ function( elem, name, isXML ) {
+ var ret, handle;
+ if ( !isXML ) {
+ // Avoid an infinite loop by temporarily removing this function from the getter
+ handle = attrHandle[ name ];
+ attrHandle[ name ] = ret;
+ ret = getter( elem, name, isXML ) != null ?
+ name.toLowerCase() :
+ null;
+ attrHandle[ name ] = handle;
+ }
+ return ret;
+ } :
+ function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem[ jQuery.camelCase( "default-" + name ) ] ?
+ name.toLowerCase() :
+ null;
+ }
+ };
+});
+
+// fix oldIE attroperties
+if ( !getSetInput || !getSetAttribute ) {
+ jQuery.attrHooks.value = {
+ set: function( elem, value, name ) {
+ if ( jQuery.nodeName( elem, "input" ) ) {
+ // Does not return so that setAttribute is also used
+ elem.defaultValue = value;
+ } else {
+ // Use nodeHook if defined (#1954); otherwise setAttribute is fine
+ return nodeHook && nodeHook.set( elem, value, name );
+ }
+ }
+ };
+}
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = {
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ elem.setAttributeNode(
+ (ret = elem.ownerDocument.createAttribute( name ))
+ );
+ }
+
+ ret.value = value += "";
+
+ // Break association with cloned elements by also using setAttribute (#9646)
+ if ( name === "value" || value === elem.getAttribute( name ) ) {
+ return value;
+ }
+ }
+ };
+
+ // Some attributes are constructed with empty-string values when not defined
+ attrHandle.id = attrHandle.name = attrHandle.coords =
+ function( elem, name, isXML ) {
+ var ret;
+ if ( !isXML ) {
+ return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
+ ret.value :
+ null;
+ }
+ };
+
+ // Fixing value retrieval on a button requires this module
+ jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ if ( ret && ret.specified ) {
+ return ret.value;
+ }
+ },
+ set: nodeHook.set
+ };
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ set: function( elem, value, name ) {
+ nodeHook.set( elem, value === "" ? false : value, name );
+ }
+ };
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ };
+ });
+}
+
+if ( !support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Note: IE uppercases css property names, but if we were to .toLowerCase()
+ // .cssText, that would destroy case senstitivity in URL's, like in "background"
+ return elem.style.cssText || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = value + "" );
+ }
+ };
+}
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button|object)$/i,
+ rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend({
+ prop: function( name, value ) {
+ return access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ }
+});
+
+jQuery.extend({
+ propFix: {
+ "for": "htmlFor",
+ "class": "className"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
+ ret :
+ ( elem[ name ] = value );
+
+ } else {
+ return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
+ ret :
+ elem[ name ];
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ // Use proper attribute retrieval(#12072)
+ var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+ return tabindex ?
+ parseInt( tabindex, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ -1;
+ }
+ }
+ }
+});
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !support.hrefNormalized ) {
+ // href/src property should get the full normalized URL (#10299/#12915)
+ jQuery.each([ "href", "src" ], function( i, name ) {
+ jQuery.propHooks[ name ] = {
+ get: function( elem ) {
+ return elem.getAttribute( name, 4 );
+ }
+ };
+ });
+}
+
+// Support: Safari, IE9+
+// mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !support.optSelected ) {
+ jQuery.propHooks.selected = {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ };
+}
+
+jQuery.each([
+ "tabIndex",
+ "readOnly",
+ "maxLength",
+ "cellSpacing",
+ "cellPadding",
+ "rowSpan",
+ "colSpan",
+ "useMap",
+ "frameBorder",
+ "contentEditable"
+], function() {
+ jQuery.propFix[ this.toLowerCase() ] = this;
+});
+
+// IE6/7 call enctype encoding
+if ( !support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+jQuery.fn.extend({
+ addClass: function( value ) {
+ var classes, elem, cur, clazz, j, finalValue,
+ i = 0,
+ len = this.length,
+ proceed = typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call( this, j, this.className ) );
+ });
+ }
+
+ if ( proceed ) {
+ // The disjunction here is for better compressibility (see removeClass)
+ classes = ( value || "" ).match( rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ " "
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+
+ // only assign if different to avoid unneeded rendering.
+ finalValue = jQuery.trim( cur );
+ if ( elem.className !== finalValue ) {
+ elem.className = finalValue;
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, clazz, j, finalValue,
+ i = 0,
+ len = this.length,
+ proceed = arguments.length === 0 || typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, this.className ) );
+ });
+ }
+ if ( proceed ) {
+ classes = ( value || "" ).match( rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ ""
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+
+ // only assign if different to avoid unneeded rendering.
+ finalValue = value ? jQuery.trim( cur ) : "";
+ if ( elem.className !== finalValue ) {
+ elem.className = finalValue;
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value;
+
+ if ( typeof stateVal === "boolean" && type === "string" ) {
+ return stateVal ? this.addClass( value ) : this.removeClass( value );
+ }
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ classNames = value.match( rnotwhite ) || [];
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space separated list
+ if ( self.hasClass( className ) ) {
+ self.removeClass( className );
+ } else {
+ self.addClass( className );
+ }
+ }
+
+ // Toggle whole class name
+ } else if ( type === strundefined || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // If the element has a class name or if we're passed "false",
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+});
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+});
+
+jQuery.fn.extend({
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+ }
+});
+
+
+var nonce = jQuery.now();
+
+var rquery = (/\?/);
+
+
+
+var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
+
+jQuery.parseJSON = function( data ) {
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ // Support: Android 2.3
+ // Workaround failure to string-cast null input
+ return window.JSON.parse( data + "" );
+ }
+
+ var requireNonComma,
+ depth = null,
+ str = jQuery.trim( data + "" );
+
+ // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
+ // after removing valid tokens
+ return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
+
+ // Force termination if we see a misplaced comma
+ if ( requireNonComma && comma ) {
+ depth = 0;
+ }
+
+ // Perform no more replacements after returning to outermost depth
+ if ( depth === 0 ) {
+ return token;
+ }
+
+ // Commas must not follow "[", "{", or ","
+ requireNonComma = open || comma;
+
+ // Determine new depth
+ // array/object open ("[" or "{"): depth += true - false (increment)
+ // array/object close ("]" or "}"): depth += false - true (decrement)
+ // other cases ("," or primitive): depth += true - true (numeric cast)
+ depth += !close - !open;
+
+ // Remove this token
+ return "";
+ }) ) ?
+ ( Function( "return " + str ) )() :
+ jQuery.error( "Invalid JSON: " + data );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+ var xml, tmp;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data, "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+};
+
+
+var
+ // Document location
+ ajaxLocParts,
+ ajaxLocation,
+
+ rhash = /#.*$/,
+ rts = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+ // For each dataType in the dataTypeExpression
+ while ( (dataType = dataTypes[i++]) ) {
+ // Prepend if requested
+ if ( dataType.charAt( 0 ) === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+ // Otherwise append
+ } else {
+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
+ }
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ });
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var deep, key,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+ var firstDataType, ct, finalDataType, type,
+ contents = s.contents,
+ dataTypes = s.dataTypes;
+
+ // Remove auto dataType and get content-type in the process
+ while ( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+ var conv2, current, conv, tmp, prev,
+ converters = {},
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice();
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ current = dataTypes.shift();
+
+ // Convert to each sequential dataType
+ while ( current ) {
+
+ if ( s.responseFields[ current ] ) {
+ jqXHR[ s.responseFields[ current ] ] = response;
+ }
+
+ // Apply the dataFilter if provided
+ if ( !prev && isSuccess && s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ prev = current;
+ current = dataTypes.shift();
+
+ if ( current ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current === "*" ) {
+
+ current = prev;
+
+ // Convert response if prev dataType is non-auto and differs from current
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split( " " );
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.unshift( tmp[ 1 ] );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s[ "throws" ] ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { state: "success", data: response };
+}
+
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ type: "GET",
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText",
+ json: "responseJSON"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Cross-domain detection vars
+ parts,
+ // Loop variable
+ i,
+ // URL without anti-cache param
+ cacheURL,
+ // Response headers as string
+ responseHeadersString,
+ // timeout handle
+ timeoutTimer,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ transport,
+ // Response headers
+ responseHeaders,
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks("once memory"),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // The jqXHR state
+ state = 0,
+ // Default abort message
+ strAbort = "canceled",
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ var lname = name.toLowerCase();
+ if ( !state ) {
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( state < 2 ) {
+ for ( code in map ) {
+ // Lazy-add the new callback in a way that preserves old ones
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ } else {
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger("ajaxStart");
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ cacheURL = s.url;
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+ s.url = rts.test( cacheURL ) ?
+
+ // If there is already a '_' parameter, set its value
+ cacheURL.replace( rts, "$1_=" + nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
+ }
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout(function() {
+ jqXHR.abort("timeout");
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Determine if successful
+ isSuccess = status >= 200 && status < 300 || status === 304;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // Convert no matter what (that way responseXXX fields are always set)
+ response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+ // If successful, handle type chaining
+ if ( isSuccess ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader("Last-Modified");
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader("etag");
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 || s.type === "HEAD" ) {
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ statusText = response.state;
+ success = response.data;
+ error = response.error;
+ isSuccess = !error;
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger("ajaxStop");
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ }
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ });
+ };
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
+ jQuery.fn[ type ] = function( fn ) {
+ return this.on( type, fn );
+ };
+});
+
+
+jQuery._evalUrl = function( url ) {
+ return jQuery.ajax({
+ url: url,
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ });
+};
+
+
+jQuery.fn.extend({
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ }
+});
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+ // Support: Opera <= 12.12
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
+ return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+ (!support.reliableHiddenOffsets() &&
+ ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+};
+
+jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+};
+
+
+
+
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend({
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map(function() {
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ })
+ .filter(function() {
+ var type = this.type;
+ // Use .is(":disabled") so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !rcheckableType.test( type ) );
+ })
+ .map(function( i, elem ) {
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ) {
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
+ // Support: IE6+
+ function() {
+
+ // XHR cannot access local files, always use ActiveX for that case
+ return !this.isLocal &&
+
+ // Support: IE7-8
+ // oldIE XHR does not support non-RFC2616 methods (#13240)
+ // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
+ // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
+ // Although this check for six methods instead of eight
+ // since IE also does not support "trace" and "connect"
+ /^(get|post|head|put|delete|options)$/i.test( this.type ) &&
+
+ createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+var xhrId = 0,
+ xhrCallbacks = {},
+ xhrSupported = jQuery.ajaxSettings.xhr();
+
+// Support: IE<10
+// Open requests must be manually aborted on unload (#5280)
+if ( window.ActiveXObject ) {
+ jQuery( window ).on( "unload", function() {
+ for ( var key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( undefined, true );
+ }
+ });
+}
+
+// Determine support properties
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+if ( xhrSupported ) {
+
+ jQuery.ajaxTransport(function( options ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !options.crossDomain || support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+ var i,
+ xhr = options.xhr(),
+ id = ++xhrId;
+
+ // Open the socket
+ xhr.open( options.type, options.url, options.async, options.username, options.password );
+
+ // Apply custom fields if provided
+ if ( options.xhrFields ) {
+ for ( i in options.xhrFields ) {
+ xhr[ i ] = options.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( options.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( options.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !options.crossDomain && !headers["X-Requested-With"] ) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ // Set headers
+ for ( i in headers ) {
+ // Support: IE<9
+ // IE's ActiveXObject throws a 'Type Mismatch' exception when setting
+ // request header to a null-value.
+ //
+ // To keep consistent with other XHR implementations, cast the value
+ // to string and ignore `undefined`.
+ if ( headers[ i ] !== undefined ) {
+ xhr.setRequestHeader( i, headers[ i ] + "" );
+ }
+ }
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( options.hasContent && options.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+ var status, statusText, responses;
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+ // Clean up
+ delete xhrCallbacks[ id ];
+ callback = undefined;
+ xhr.onreadystatechange = jQuery.noop;
+
+ // Abort manually if needed
+ if ( isAbort ) {
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ responses = {};
+ status = xhr.status;
+
+ // Support: IE<10
+ // Accessing binary-data responseText throws an exception
+ // (#11426)
+ if ( typeof xhr.responseText === "string" ) {
+ responses.text = xhr.responseText;
+ }
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && options.isLocal && !options.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, xhr.getAllResponseHeaders() );
+ }
+ };
+
+ if ( !options.async ) {
+ // if we're in sync mode we fire the callback
+ callback();
+ } else if ( xhr.readyState === 4 ) {
+ // (IE6 & IE7) if it's in cache and has been
+ // retrieved directly we need to fire the callback
+ setTimeout( callback );
+ } else {
+ // Add to the list of active xhr callbacks
+ xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback( undefined, true );
+ }
+ }
+ };
+ }
+ });
+}
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+ } catch( e ) {}
+}
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /(?:java|ecma)script/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || jQuery("head")[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement("script");
+
+ script.async = true;
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( script.parentNode ) {
+ script.parentNode.removeChild( script );
+ }
+
+ // Dereference the script
+ script = null;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+
+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( undefined, true );
+ }
+ }
+ };
+ }
+});
+
+
+
+
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always(function() {
+ // Restore preexisting value
+ window[ callbackName ] = overwritten;
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+ // make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ });
+
+ // Delegate to script
+ return "script";
+ }
+});
+
+
+
+
+// data: string of html
+// context (optional): If specified, the fragment will be created in this context, defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+ context = context || document;
+
+ var parsed = rsingleTag.exec( data ),
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[1] ) ];
+ }
+
+ parsed = jQuery.buildFragment( [ data ], context, scripts );
+
+ if ( scripts && scripts.length ) {
+ jQuery( scripts ).remove();
+ }
+
+ return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+ }
+
+ var selector, response, type,
+ self = this,
+ off = url.indexOf(" ");
+
+ if ( off >= 0 ) {
+ selector = jQuery.trim( url.slice( off, url.length ) );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax({
+ url: url,
+
+ // if "type" variable is undefined, then "GET" method will be used
+ type: type,
+ dataType: "html",
+ data: params
+ }).done(function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+};
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+};
+
+
+
+
+
+var docElem = window.document.documentElement;
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+
+jQuery.offset = {
+ setOffset: function( elem, options, i ) {
+ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+ position = jQuery.css( elem, "position" ),
+ curElem = jQuery( elem ),
+ props = {};
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ curOffset = curElem.offset();
+ curCSSTop = jQuery.css( elem, "top" );
+ curCSSLeft = jQuery.css( elem, "left" );
+ calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+ jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+jQuery.fn.extend({
+ offset: function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+ },
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
+
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // we assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || docElem;
+
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || docElem;
+ });
+ }
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ win.document.documentElement[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// getComputedStyle returns percent when specified for top/left/bottom/right
+// rather than make the css module depend on the offset module, we just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+ function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ );
+});
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+});
+
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+ return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+ define( "jquery", [], function() {
+ return jQuery;
+ });
+}
+
+
+
+
+var
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in
+// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+ window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+
+}));
diff --git a/sphinx/themes/basic/static/jquery.js b/sphinx/themes/basic/static/jquery.js
index 83589daa..ab28a247 100644
--- a/sphinx/themes/basic/static/jquery.js
+++ b/sphinx/themes/basic/static/jquery.js
@@ -1,2 +1,4 @@
-/*! jQuery v1.8.3 jquery.com | jquery.org/license */
-(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]!==t&&((s[r]?e:i||(i={}))[r]=n[r]);i&&v.extend(!0,e,i)}function An(e,n,r){var i,s,o,u,a=e.contents,f=e.dataTypes,l=e.responseFields;for(s in l)s in r&&(n[l[s]]=r[s]);while(f[0]==="*")f.shift(),i===t&&(i=e.mimeType||n.getResponseHeader("content-type"));if(i)for(s in a)if(a[s]&&a[s].test(i)){f.unshift(s);break}if(f[0]in r)o=f[0];else{for(s in r){if(!f[0]||e.converters[s+" "+f[0]]){o=s;break}u||(u=s)}o=o||u}if(o)return o!==f[0]&&f.unshift(o),r[o]}function On(e,t){var n,r,i,s,o=e.dataTypes.slice(),u=o[0],a={},f=0;e.dataFilter&&(t=e.dataFilter(t,e.dataType));if(o[1])for(n in e.converters)a[n.toLowerCase()]=e.converters[n];for(;i=o[++f];)if(i!=="*"){if(u!=="*"&&u!==i){n=a[u+" "+i]||a["* "+i];if(!n)for(r in a){s=r.split(" ");if(s[1]===i){n=a[u+" "+s[0]]||a["* "+s[0]];if(n){n===!0?n=a[r]:a[r]!==!0&&(i=s[0],o.splice(f--,0,i));break}}}if(n!==!0)if(n&&e["throws"])t=n(t);else try{t=n(t)}catch(l){return{state:"parsererror",error:n?l:"No conversion from "+u+" to "+i}}}u=i}return{state:"success",data:t}}function Fn(){try{return new e.XMLHttpRequest}catch(t){}}function In(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function $n(){return setTimeout(function(){qn=t},0),qn=v.now()}function Jn(e,t){v.each(t,function(t,n){var r=(Vn[t]||[]).concat(Vn["*"]),i=0,s=r.length;for(;i<s;i++)if(r[i].call(e,t,n))return})}function Kn(e,t,n){var r,i=0,s=0,o=Xn.length,u=v.Deferred().always(function(){delete a.elem}),a=function(){var t=qn||$n(),n=Math.max(0,f.startTime+f.duration-t),r=n/f.duration||0,i=1-r,s=0,o=f.tweens.length;for(;s<o;s++)f.tweens[s].run(i);return u.notifyWith(e,[f,i,n]),i<1&&o?n:(u.resolveWith(e,[f]),!1)},f=u.promise({elem:e,props:v.extend({},t),opts:v.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:qn||$n(),duration:n.duration,tweens:[],createTween:function(t,n,r){var i=v.Tween(e,f.opts,t,n,f.opts.specialEasing[t]||f.opts.easing);return f.tweens.push(i),i},stop:function(t){var n=0,r=t?f.tweens.length:0;for(;n<r;n++)f.tweens[n].run(1);return t?u.resolveWith(e,[f,t]):u.rejectWith(e,[f,t]),this}}),l=f.props;Qn(l,f.opts.specialEasing);for(;i<o;i++){r=Xn[i].call(f,e,l,f.opts);if(r)return r}return Jn(f,l),v.isFunction(f.opts.start)&&f.opts.start.call(e,f),v.fx.timer(v.extend(a,{anim:f,queue:f.opts.queue,elem:e})),f.progress(f.opts.progress).done(f.opts.done,f.opts.complete).fail(f.opts.fail).always(f.opts.always)}function Qn(e,t){var n,r,i,s,o;for(n in e){r=v.camelCase(n),i=t[r],s=e[n],v.isArray(s)&&(i=s[1],s=e[n]=s[0]),n!==r&&(e[r]=s,delete e[n]),o=v.cssHooks[r];if(o&&"expand"in o){s=o.expand(s),delete e[r];for(n in s)n in e||(e[n]=s[n],t[n]=i)}else t[r]=i}}function Gn(e,t,n){var r,i,s,o,u,a,f,l,c,h=this,p=e.style,d={},m=[],g=e.nodeType&&Gt(e);n.queue||(l=v._queueHooks(e,"fx"),l.unqueued==null&&(l.unqueued=0,c=l.empty.fire,l.empty.fire=function(){l.unqueued||c()}),l.unqueued++,h.always(function(){h.always(function(){l.unqueued--,v.queue(e,"fx").length||l.empty.fire()})})),e.nodeType===1&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],v.css(e,"display")==="inline"&&v.css(e,"float")==="none"&&(!v.support.inlineBlockNeedsLayout||nn(e.nodeName)==="inline"?p.display="inline-block":p.zoom=1)),n.overflow&&(p.overflow="hidden",v.support.shrinkWrapBlocks||h.done(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t){s=t[r];if(Un.exec(s)){delete t[r],a=a||s==="toggle";if(s===(g?"hide":"show"))continue;m.push(r)}}o=m.length;if(o){u=v._data(e,"fxshow")||v._data(e,"fxshow",{}),"hidden"in u&&(g=u.hidden),a&&(u.hidden=!g),g?v(e).show():h.done(function(){v(e).hide()}),h.done(function(){var t;v.removeData(e,"fxshow",!0);for(t in d)v.style(e,t,d[t])});for(r=0;r<o;r++)i=m[r],f=h.createTween(i,g?u[i]:0),d[i]=u[i]||v.style(e,i),i in u||(u[i]=f.start,g&&(f.end=f.start,f.start=i==="width"||i==="height"?1:0))}}function Yn(e,t,n,r,i){return new Yn.prototype.init(e,t,n,r,i)}function Zn(e,t){var n,r={height:e},i=0;t=t?1:0;for(;i<4;i+=2-t)n=$t[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function tr(e){return v.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:!1}var n,r,i=e.document,s=e.location,o=e.navigator,u=e.jQuery,a=e.$,f=Array.prototype.push,l=Array.prototype.slice,c=Array.prototype.indexOf,h=Object.prototype.toString,p=Object.prototype.hasOwnProperty,d=String.prototype.trim,v=function(e,t){return new v.fn.init(e,t,n)},m=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,g=/\S/,y=/\s+/,b=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,w=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a<f;a++)if((e=arguments[a])!=null)for(n in e){r=u[n],i=e[n];if(u===i)continue;l&&i&&(v.isPlainObject(i)||(s=v.isArray(i)))?(s?(s=!1,o=r&&v.isArray(r)?r:[]):o=r&&v.isPlainObject(r)?r:{},u[n]=v.extend(l,o,i)):i!==t&&(u[n]=i)}return u},v.extend({noConflict:function(t){return e.$===v&&(e.$=a),t&&e.jQuery===v&&(e.jQuery=u),v},isReady:!1,readyWait:1,holdReady:function(e){e?v.readyWait++:v.ready(!0)},ready:function(e){if(e===!0?--v.readyWait:v.isReady)return;if(!i.body)return setTimeout(v.ready,1);v.isReady=!0;if(e!==!0&&--v.readyWait>0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s<o;)if(n.apply(e[s++],r)===!1)break}else if(u){for(i in e)if(n.call(e[i],i,e[i])===!1)break}else for(;s<o;)if(n.call(e[s],s,e[s++])===!1)break;return e},trim:d&&!d.call("\ufeff\u00a0")?function(e){return e==null?"":d.call(e)}:function(e){return e==null?"":(e+"").replace(b,"")},makeArray:function(e,t){var n,r=t||[];return e!=null&&(n=v.type(e),e.length==null||n==="string"||n==="function"||n==="regexp"||v.isWindow(e)?f.call(r,e):v.merge(r,e)),r},inArray:function(e,t,n){var r;if(t){if(c)return c.call(t,e,n);r=t.length,n=n?n<0?Math.max(0,r+n):n:0;for(;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,s=0;if(typeof r=="number")for(;s<r;s++)e[i++]=n[s];else while(n[s]!==t)e[i++]=n[s++];return e.length=i,e},grep:function(e,t,n){var r,i=[],s=0,o=e.length;n=!!n;for(;s<o;s++)r=!!t(e[s],s),n!==r&&i.push(e[s]);return i},map:function(e,n,r){var i,s,o=[],u=0,a=e.length,f=e instanceof v||a!==t&&typeof a=="number"&&(a>0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u<a;u++)i=n(e[u],u,r),i!=null&&(o[o.length]=i);else for(s in e)i=n(e[s],s,r),i!=null&&(o[o.length]=i);return o.concat.apply([],o)},guid:1,proxy:function(e,n){var r,i,s;return typeof n=="string"&&(r=e[n],n=e,e=r),v.isFunction(e)?(i=l.call(arguments,2),s=function(){return e.apply(n,i.concat(l.call(arguments)))},s.guid=e.guid=e.guid||v.guid++,s):t},access:function(e,n,r,i,s,o,u){var a,f=r==null,l=0,c=e.length;if(r&&typeof r=="object"){for(l in r)v.access(e,n,l,r[l],1,o,i);s=1}else if(i!==t){a=u===t&&v.isFunction(i),f&&(a?(a=n,n=function(e,t,n){return a.call(v(e),n)}):(n.call(e,i),n=null));if(n)for(;l<c;l++)n(e[l],r,a?i.call(e[l],l,n(e[l],r)):i,u);s=1}return s?e:f?n.call(e):c?n(e[0],r):o},now:function(){return(new Date).getTime()}}),v.ready.promise=function(t){if(!r){r=v.Deferred();if(i.readyState==="complete")setTimeout(v.ready,1);else if(i.addEventListener)i.addEventListener("DOMContentLoaded",A,!1),e.addEventListener("load",v.ready,!1);else{i.attachEvent("onreadystatechange",A),e.attachEvent("onload",v.ready);var n=!1;try{n=e.frameElement==null&&i.documentElement}catch(s){}n&&n.doScroll&&function o(){if(!v.isReady){try{n.doScroll("left")}catch(e){return setTimeout(o,50)}v.ready()}}()}}return r.promise(t)},v.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(e,t){O["[object "+t+"]"]=t.toLowerCase()}),n=v(i);var M={};v.Callbacks=function(e){e=typeof e=="string"?M[e]||_(e):v.extend({},e);var n,r,i,s,o,u,a=[],f=!e.once&&[],l=function(t){n=e.memory&&t,r=!0,u=s||0,s=0,o=a.length,i=!0;for(;a&&u<o;u++)if(a[u].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}i=!1,a&&(f?f.length&&l(f.shift()):n?a=[]:c.disable())},c={add:function(){if(a){var t=a.length;(function r(t){v.each(t,function(t,n){var i=v.type(n);i==="function"?(!e.unique||!c.has(n))&&a.push(n):n&&n.length&&i!=="string"&&r(n)})})(arguments),i?o=a.length:n&&(s=t,l(n))}return this},remove:function(){return a&&v.each(arguments,function(e,t){var n;while((n=v.inArray(t,a,n))>-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t<r;t++)n[t]&&v.isFunction(n[t].promise)?n[t].promise().done(o(t,f,n)).fail(s.reject).progress(o(t,a,u)):--i}return i||s.resolveWith(f,n),s.promise()}}),v.support=function(){var t,n,r,s,o,u,a,f,l,c,h,p=i.createElement("div");p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="<table><tr><td></td><td>t</td></tr></table>",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="<div></div>",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i<s;i++)delete r[t[i]];if(!(n?B:v.isEmptyObject)(r))return}}if(!n){delete u[a].data;if(!B(u[a]))return}o?v.cleanData([e],!0):v.support.deleteExpando||u!=u.window?delete u[a]:u[a]=null},_data:function(e,t,n){return v.data(e,t,n,!0)},acceptData:function(e){var t=e.nodeName&&v.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),v.fn.extend({data:function(e,n){var r,i,s,o,u,a=this[0],f=0,l=null;if(e===t){if(this.length){l=v.data(a);if(a.nodeType===1&&!v._data(a,"parsedAttrs")){s=a.attributes;for(u=s.length;f<u;f++)o=s[f].name,o.indexOf("data-")||(o=v.camelCase(o.substring(5)),H(a,o,l[o]));v._data(a,"parsedAttrs",!0)}}return l}return typeof e=="object"?this.each(function(){v.data(this,e)}):(r=e.split(".",2),r[1]=r[1]?"."+r[1]:"",i=r[1]+"!",v.access(this,function(n){if(n===t)return l=this.triggerHandler("getData"+i,[r[0]]),l===t&&a&&(l=v.data(a,e),l=H(a,e,l)),l===t&&r[1]?this.data(r[0]):l;r[1]=n,this.each(function(){var t=v(this);t.triggerHandler("setData"+i,r),v.data(this,e,n),t.triggerHandler("changeData"+i,r)})},null,n,arguments.length>1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length<r?v.queue(this[0],e):n===t?this:this.each(function(){var t=v.queue(this,e,n);v._queueHooks(this,e),e==="fx"&&t[0]!=="inprogress"&&v.dequeue(this,e)})},dequeue:function(e){return this.each(function(){v.dequeue(this,e)})},delay:function(e,t){return e=v.fx?v.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,s=v.Deferred(),o=this,u=this.length,a=function(){--i||s.resolveWith(o,[o])};typeof e!="string"&&(n=e,e=t),e=e||"fx";while(u--)r=v._data(o[u],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(a));return a(),s.promise(n)}});var j,F,I,q=/[\t\r\n]/g,R=/\r/g,U=/^(?:button|input)$/i,z=/^(?:button|input|object|select|textarea)$/i,W=/^a(?:rea|)$/i,X=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,V=v.support.getSetAttribute;v.fn.extend({attr:function(e,t){return v.access(this,v.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n<r;n++){i=this[n];if(i.nodeType===1)if(!i.className&&t.length===1)i.className=e;else{s=" "+i.className+" ";for(o=0,u=t.length;o<u;o++)s.indexOf(" "+t[o]+" ")<0&&(s+=t[o]+" ");i.className=v.trim(s)}}}return this},removeClass:function(e){var n,r,i,s,o,u,a;if(v.isFunction(e))return this.each(function(t){v(this).removeClass(e.call(this,t,this.className))});if(e&&typeof e=="string"||e===t){n=(e||"").split(y);for(u=0,a=this.length;u<a;u++){i=this[u];if(i.nodeType===1&&i.className){r=(" "+i.className+" ").replace(q," ");for(s=0,o=n.length;s<o;s++)while(r.indexOf(" "+n[s]+" ")>=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n<r;n++)if(this[n].nodeType===1&&(" "+this[n].className+" ").replace(q," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a<u;a++){n=r[a];if((n.selected||a===i)&&(v.support.optDisabled?!n.disabled:n.getAttribute("disabled")===null)&&(!n.parentNode.disabled||!v.nodeName(n.parentNode,"optgroup"))){t=v(n).val();if(s)return t;o.push(t)}}return o},set:function(e,t){var n=v.makeArray(t);return v(e).find("option").each(function(){this.selected=v.inArray(v(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o<r.length;o++)i=r[o],i&&(n=v.propFix[i]||i,s=X.test(i),s||v.attr(e,i,""),e.removeAttribute(V?i:n),s&&n in e&&(e[n]=!1))}},attrHooks:{type:{set:function(e,t){if(U.test(e.nodeName)&&e.parentNode)v.error("type property can't be changed");else if(!v.support.radioValue&&t==="radio"&&v.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}},value:{get:function(e,t){return j&&v.nodeName(e,"button")?j.get(e,t):t in e?e.value:null},set:function(e,t,n){if(j&&v.nodeName(e,"button"))return j.set(e,t,n);e.value=t}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,s,o,u=e.nodeType;if(!e||u===3||u===8||u===2)return;return o=u!==1||!v.isXMLDoc(e),o&&(n=v.propFix[n]||n,s=v.propHooks[n]),r!==t?s&&"set"in s&&(i=s.set(e,r,n))!==t?i:e[n]=r:s&&"get"in s&&(i=s.get(e,n))!==null?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):z.test(e.nodeName)||W.test(e.nodeName)&&e.href?0:t}}}}),F={get:function(e,n){var r,i=v.prop(e,n);return i===!0||typeof i!="boolean"&&(r=e.getAttributeNode(n))&&r.nodeValue!==!1?n.toLowerCase():t},set:function(e,t,n){var r;return t===!1?v.removeAttr(e,n):(r=v.propFix[n]||n,r in e&&(e[r]=!0),e.setAttribute(n,n.toLowerCase())),n}},V||(I={name:!0,id:!0,coords:!0},j=v.valHooks.button={get:function(e,n){var r;return r=e.getAttributeNode(n),r&&(I[n]?r.value!=="":r.specified)?r.value:t},set:function(e,t,n){var r=e.getAttributeNode(n);return r||(r=i.createAttribute(n),e.setAttributeNode(r)),r.value=t+""}},v.each(["width","height"],function(e,t){v.attrHooks[t]=v.extend(v.attrHooks[t],{set:function(e,n){if(n==="")return e.setAttribute(t,"auto"),n}})}),v.attrHooks.contenteditable={get:j.get,set:function(e,t,n){t===""&&(t="false"),j.set(e,t,n)}}),v.support.hrefNormalized||v.each(["href","src","width","height"],function(e,n){v.attrHooks[n]=v.extend(v.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return r===null?t:r}})}),v.support.style||(v.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||t},set:function(e,t){return e.style.cssText=t+""}}),v.support.optSelected||(v.propHooks.selected=v.extend(v.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),v.support.enctype||(v.propFix.enctype="encoding"),v.support.checkOn||v.each(["radio","checkbox"],function(){v.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}}),v.each(["radio","checkbox"],function(){v.valHooks[this]=v.extend(v.valHooks[this],{set:function(e,t){if(v.isArray(t))return e.checked=v.inArray(v(e).val(),t)>=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f<n.length;f++){l=J.exec(n[f])||[],c=l[1],h=(l[2]||"").split(".").sort(),g=v.event.special[c]||{},c=(s?g.delegateType:g.bindType)||c,g=v.event.special[c]||{},p=v.extend({type:c,origType:l[1],data:i,handler:r,guid:r.guid,selector:s,needsContext:s&&v.expr.match.needsContext.test(s),namespace:h.join(".")},d),m=a[c];if(!m){m=a[c]=[],m.delegateCount=0;if(!g.setup||g.setup.call(e,i,h,u)===!1)e.addEventListener?e.addEventListener(c,u,!1):e.attachEvent&&e.attachEvent("on"+c,u)}g.add&&(g.add.call(e,p),p.handler.guid||(p.handler.guid=r.guid)),s?m.splice(m.delegateCount++,0,p):m.push(p),v.event.global[c]=!0}e=null},global:{},remove:function(e,t,n,r,i){var s,o,u,a,f,l,c,h,p,d,m,g=v.hasData(e)&&v._data(e);if(!g||!(h=g.events))return;t=v.trim(Z(t||"")).split(" ");for(s=0;s<t.length;s++){o=J.exec(t[s])||[],u=a=o[1],f=o[2];if(!u){for(u in h)v.event.remove(e,u+t[s],n,r,!0);continue}p=v.event.special[u]||{},u=(r?p.delegateType:p.bindType)||u,d=h[u]||[],l=d.length,f=f?new RegExp("(^|\\.)"+f.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(c=0;c<d.length;c++)m=d[c],(i||a===m.origType)&&(!n||n.guid===m.guid)&&(!f||f.test(m.namespace))&&(!r||r===m.selector||r==="**"&&m.selector)&&(d.splice(c--,1),m.selector&&d.delegateCount--,p.remove&&p.remove.call(e,m));d.length===0&&l!==d.length&&((!p.teardown||p.teardown.call(e,f,g.handle)===!1)&&v.removeEvent(e,u,g.handle),delete h[u])}v.isEmptyObject(h)&&(delete g.handle,v.removeData(e,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(n,r,s,o){if(!s||s.nodeType!==3&&s.nodeType!==8){var u,a,f,l,c,h,p,d,m,g,y=n.type||n,b=[];if(Y.test(y+v.event.triggered))return;y.indexOf("!")>=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f<m.length&&!n.isPropagationStopped();f++)l=m[f][0],n.type=m[f][1],d=(v._data(l,"events")||{})[n.type]&&v._data(l,"handle"),d&&d.apply(l,r),d=h&&l[h],d&&v.acceptData(l)&&d.apply&&d.apply(l,r)===!1&&n.preventDefault();return n.type=y,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(s.ownerDocument,r)===!1)&&(y!=="click"||!v.nodeName(s,"a"))&&v.acceptData(s)&&h&&s[y]&&(y!=="focus"&&y!=="blur"||n.target.offsetWidth!==0)&&!v.isWindow(s)&&(c=s[h],c&&(s[h]=null),v.event.triggered=y,s[y](),v.event.triggered=t,c&&(s[h]=c)),n.result}return},dispatch:function(n){n=v.event.fix(n||e.event);var r,i,s,o,u,a,f,c,h,p,d=(v._data(this,"events")||{})[n.type]||[],m=d.delegateCount,g=l.call(arguments),y=!n.exclusive&&!n.namespace,b=v.event.special[n.type]||{},w=[];g[0]=n,n.delegateTarget=this;if(b.preDispatch&&b.preDispatch.call(this,n)===!1)return;if(m&&(!n.button||n.type!=="click"))for(s=n.target;s!=this;s=s.parentNode||this)if(s.disabled!==!0||n.type!=="click"){u={},f=[];for(r=0;r<m;r++)c=d[r],h=c.selector,u[h]===t&&(u[h]=c.needsContext?v(h,this).index(s)>=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r<w.length&&!n.isPropagationStopped();r++){a=w[r],n.currentTarget=a.elem;for(i=0;i<a.matches.length&&!n.isImmediatePropagationStopped();i++){c=a.matches[i];if(y||!n.namespace&&!c.namespace||n.namespace_re&&n.namespace_re.test(c.namespace))n.data=c.data,n.handleObj=c,o=((v.event.special[c.origType]||{}).handle||c.handler).apply(a.elem,g),o!==t&&(n.result=o,o===!1&&(n.preventDefault(),n.stopPropagation()))}}return b.postDispatch&&b.postDispatch.call(this,n),n.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return e.which==null&&(e.which=t.charCode!=null?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,s,o,u=n.button,a=n.fromElement;return e.pageX==null&&n.clientX!=null&&(r=e.target.ownerDocument||i,s=r.documentElement,o=r.body,e.pageX=n.clientX+(s&&s.scrollLeft||o&&o.scrollLeft||0)-(s&&s.clientLeft||o&&o.clientLeft||0),e.pageY=n.clientY+(s&&s.scrollTop||o&&o.scrollTop||0)-(s&&s.clientTop||o&&o.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?n.toElement:a),!e.which&&u!==t&&(e.which=u&1?1:u&2?3:u&4?2:0),e}},fix:function(e){if(e[v.expando])return e;var t,n,r=e,s=v.event.fixHooks[e.type]||{},o=s.props?this.props.concat(s.props):this.props;e=v.Event(r);for(t=o.length;t;)n=o[--t],e[n]=r[n];return e.target||(e.target=r.srcElement||i),e.target.nodeType===3&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,r):e},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(e,t,n){v.isWindow(this)&&(this.onbeforeunload=n)},teardown:function(e,t){this.onbeforeunload===t&&(this.onbeforeunload=null)}}},simulate:function(e,t,n,r){var i=v.extend(new v.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?v.event.trigger(i,null,t):v.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},v.event.handle=v.event.dispatch,v.removeEvent=i.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]=="undefined"&&(e[r]=null),e.detachEvent(r,n))},v.Event=function(e,t){if(!(this instanceof v.Event))return new v.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?tt:et):this.type=e,t&&v.extend(this,t),this.timeStamp=e&&e.timeStamp||v.now(),this[v.expando]=!0},v.Event.prototype={preventDefault:function(){this.isDefaultPrevented=tt;var e=this.originalEvent;if(!e)return;e.preventDefault?e.preventDefault():e.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=tt;var e=this.originalEvent;if(!e)return;e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=tt,this.stopPropagation()},isDefaultPrevented:et,isPropagationStopped:et,isImmediatePropagationStopped:et},v.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){v.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,s=e.handleObj,o=s.selector;if(!i||i!==r&&!v.contains(r,i))e.type=s.origType,n=s.handler.apply(this,arguments),e.type=t;return n}}}),v.support.submitBubbles||(v.event.special.submit={setup:function(){if(v.nodeName(this,"form"))return!1;v.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=v.nodeName(n,"input")||v.nodeName(n,"button")?n.form:t;r&&!v._data(r,"_submit_attached")&&(v.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),v._data(r,"_submit_attached",!0))})},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&v.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){if(v.nodeName(this,"form"))return!1;v.event.remove(this,"._submit")}}),v.support.changeBubbles||(v.event.special.change={setup:function(){if($.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")v.event.add(this,"propertychange._change",function(e){e.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),v.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),v.event.simulate("change",this,e,!0)});return!1}v.event.add(this,"beforeactivate._change",function(e){var t=e.target;$.test(t.nodeName)&&!v._data(t,"_change_attached")&&(v.event.add(t,"change._change",function(e){this.parentNode&&!e.isSimulated&&!e.isTrigger&&v.event.simulate("change",this.parentNode,e,!0)}),v._data(t,"_change_attached",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||t.type!=="radio"&&t.type!=="checkbox")return e.handleObj.handler.apply(this,arguments)},teardown:function(){return v.event.remove(this,"._change"),!$.test(this.nodeName)}}),v.support.focusinBubbles||v.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){v.event.simulate(t,e.target,v.event.fix(e),!0)};v.event.special[t]={setup:function(){n++===0&&i.addEventListener(e,r,!0)},teardown:function(){--n===0&&i.removeEventListener(e,r,!0)}}}),v.fn.extend({on:function(e,n,r,i,s){var o,u;if(typeof e=="object"){typeof n!="string"&&(r=r||n,n=t);for(u in e)this.on(u,n,r,e[u],s);return this}r==null&&i==null?(i=n,r=n=t):i==null&&(typeof n=="string"?(i=r,r=t):(i=r,r=n,n=t));if(i===!1)i=et;else if(!i)return this;return s===1&&(o=i,i=function(e){return v().off(e),o.apply(this,arguments)},i.guid=o.guid||(o.guid=v.guid++)),this.each(function(){v.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,s;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,v(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if(typeof e=="object"){for(s in e)this.off(s,n,e[s]);return this}if(n===!1||typeof n=="function")r=n,n=t;return r===!1&&(r=et),this.each(function(){v.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},live:function(e,t,n){return v(this.context).on(e,this.selector,t,n),this},die:function(e,t){return v(this.context).off(e,this.selector||"**",t),this},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return arguments.length===1?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){v.event.trigger(e,t,this)})},triggerHandler:function(e,t){if(this[0])return v.event.trigger(e,t,this[0],!0)},toggle:function(e){var t=arguments,n=e.guid||v.guid++,r=0,i=function(n){var i=(v._data(this,"lastToggle"+e.guid)||0)%r;return v._data(this,"lastToggle"+e.guid,i+1),n.preventDefault(),t[i].apply(this,arguments)||!1};i.guid=n;while(r<t.length)t[r++].guid=n;return this.click(i)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),v.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){v.fn[t]=function(e,n){return n==null&&(n=e,e=null),arguments.length>0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u<a;u++)if(s=e[u])if(!n||n(s,r,i))o.push(s),f&&t.push(u);return o}function ct(e,t,n,r,i,s){return r&&!r[d]&&(r=ct(r)),i&&!i[d]&&(i=ct(i,s)),N(function(s,o,u,a){var f,l,c,h=[],p=[],d=o.length,v=s||dt(t||"*",u.nodeType?[u]:u,[]),m=e&&(s||!t)?lt(v,h,e,u,a):v,g=n?i||(s?e:d||r)?[]:o:m;n&&n(m,g,u,a);if(r){f=lt(g,p),r(f,[],u,a),l=f.length;while(l--)if(c=f[l])g[p[l]]=!(m[p[l]]=c)}if(s){if(i||e){if(i){f=[],l=g.length;while(l--)(c=g[l])&&f.push(m[l]=c);i(null,g=[],f,a)}l=g.length;while(l--)(c=g[l])&&(f=i?T.call(s,c):h[l])>-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a<s;a++)if(n=i.relative[e[a].type])h=[at(ft(h),n)];else{n=i.filter[e[a].type].apply(null,e[a].matches);if(n[d]){r=++a;for(;r<s;r++)if(i.relative[e[r].type])break;return ct(a>1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a<r&&ht(e.slice(a,r)),r<s&&ht(e=e.slice(r)),r<s&&e.join(""))}h.push(n)}return ft(h)}function pt(e,t){var r=t.length>0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r<i;r++)nt(e,t[r],n);return n}function vt(e,t,n,r,s){var o,u,f,l,c,h=ut(e),p=h.length;if(!r&&h.length===1){u=h[0]=h[0].slice(0);if(u.length>2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;t<n;t++)if(this[t]===e)return t;return-1},N=function(e,t){return e[d]=t==null||t,e},C=function(){var e={},t=[];return N(function(n,r){return t.push(n)>i.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="<a name='"+d+"'></a><div name='"+d+"'></div>",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:st(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:st(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},f=y.compareDocumentPosition?function(e,t){return e===t?(l=!0,0):(!e.compareDocumentPosition||!t.compareDocumentPosition?e.compareDocumentPosition:e.compareDocumentPosition(t)&4)?-1:1}:function(e,t){if(e===t)return l=!0,0;if(e.sourceIndex&&t.sourceIndex)return e.sourceIndex-t.sourceIndex;var n,r,i=[],s=[],o=e.parentNode,u=t.parentNode,a=o;if(o===u)return ot(e,t);if(!o)return-1;if(!u)return 1;while(a)i.unshift(a),a=a.parentNode;a=u;while(a)s.unshift(a),a=a.parentNode;n=i.length,r=s.length;for(var f=0;f<n&&f<r;f++)if(i[f]!==s[f])return ot(i[f],s[f]);return f===n?ot(e,s[f],-1):ot(i[f],t,1)},[0,0].sort(f),h=!l,nt.uniqueSort=function(e){var t,n=[],r=1,i=0;l=h,e.sort(f);if(l){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e},nt.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},a=nt.compile=function(e,t){var n,r=[],i=[],s=A[d][e+" "];if(!s){t||(t=ut(e)),n=t.length;while(n--)s=ht(t[n]),s[d]?r.push(s):i.push(s);s=A(e,pt(i,r))}return s},g.querySelectorAll&&function(){var e,t=vt,n=/'|\\/g,r=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,i=[":focus"],s=[":active"],u=y.matchesSelector||y.mozMatchesSelector||y.webkitMatchesSelector||y.oMatchesSelector||y.msMatchesSelector;K(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="<p test=''></p>",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="<input type='hidden'/>",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t<n;t++)if(v.contains(u[t],this))return!0});o=this.pushStack("","find",e);for(t=0,n=this.length;t<n;t++){r=o.length,v.find(e,this[t],o);if(t>0)for(i=r;i<o.length;i++)for(s=0;s<r;s++)if(o[s]===o[i]){o.splice(i--,1);break}}return o},has:function(e){var t,n=v(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(v.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1),"not",e)},filter:function(e){return this.pushStack(ft(this,e,!0),"filter",e)},is:function(e){return!!e&&(typeof e=="string"?st.test(e)?v(e,this.context).index(this[0])>=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r<i;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&n.nodeType!==11){if(o?o.index(n)>-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/<tbody/i,gt=/<|&#?\w+;/,yt=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,wt=new RegExp("<(?:"+ct+")[\\s/>]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,Nt={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X<div>","</div>"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1></$2>");try{for(;r<i;r++)n=this[r]||{},n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),n.innerHTML=e);n=0}catch(s){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){return ut(this[0])?this.length?this.pushStack(v(v.isFunction(e)?e():e),"replaceWith",e):this:v.isFunction(e)?this.each(function(t){var n=v(this),r=n.html();n.replaceWith(e.call(this,t,r))}):(typeof e!="string"&&(e=v(e).detach()),this.each(function(){var t=this.nextSibling,n=this.parentNode;v(this).remove(),t?v(t).before(e):v(n).append(e)}))},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=[].concat.apply([],e);var i,s,o,u,a=0,f=e[0],l=[],c=this.length;if(!v.support.checkClone&&c>1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a<c;a++)r.call(n&&v.nodeName(this[a],"table")?Lt(this[a],"tbody"):this[a],a===u?o:v.clone(o,!0,!0))}o=s=null,l.length&&v.each(l,function(e,t){t.src?v.ajax?v.ajax({url:t.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):v.error("no ajax"):v.globalEval((t.text||t.textContent||t.innerHTML||"").replace(Tt,"")),t.parentNode&&t.parentNode.removeChild(t)})}return this}}),v.buildFragment=function(e,n,r){var s,o,u,a=e[0];return n=n||i,n=!n.nodeType&&n[0]||n,n=n.ownerDocument||n,e.length===1&&typeof a=="string"&&a.length<512&&n===i&&a.charAt(0)==="<"&&!bt.test(a)&&(v.support.checkClone||!St.test(a))&&(v.support.html5Clone||!wt.test(a))&&(o=!0,s=v.fragments[a],u=s!==t),s||(s=n.createDocumentFragment(),v.clean(e,n,s,r),o&&(v.fragments[a]=u&&s)),{fragment:s,cacheable:o}},v.fragments={},v.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){v.fn[e]=function(n){var r,i=0,s=[],o=v(n),u=o.length,a=this.length===1&&this[0].parentNode;if((a==null||a&&a.nodeType===11&&a.childNodes.length===1)&&u===1)return o[t](this[0]),this;for(;i<u;i++)r=(i>0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1></$2>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]==="<table>"&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("<div>").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r<i;r++)n=e[r],Vn[n]=Vn[n]||[],Vn[n].unshift(t)},prefilter:function(e,t){t?Xn.unshift(e):Xn.push(e)}}),v.Tween=Yn,Yn.prototype={constructor:Yn,init:function(e,t,n,r,i,s){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=s||(v.cssNumber[n]?"":"px")},cur:function(){var e=Yn.propHooks[this.prop];return e&&e.get?e.get(this):Yn.propHooks._default.get(this)},run:function(e){var t,n=Yn.propHooks[this.prop];return this.options.duration?this.pos=t=v.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):Yn.propHooks._default.set(this),this}},Yn.prototype.init.prototype=Yn.prototype,Yn.propHooks={_default:{get:function(e){var t;return e.elem[e.prop]==null||!!e.elem.style&&e.elem.style[e.prop]!=null?(t=v.css(e.elem,e.prop,!1,""),!t||t==="auto"?0:t):e.elem[e.prop]},set:function(e){v.fx.step[e.prop]?v.fx.step[e.prop](e):e.elem.style&&(e.elem.style[v.cssProps[e.prop]]!=null||v.cssHooks[e.prop])?v.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},Yn.propHooks.scrollTop=Yn.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},v.each(["toggle","show","hide"],function(e,t){var n=v.fn[t];v.fn[t]=function(r,i,s){return r==null||typeof r=="boolean"||!e&&v.isFunction(r)&&v.isFunction(i)?n.apply(this,arguments):this.animate(Zn(t,!0),r,i,s)}}),v.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Gt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=v.isEmptyObject(e),s=v.speed(t,n,r),o=function(){var t=Kn(this,v.extend({},e),s);i&&t.stop(!0)};return i||s.queue===!1?this.each(o):this.queue(s.queue,o)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return typeof e!="string"&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=e!=null&&e+"queueHooks",s=v.timers,o=v._data(this);if(n)o[n]&&o[n].stop&&i(o[n]);else for(n in o)o[n]&&o[n].stop&&Wn.test(n)&&i(o[n]);for(n=s.length;n--;)s[n].elem===this&&(e==null||s[n].queue===e)&&(s[n].anim.stop(r),t=!1,s.splice(n,1));(t||!r)&&v.dequeue(this,e)})}}),v.each({slideDown:Zn("show"),slideUp:Zn("hide"),slideToggle:Zn("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){v.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),v.speed=function(e,t,n){var r=e&&typeof e=="object"?v.extend({},e):{complete:n||!n&&t||v.isFunction(e)&&e,duration:e,easing:n&&t||t&&!v.isFunction(t)&&t};r.duration=v.fx.off?0:typeof r.duration=="number"?r.duration:r.duration in v.fx.speeds?v.fx.speeds[r.duration]:v.fx.speeds._default;if(r.queue==null||r.queue===!0)r.queue="fx";return r.old=r.complete,r.complete=function(){v.isFunction(r.old)&&r.old.call(this),r.queue&&v.dequeue(this,r.queue)},r},v.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},v.timers=[],v.fx=Yn.prototype.init,v.fx.tick=function(){var e,n=v.timers,r=0;qn=v.now();for(;r<n.length;r++)e=n[r],!e()&&n[r]===e&&n.splice(r--,1);n.length||v.fx.stop(),qn=t},v.fx.timer=function(e){e()&&v.timers.push(e)&&!Rn&&(Rn=setInterval(v.fx.tick,v.fx.interval))},v.fx.interval=13,v.fx.stop=function(){clearInterval(Rn),Rn=null},v.fx.speeds={slow:600,fast:200,_default:400},v.fx.step={},v.expr&&v.expr.filters&&(v.expr.filters.animated=function(e){return v.grep(v.timers,function(t){return e===t.elem}).length});var er=/^(?:body|html)$/i;v.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){v.offset.setOffset(this,e,t)});var n,r,i,s,o,u,a,f={top:0,left:0},l=this[0],c=l&&l.ownerDocument;if(!c)return;return(r=c.body)===l?v.offset.bodyOffset(l):(n=c.documentElement,v.contains(n,l)?(typeof l.getBoundingClientRect!="undefined"&&(f=l.getBoundingClientRect()),i=tr(c),s=n.clientTop||r.clientTop||0,o=n.clientLeft||r.clientLeft||0,u=i.pageYOffset||n.scrollTop,a=i.pageXOffset||n.scrollLeft,{top:f.top+u-s,left:f.left+a-o}):f)},v.offset={bodyOffset:function(e){var t=e.offsetTop,n=e.offsetLeft;return v.support.doesNotIncludeMarginInBodyOffset&&(t+=parseFloat(v.css(e,"marginTop"))||0,n+=parseFloat(v.css(e,"marginLeft"))||0),{top:t,left:n}},setOffset:function(e,t,n){var r=v.css(e,"position");r==="static"&&(e.style.position="relative");var i=v(e),s=i.offset(),o=v.css(e,"top"),u=v.css(e,"left"),a=(r==="absolute"||r==="fixed")&&v.inArray("auto",[o,u])>-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); \ No newline at end of file
+/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="<select msallowclip=''><option selected=''></option></select>",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=lb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=mb(b);function pb(){}pb.prototype=d.filters=d.pseudos,d.setFilters=new pb,g=fb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fb.error(a):z(a,i).slice(0)};function qb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;
+if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==cb()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===cb()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ab:bb):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:bb,isPropagationStopped:bb,isImmediatePropagationStopped:bb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ab,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ab,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ab,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=bb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=bb),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function db(a){var b=eb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var eb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fb=/ jQuery\d+="(?:null|\d+)"/g,gb=new RegExp("<(?:"+eb+")[\\s/>]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/<tbody/i,lb=/<|&#?\w+;/,mb=/<(?:script|style|link)/i,nb=/checked\s*(?:[^=]|=\s*.checked.)/i,ob=/^$|\/(?:java|ecma)script/i,pb=/^true\/(.*)/,qb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,rb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"<table>"!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Cb[0].contentWindow||Cb[0].contentDocument).document,b.write(),b.close(),c=Eb(a,b),Cb.detach()),Db[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Gb=/^margin/,Hb=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ib,Jb,Kb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ib=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Hb.test(g)&&Gb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ib=function(a){return a.currentStyle},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Hb.test(g)&&!Kb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Lb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Mb=/alpha\([^)]*\)/i,Nb=/opacity\s*=\s*([^)]*)/,Ob=/^(none|table(?!-c[ea]).+)/,Pb=new RegExp("^("+S+")(.*)$","i"),Qb=new RegExp("^([+-])=("+S+")","i"),Rb={position:"absolute",visibility:"hidden",display:"block"},Sb={letterSpacing:"0",fontWeight:"400"},Tb=["Webkit","O","Moz","ms"];function Ub(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Tb.length;while(e--)if(b=Tb[e]+c,b in a)return b;return d}function Vb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fb(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wb(a,b,c){var d=Pb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Yb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ib(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Jb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Hb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xb(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Jb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ub(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ub(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Jb(a,b,d)),"normal"===f&&b in Sb&&(f=Sb[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Ob.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Rb,function(){return Yb(a,b,d)}):Yb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ib(a);return Wb(a,c,d?Xb(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Nb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Mb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Mb.test(f)?f.replace(Mb,e):f+" "+e)}}),m.cssHooks.marginRight=Lb(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Jb,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Gb.test(a)||(m.cssHooks[a+b].set=Wb)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ib(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Vb(this,!0)},hide:function(){return Vb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Zb(a,b,c,d,e){return new Zb.prototype.init(a,b,c,d,e)}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")
+},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(a,b){b?dc.unshift(a):dc.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kc(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gc(b,!0),a,d,e)}}),m.each({slideDown:gc("show"),slideUp:gc("hide"),slideToggle:gc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($b=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$b=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_b||(_b=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_b),_b=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lc=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mc,nc,oc=m.expr.attrHandle,pc=/^(?:checked|selected)$/i,qc=k.getSetAttribute,rc=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nc:mc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rc&&qc||!pc.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qc?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nc={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rc&&qc||!pc.test(c)?a.setAttribute(!qc&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=oc[b]||m.find.attr;oc[b]=rc&&qc||!pc.test(b)?function(a,b,d){var e,f;return d||(f=oc[b],oc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,oc[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rc&&qc||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mc&&mc.set(a,b,c)}}),qc||(mc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},oc.id=oc.name=oc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mc.set},m.attrHooks.contenteditable={set:function(a,b,c){mc.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sc=/^(?:input|select|textarea|button|object)$/i,tc=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sc.test(a.nodeName)||tc.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var uc=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(uc," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vc=m.now(),wc=/\?/,xc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yc,zc,Ac=/#.*$/,Bc=/([?&])_=[^&]*/,Cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Dc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ec=/^(?:GET|HEAD)$/,Fc=/^\/\//,Gc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hc={},Ic={},Jc="*/".concat("*");try{zc=location.href}catch(Kc){zc=y.createElement("a"),zc.href="",zc=zc.href}yc=Gc.exec(zc.toLowerCase())||[];function Lc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mc(a,b,c,d){var e={},f=a===Ic;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nc(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Oc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zc,type:"GET",isLocal:Dc.test(yc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nc(Nc(a,m.ajaxSettings),b):Nc(m.ajaxSettings,a)},ajaxPrefilter:Lc(Hc),ajaxTransport:Lc(Ic),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zc)+"").replace(Ac,"").replace(Fc,yc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yc[1]&&c[2]===yc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yc[3]||("http:"===yc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mc(Hc,k,b,v),2===t)return v;h=k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Ec.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bc.test(e)?e.replace(Bc,"$1_="+vc++):e+(wc.test(e)?"&":"?")+"_="+vc++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mc(Ic,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Oc(k,v,c)),u=Pc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qc=/%20/g,Rc=/\[\]$/,Sc=/\r?\n/g,Tc=/^(?:submit|button|image|reset|file)$/i,Uc=/^(?:input|select|textarea|keygen)/i;function Vc(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rc.test(a)?d(a,e):Vc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vc(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vc(c,a[c],b,e);return d.join("&").replace(Qc,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Uc.test(this.nodeName)&&!Tc.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sc,"\r\n")}}):{name:b.name,value:c.replace(Sc,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zc()||$c()}:Zc;var Wc=0,Xc={},Yc=m.ajaxSettings.xhr();a.ActiveXObject&&m(a).on("unload",function(){for(var a in Xc)Xc[a](void 0,!0)}),k.cors=!!Yc&&"withCredentials"in Yc,Yc=k.ajax=!!Yc,Yc&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xc[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zc(){try{return new a.XMLHttpRequest}catch(b){}}function $c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _c=[],ad=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_c.pop()||m.expando+"_"+vc++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ad.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ad.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ad,"$1"+e):b.jsonp!==!1&&(b.url+=(wc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_c.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bd=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bd)return bd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m});
diff --git a/sphinx/themes/basic/static/minus.png b/sphinx/themes/basic/static/minus.png
index da1c5620..0f22b16b 100644
--- a/sphinx/themes/basic/static/minus.png
+++ b/sphinx/themes/basic/static/minus.png
Binary files differ
diff --git a/sphinx/themes/basic/static/plus.png b/sphinx/themes/basic/static/plus.png
index b3cb3742..0cfe084c 100644
--- a/sphinx/themes/basic/static/plus.png
+++ b/sphinx/themes/basic/static/plus.png
Binary files differ
diff --git a/sphinx/themes/basic/static/underscore-1.3.1.js b/sphinx/themes/basic/static/underscore-1.3.1.js
new file mode 100644
index 00000000..208d4cd8
--- /dev/null
+++ b/sphinx/themes/basic/static/underscore-1.3.1.js
@@ -0,0 +1,999 @@
+// Underscore.js 1.3.1
+// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the MIT license.
+// Portions of Underscore are inspired or borrowed from Prototype,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `global` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Establish the object that gets returned to break out of a loop iteration.
+ var breaker = {};
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var slice = ArrayProto.slice,
+ unshift = ArrayProto.unshift,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeForEach = ArrayProto.forEach,
+ nativeMap = ArrayProto.map,
+ nativeReduce = ArrayProto.reduce,
+ nativeReduceRight = ArrayProto.reduceRight,
+ nativeFilter = ArrayProto.filter,
+ nativeEvery = ArrayProto.every,
+ nativeSome = ArrayProto.some,
+ nativeIndexOf = ArrayProto.indexOf,
+ nativeLastIndexOf = ArrayProto.lastIndexOf,
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind;
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) { return new wrapper(obj); };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object via a string identifier,
+ // for Closure Compiler "advanced" mode.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root['_'] = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.3.1';
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles objects with the built-in `forEach`, arrays, and raw objects.
+ // Delegates to **ECMAScript 5**'s native `forEach` if available.
+ var each = _.each = _.forEach = function(obj, iterator, context) {
+ if (obj == null) return;
+ if (nativeForEach && obj.forEach === nativeForEach) {
+ obj.forEach(iterator, context);
+ } else if (obj.length === +obj.length) {
+ for (var i = 0, l = obj.length; i < l; i++) {
+ if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
+ }
+ } else {
+ for (var key in obj) {
+ if (_.has(obj, key)) {
+ if (iterator.call(context, obj[key], key, obj) === breaker) return;
+ }
+ }
+ }
+ };
+
+ // Return the results of applying the iterator to each element.
+ // Delegates to **ECMAScript 5**'s native `map` if available.
+ _.map = _.collect = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+ each(obj, function(value, index, list) {
+ results[results.length] = iterator.call(context, value, index, list);
+ });
+ if (obj.length === +obj.length) results.length = obj.length;
+ return results;
+ };
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
+ _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduce && obj.reduce === nativeReduce) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+ }
+ each(obj, function(value, index, list) {
+ if (!initial) {
+ memo = value;
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, value, index, list);
+ }
+ });
+ if (!initial) throw new TypeError('Reduce of empty array with no initial value');
+ return memo;
+ };
+
+ // The right-associative version of reduce, also known as `foldr`.
+ // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
+ _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+ }
+ var reversed = _.toArray(obj).reverse();
+ if (context && !initial) iterator = _.bind(iterator, context);
+ return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
+ };
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, iterator, context) {
+ var result;
+ any(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ return true;
+ }
+ });
+ return result;
+ };
+
+ // Return all the elements that pass a truth test.
+ // Delegates to **ECMAScript 5**'s native `filter` if available.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+ each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ each(obj, function(value, index, list) {
+ if (!iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Delegates to **ECMAScript 5**'s native `every` if available.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, iterator, context) {
+ var result = true;
+ if (obj == null) return result;
+ if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+ each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+ });
+ return result;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Delegates to **ECMAScript 5**'s native `some` if available.
+ // Aliased as `any`.
+ var any = _.some = _.any = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
+ var result = false;
+ if (obj == null) return result;
+ if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+ each(obj, function(value, index, list) {
+ if (result || (result = iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+
+ // Determine if a given value is included in the array or object using `===`.
+ // Aliased as `contains`.
+ _.include = _.contains = function(obj, target) {
+ var found = false;
+ if (obj == null) return found;
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+ found = any(obj, function(value) {
+ return value === target;
+ });
+ return found;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ return _.map(obj, function(value) {
+ return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+
+ // Return the maximum element or (element-based computation).
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
+ if (!iterator && _.isEmpty(obj)) return -Infinity;
+ var result = {computed : -Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
+ if (!iterator && _.isEmpty(obj)) return Infinity;
+ var result = {computed : Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Shuffle an array.
+ _.shuffle = function(obj) {
+ var shuffled = [], rand;
+ each(obj, function(value, index, list) {
+ if (index == 0) {
+ shuffled[0] = value;
+ } else {
+ rand = Math.floor(Math.random() * (index + 1));
+ shuffled[index] = shuffled[rand];
+ shuffled[rand] = value;
+ }
+ });
+ return shuffled;
+ };
+
+ // Sort the object's values by a criterion produced by an iterator.
+ _.sortBy = function(obj, iterator, context) {
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }), 'value');
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = function(obj, val) {
+ var result = {};
+ var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
+ each(obj, function(value, index) {
+ var key = iterator(value, index);
+ (result[key] || (result[key] = [])).push(value);
+ });
+ return result;
+ };
+
+ // Use a comparator function to figure out at what index an object should
+ // be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator) {
+ iterator || (iterator = _.identity);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >> 1;
+ iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+
+ // Safely convert anything iterable into a real, live array.
+ _.toArray = function(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ if (_.isArray(iterable)) return slice.call(iterable);
+ if (_.isArguments(iterable)) return slice.call(iterable);
+ return _.values(iterable);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ return _.toArray(obj).length;
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head`. The **guard** check allows it to work
+ // with `_.map`.
+ _.first = _.head = function(array, n, guard) {
+ return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+ };
+
+ // Returns everything but the last entry of the array. Especcialy useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N. The **guard** check allows it to work with
+ // `_.map`.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array. The **guard** check allows it to work with `_.map`.
+ _.last = function(array, n, guard) {
+ if ((n != null) && !guard) {
+ return slice.call(array, Math.max(array.length - n, 0));
+ } else {
+ return array[array.length - 1];
+ }
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail`.
+ // Especially useful on the arguments object. Passing an **index** will return
+ // the rest of the values in the array from that index onward. The **guard**
+ // check allows it to work with `_.map`.
+ _.rest = _.tail = function(array, index, guard) {
+ return slice.call(array, (index == null) || guard ? 1 : index);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, function(value){ return !!value; });
+ };
+
+ // Return a completely flattened version of an array.
+ _.flatten = function(array, shallow) {
+ return _.reduce(array, function(memo, value) {
+ if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
+ memo[memo.length] = value;
+ return memo;
+ }, []);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iterator) {
+ var initial = iterator ? _.map(array, iterator) : array;
+ var result = [];
+ _.reduce(initial, function(memo, el, i) {
+ if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
+ memo[memo.length] = el;
+ result[result.length] = array[i];
+ }
+ return memo;
+ }, []);
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(_.flatten(arguments, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays. (Aliased as "intersect" for back-compat.)
+ _.intersection = _.intersect = function(array) {
+ var rest = slice.call(arguments, 1);
+ return _.filter(_.uniq(array), function(item) {
+ return _.every(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = _.flatten(slice.call(arguments, 1));
+ return _.filter(array, function(value){ return !_.include(rest, value); });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ var args = slice.call(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
+ return results;
+ };
+
+ // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
+ // we need this function. Return the position of the first occurrence of an
+ // item in an array, or -1 if the item is not included in the array.
+ // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = function(array, item, isSorted) {
+ if (array == null) return -1;
+ var i, l;
+ if (isSorted) {
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
+ }
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
+ for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
+ return -1;
+ };
+
+ // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
+ _.lastIndexOf = function(array, item) {
+ if (array == null) return -1;
+ if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
+ var i = array.length;
+ while (i--) if (i in array && array[i] === item) return i;
+ return -1;
+ };
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (arguments.length <= 1) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = arguments[2] || 1;
+
+ var len = Math.max(Math.ceil((stop - start) / step), 0);
+ var idx = 0;
+ var range = new Array(len);
+
+ while(idx < len) {
+ range[idx++] = start;
+ start += step;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Reusable constructor function for prototype setting.
+ var ctor = function(){};
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Binding with arguments is also known as `curry`.
+ // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
+ // We check for `func.bind` first, to fail fast when `func` is undefined.
+ _.bind = function bind(func, context) {
+ var bound, args;
+ if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError;
+ args = slice.call(arguments, 2);
+ return bound = function() {
+ if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
+ ctor.prototype = func.prototype;
+ var self = new ctor;
+ var result = func.apply(self, args.concat(slice.call(arguments)));
+ if (Object(result) === result) return result;
+ return self;
+ };
+ };
+
+ // Bind all of an object's methods to that object. Useful for ensuring that
+ // all callbacks defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var funcs = slice.call(arguments, 1);
+ if (funcs.length == 0) funcs = _.functions(obj);
+ each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memo = {};
+ hasher || (hasher = _.identity);
+ return function() {
+ var key = hasher.apply(this, arguments);
+ return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+ };
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){ return func.apply(func, args); }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+ };
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time.
+ _.throttle = function(func, wait) {
+ var context, args, timeout, throttling, more;
+ var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
+ return function() {
+ context = this; args = arguments;
+ var later = function() {
+ timeout = null;
+ if (more) func.apply(context, args);
+ whenDone();
+ };
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (throttling) {
+ more = true;
+ } else {
+ func.apply(context, args);
+ }
+ whenDone();
+ throttling = true;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds.
+ _.debounce = function(func, wait) {
+ var timeout;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ func.apply(context, args);
+ };
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = function(func) {
+ var ran = false, memo;
+ return function() {
+ if (ran) return memo;
+ ran = true;
+ return memo = func.apply(this, arguments);
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return function() {
+ var args = [func].concat(slice.call(arguments, 0));
+ return wrapper.apply(this, args);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var funcs = arguments;
+ return function() {
+ var args = arguments;
+ for (var i = funcs.length - 1; i >= 0; i--) {
+ args = [funcs[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ };
+
+ // Returns a function that will only be executed after being called N times.
+ _.after = function(times, func) {
+ if (times <= 0) return func();
+ return function() {
+ if (--times < 1) { return func.apply(this, arguments); }
+ };
+ };
+
+ // Object Functions
+ // ----------------
+
+ // Retrieve the names of an object's properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = nativeKeys || function(obj) {
+ if (obj !== Object(obj)) throw new TypeError('Invalid object');
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ return _.map(obj, _.identity);
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ for (var prop in source) {
+ obj[prop] = source[prop];
+ }
+ });
+ return obj;
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ for (var prop in source) {
+ if (obj[prop] == null) obj[prop] = source[prop];
+ }
+ });
+ return obj;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Internal recursive comparison function.
+ function eq(a, b, stack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
+ if (a === b) return a !== 0 || 1 / a == 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a._chain) a = a._wrapped;
+ if (b._chain) b = b._wrapped;
+ // Invoke a custom `isEqual` method if one is provided.
+ if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
+ if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className != toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, dates, and booleans are compared by value.
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return a == String(b);
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
+ // other numeric values.
+ return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a == +b;
+ // RegExps are compared by their source patterns and flags.
+ case '[object RegExp]':
+ return a.source == b.source &&
+ a.global == b.global &&
+ a.multiline == b.multiline &&
+ a.ignoreCase == b.ignoreCase;
+ }
+ if (typeof a != 'object' || typeof b != 'object') return false;
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+ var length = stack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (stack[length] == a) return true;
+ }
+ // Add the first object to the stack of traversed objects.
+ stack.push(a);
+ var size = 0, result = true;
+ // Recursively compare objects and arrays.
+ if (className == '[object Array]') {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ size = a.length;
+ result = size == b.length;
+ if (result) {
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (size--) {
+ // Ensure commutative equality for sparse arrays.
+ if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
+ }
+ }
+ } else {
+ // Objects with different constructors are not equivalent.
+ if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
+ // Deep compare objects.
+ for (var key in a) {
+ if (_.has(a, key)) {
+ // Count the expected number of properties.
+ size++;
+ // Deep compare each member.
+ if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
+ }
+ }
+ // Ensure that both objects contain the same number of properties.
+ if (result) {
+ for (key in b) {
+ if (_.has(b, key) && !(size--)) break;
+ }
+ result = !size;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ stack.pop();
+ return result;
+ }
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b, []);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+ for (var key in obj) if (_.has(obj, key)) return false;
+ return true;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType == 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) == '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ return obj === Object(obj);
+ };
+
+ // Is a given variable an arguments object?
+ _.isArguments = function(obj) {
+ return toString.call(obj) == '[object Arguments]';
+ };
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return !!(obj && _.has(obj, 'callee'));
+ };
+ }
+
+ // Is a given value a function?
+ _.isFunction = function(obj) {
+ return toString.call(obj) == '[object Function]';
+ };
+
+ // Is a given value a string?
+ _.isString = function(obj) {
+ return toString.call(obj) == '[object String]';
+ };
+
+ // Is a given value a number?
+ _.isNumber = function(obj) {
+ return toString.call(obj) == '[object Number]';
+ };
+
+ // Is the given value `NaN`?
+ _.isNaN = function(obj) {
+ // `NaN` is the only value for which `===` is not reflexive.
+ return obj !== obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
+ };
+
+ // Is a given value a date?
+ _.isDate = function(obj) {
+ return toString.call(obj) == '[object Date]';
+ };
+
+ // Is the given value a regular expression?
+ _.isRegExp = function(obj) {
+ return toString.call(obj) == '[object RegExp]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Has own property?
+ _.has = function(obj, key) {
+ return hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iterators.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Run a function **n** times.
+ _.times = function (n, iterator, context) {
+ for (var i = 0; i < n; i++) iterator.call(context, i);
+ };
+
+ // Escape a string for HTML interpolation.
+ _.escape = function(string) {
+ return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
+ };
+
+ // Add your own custom functions to the Underscore object, ensuring that
+ // they're correctly added to the OOP wrapper as well.
+ _.mixin = function(obj) {
+ each(_.functions(obj), function(name){
+ addToWrapper(name, _[name] = obj[name]);
+ });
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = idCounter++;
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /.^/;
+
+ // Within an interpolation, evaluation, or escaping, remove HTML escaping
+ // that had been previously added.
+ var unescape = function(code) {
+ return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ _.template = function(str, data) {
+ var c = _.templateSettings;
+ var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
+ 'with(obj||{}){__p.push(\'' +
+ str.replace(/\\/g, '\\\\')
+ .replace(/'/g, "\\'")
+ .replace(c.escape || noMatch, function(match, code) {
+ return "',_.escape(" + unescape(code) + "),'";
+ })
+ .replace(c.interpolate || noMatch, function(match, code) {
+ return "'," + unescape(code) + ",'";
+ })
+ .replace(c.evaluate || noMatch, function(match, code) {
+ return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
+ })
+ .replace(/\r/g, '\\r')
+ .replace(/\n/g, '\\n')
+ .replace(/\t/g, '\\t')
+ + "');}return __p.join('');";
+ var func = new Function('obj', '_', tmpl);
+ if (data) return func(data, _);
+ return function(data) {
+ return func.call(this, data, _);
+ };
+ };
+
+ // Add a "chain" function, which will delegate to the wrapper.
+ _.chain = function(obj) {
+ return _(obj).chain();
+ };
+
+ // The OOP Wrapper
+ // ---------------
+
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+ var wrapper = function(obj) { this._wrapped = obj; };
+
+ // Expose `wrapper.prototype` as `_.prototype`
+ _.prototype = wrapper.prototype;
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(obj, chain) {
+ return chain ? _(obj).chain() : obj;
+ };
+
+ // A method to easily add functions to the OOP wrapper.
+ var addToWrapper = function(name, func) {
+ wrapper.prototype[name] = function() {
+ var args = slice.call(arguments);
+ unshift.call(args, this._wrapped);
+ return result(func.apply(_, args), this._chain);
+ };
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ wrapper.prototype[name] = function() {
+ var wrapped = this._wrapped;
+ method.apply(wrapped, arguments);
+ var length = wrapped.length;
+ if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
+ return result(wrapped, this._chain);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ wrapper.prototype[name] = function() {
+ return result(method.apply(this._wrapped, arguments), this._chain);
+ };
+ });
+
+ // Start chaining a wrapped Underscore object.
+ wrapper.prototype.chain = function() {
+ this._chain = true;
+ return this;
+ };
+
+ // Extracts the result from a wrapped and chained object.
+ wrapper.prototype.value = function() {
+ return this._wrapped;
+ };
+
+}).call(this);
diff --git a/sphinx/themes/basic/static/up-pressed.png b/sphinx/themes/basic/static/up-pressed.png
index 8bd587af..99e72109 100644
--- a/sphinx/themes/basic/static/up-pressed.png
+++ b/sphinx/themes/basic/static/up-pressed.png
Binary files differ
diff --git a/sphinx/themes/basic/static/up.png b/sphinx/themes/basic/static/up.png
index b9462568..26de002e 100644
--- a/sphinx/themes/basic/static/up.png
+++ b/sphinx/themes/basic/static/up.png
Binary files differ
diff --git a/sphinx/themes/basic/static/websupport.js b/sphinx/themes/basic/static/websupport.js
index 71c0a136..79ed10e2 100644
--- a/sphinx/themes/basic/static/websupport.js
+++ b/sphinx/themes/basic/static/websupport.js
@@ -50,51 +50,51 @@
}
function initEvents() {
- $('a.comment-close').live("click", function(event) {
+ $(document).on("click", 'a.comment-close', function(event) {
event.preventDefault();
hide($(this).attr('id').substring(2));
});
- $('a.vote').live("click", function(event) {
+ $(document).on("click", 'a.vote', function(event) {
event.preventDefault();
handleVote($(this));
});
- $('a.reply').live("click", function(event) {
+ $(document).on("click", 'a.reply', function(event) {
event.preventDefault();
openReply($(this).attr('id').substring(2));
});
- $('a.close-reply').live("click", function(event) {
+ $(document).on("click", 'a.close-reply', function(event) {
event.preventDefault();
closeReply($(this).attr('id').substring(2));
});
- $('a.sort-option').live("click", function(event) {
+ $(document).on("click", 'a.sort-option', function(event) {
event.preventDefault();
handleReSort($(this));
});
- $('a.show-proposal').live("click", function(event) {
+ $(document).on("click", 'a.show-proposal', function(event) {
event.preventDefault();
showProposal($(this).attr('id').substring(2));
});
- $('a.hide-proposal').live("click", function(event) {
+ $(document).on("click", 'a.hide-proposal', function(event) {
event.preventDefault();
hideProposal($(this).attr('id').substring(2));
});
- $('a.show-propose-change').live("click", function(event) {
+ $(document).on("click", 'a.show-propose-change', function(event) {
event.preventDefault();
showProposeChange($(this).attr('id').substring(2));
});
- $('a.hide-propose-change').live("click", function(event) {
+ $(document).on("click", 'a.hide-propose-change', function(event) {
event.preventDefault();
hideProposeChange($(this).attr('id').substring(2));
});
- $('a.accept-comment').live("click", function(event) {
+ $(document).on("click", 'a.accept-comment', function(event) {
event.preventDefault();
acceptComment($(this).attr('id').substring(2));
});
- $('a.delete-comment').live("click", function(event) {
+ $(document).on("click", 'a.delete-comment', function(event) {
event.preventDefault();
deleteComment($(this).attr('id').substring(2));
});
- $('a.comment-markup').live("click", function(event) {
+ $(document).on("click", 'a.comment-markup', function(event) {
event.preventDefault();
toggleCommentMarkupBox($(this).attr('id').substring(2));
});
@@ -700,8 +700,8 @@
(<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>\
+ <code>``code``</code>, \
+ code blocks: <code>::</code> and an indented block after blank line</div>\
<form method="post" id="cf<%id%>" class="comment-form" action="">\
<textarea name="comment" cols="80"></textarea>\
<p class="propose-button">\
diff --git a/sphinx/themes/bizstyle/layout.html b/sphinx/themes/bizstyle/layout.html
new file mode 100644
index 00000000..de2754fe
--- /dev/null
+++ b/sphinx/themes/bizstyle/layout.html
@@ -0,0 +1,28 @@
+{#
+ bizstyle/layout.html
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the bizstyle theme.
+
+ :copyright: Copyright 2011-2014 by Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{% extends "basic/layout.html" %}
+
+{% set script_files = script_files + ["_static/bizstyle.js"] %}
+
+{# put the sidebar before the body #}
+{% block sidebar1 %}{{ sidebar() }}{% endblock %}
+{% block sidebar2 %}{% endblock %}
+
+{# doctype override #}
+{%- block doctype %}
+<!doctype html>
+{%- endblock %}
+
+{%- block extrahead %}
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
+ <!--[if lt IE 9]>
+ <script type="text/javascript" src="_static/css3-mediaqueries.js"></script>
+ <![endif]-->
+{%- endblock %}
diff --git a/sphinx/themes/bizstyle/static/background_b01.png b/sphinx/themes/bizstyle/static/background_b01.png
new file mode 100644
index 00000000..d262745b
--- /dev/null
+++ b/sphinx/themes/bizstyle/static/background_b01.png
Binary files differ
diff --git a/sphinx/themes/bizstyle/static/bizstyle.css_t b/sphinx/themes/bizstyle/static/bizstyle.css_t
new file mode 100644
index 00000000..2b3964c2
--- /dev/null
+++ b/sphinx/themes/bizstyle/static/bizstyle.css_t
@@ -0,0 +1,487 @@
+/*
+ * bizstyle.css_t
+ * ~~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- business style theme.
+ *
+ * :copyright: Copyright 2011-2014 by Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+@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: white;
+ background-image: url(background_b01.png);
+ color: black;
+ padding: 0;
+ border-right: 1px solid {{ theme_maincolor }};
+ border-left: 1px solid {{ theme_maincolor }};
+
+ margin: 0px 40px 0px 40px;
+}
+
+div.document {
+ background-color: white;
+ text-align: left;
+ background-repeat: repeat-x;
+
+ -moz-box-shadow: 2px 2px 5px #000;
+ -webkit-box-shadow: 2px 2px 5px #000;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 240px;
+ border-left: 1px solid #ccc;
+}
+
+div.body {
+ margin: 0;
+ padding: 0.5em 20px 20px 20px;
+}
+
+{%- if theme_rightsidebar|tobool %}
+div.bodywrapper {
+ margin: 0 240px 0 0;
+ border-right: 1px solid #ccc;
+}
+{%- endif %}
+
+div.related {
+ font-size: 1em;
+
+ -moz-box-shadow: 2px 2px 5px #000;
+ -webkit-box-shadow: 2px 2px 5px #000;
+}
+
+div.related ul {
+ background-color: {{ theme_maincolor }};
+ height: 2em;
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+}
+
+div.related ul li {
+ color: white;
+ 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: #fff;
+}
+
+div.related ul li a:hover {
+ color: #fff;
+ text-decoration: underline;
+}
+
+div.sphinxsidebarwrapper {
+ padding: 0;
+}
+
+div.sphinxsidebar {
+ margin: 0;
+ padding: 0.5em 12px 12px 12px;
+ width: 210px;
+ {%- if theme_rightsidebar|tobool %}
+ float: right;
+ {%- endif %}
+ 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 {{ theme_maincolor }};
+ background-color: {{ theme_maincolor }};
+}
+
+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.sphinxsidebar input {
+ border: 1px solid {{ theme_maincolor }};
+}
+
+div.footer {
+ background-color: white;
+ color: {{ theme_maincolor }};
+ padding: 3px 8px 3px 0;
+ clear: both;
+ font-size: 0.8em;
+ text-align: right;
+ border-bottom: 1px solid {{ theme_maincolor }};
+
+ -moz-box-shadow: 2px 2px 5px #000;
+ -webkit-box-shadow: 2px 2px 5px #000;
+}
+
+div.footer a {
+ color: {{ theme_maincolor }};
+ text-decoration: underline;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+p {
+ margin: 0.8em 0 0.5em 0;
+}
+
+a {
+ color: {{ theme_maincolor }};
+ text-decoration: none;
+}
+
+a:hover {
+ color: {{ theme_maincolor }};
+ text-decoration: underline;
+}
+
+div.body a {
+ text-decoration: underline;
+}
+
+h1, h2, h3 {
+ color: {{ theme_maincolor }};
+}
+
+h1 {
+ margin: 0;
+ padding: 0.7em 0 0.3em 0;
+ font-size: 1.5em;
+}
+
+h2 {
+ margin: 1.3em 0 0.2em 0;
+ font-size: 1.35em;
+ padding-bottom: .5em;
+ border-bottom: 1px solid {{ theme_maincolor }};
+}
+
+h3 {
+ margin: 1em 0 -0.3em 0;
+ font-size: 1.2em;
+ padding-bottom: .3em;
+ border-bottom: 1px solid #CCCCCC;
+}
+
+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;
+}
+
+code {
+ background-color: #F2F2F2;
+ border-bottom: 1px solid #ddd;
+ color: #333;
+}
+
+code.descname, code.descclassname, code.xref {
+ border: 0;
+}
+
+hr {
+ border: 1px solid #abc;
+ margin: 2em;
+}
+
+a code {
+ border: 0;
+ color: #CA7900;
+}
+
+a code: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-right: 5px solid #ccc;
+ border-left: 5px solid #ccc;
+}
+
+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 {
+ font-size: 0.9em;
+ margin: 1em 0 1em 0;
+ border: 3px solid #cccccc;
+ background-color: #f7f7f7;
+ padding: 0;
+}
+
+div.admonition p {
+ margin: 0.5em 1em 0.5em 1em;
+ padding: 0;
+}
+
+div.admonition li p {
+ margin-left: 0;
+}
+
+div.admonition pre, div.warning pre {
+ margin: 0.4em 1em 0.4em 1em;
+}
+
+div.admonition p.admonition-title {
+ margin: 0;
+ padding: 0.1em 0 0.1em 0.5em;
+ color: white;
+ border-bottom: 3px solid #cccccc;
+ font-weight: bold;
+ background-color: #165e83;
+}
+
+div.danger { border: 3px solid #f0908d; background-color: #f0cfa0; }
+div.error { border: 3px solid #f0908d; background-color: #ede4cd; }
+div.warning { border: 3px solid #f8b862; background-color: #f0cfa0; }
+div.caution { border: 3px solid #f8b862; background-color: #ede4cd; }
+div.attention { border: 3px solid #f8b862; background-color: #f3f3f3; }
+div.important { border: 3px solid #f0cfa0; background-color: #ede4cd; }
+div.note { border: 3px solid #f0cfa0; background-color: #f3f3f3; }
+div.hint { border: 3px solid #bed2c3; background-color: #f3f3f3; }
+div.tip { border: 3px solid #bed2c3; background-color: #f3f3f3; }
+
+div.danger p.admonition-title, div.error p.admonition-title {
+ background-color: #b7282e;
+ border-bottom: 3px solid #f0908d;
+}
+
+div.caution p.admonition-title,
+div.warning p.admonition-title,
+div.attention p.admonition-title {
+ background-color: #f19072;
+ border-bottom: 3px solid #f8b862;
+}
+
+div.note p.admonition-title, div.important p.admonition-title {
+ background-color: #f8b862;
+ border-bottom: 3px solid #f0cfa0;
+}
+
+div.hint p.admonition-title, div.tip p.admonition-title {
+ background-color: #7ebea5;
+ border-bottom: 3px solid #bed2c3;
+}
+
+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;
+}
+
+p.versionchanged span.versionmodified {
+ font-size: 0.9em;
+ margin-right: 0.2em;
+ padding: 0.1em;
+ background-color: #DCE6A0;
+}
+
+/* -- table styles ---------------------------------------------------------- */
+
+table.docutils {
+ margin: 1em 0;
+ padding: 0;
+ border: 1px solid white;
+ background-color: #f7f7f7;
+}
+
+table.docutils td, table.docutils th {
+ padding: 1px 8px 1px 5px;
+ border-top: 0;
+ border-left: 0;
+ border-right: 1px solid white;
+ border-bottom: 1px solid white;
+}
+
+table.docutils td p {
+ margin-top: 0;
+ margin-bottom: 0.3em;
+}
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+ word-break: break-word;
+}
+
+table.footnote td, table.footnote th {
+ border: 0 !important;
+}
+
+th {
+ color: white;
+ text-align: left;
+ padding-right: 5px;
+ background-color: #82A0BE;
+}
+
+/* WIDE DESKTOP STYLE */
+@media only screen and (min-width: 1176px) {
+body {
+ margin: 0 40px 0 40px;
+}
+}
+
+/* TABLET STYLE */
+@media only screen and (min-width: 768px) and (max-width: 991px) {
+body {
+ margin: 0 40px 0 40px;
+}
+}
+
+/* MOBILE LAYOUT (PORTRAIT/320px) */
+@media only screen and (max-width: 767px) {
+body {
+ margin: 0;
+}
+div.bodywrapper {
+ margin: 0;
+ width: 100%;
+ border: none;
+}
+div.sphinxsidebar {
+ display: none;
+}
+}
+
+/* MOBILE LAYOUT (LANDSCAPE/480px) */
+@media only screen and (min-width: 480px) and (max-width: 767px) {
+body {
+ margin: 0 20px 0 20px;
+}
+}
+
+/* RETINA OVERRIDES */
+@media
+only screen and (-webkit-min-device-pixel-ratio: 2),
+only screen and (min-device-pixel-ratio: 2) {
+}
+
+/* -- end ------------------------------------------------------------------- */
diff --git a/sphinx/themes/bizstyle/static/bizstyle.js_t b/sphinx/themes/bizstyle/static/bizstyle.js_t
new file mode 100644
index 00000000..1950d392
--- /dev/null
+++ b/sphinx/themes/bizstyle/static/bizstyle.js_t
@@ -0,0 +1,45 @@
+//
+// bizstyle.js
+// ~~~~~~~~~~~
+//
+// Sphinx javascript -- for bizstyle theme.
+//
+// This theme was created by referring to 'sphinxdoc'
+//
+// :copyright: Copyright 2012-2014 by Sphinx team, see AUTHORS.
+// :license: BSD, see LICENSE for details.
+//
+$(document).ready(function(){
+ if (navigator.userAgent.indexOf('iPhone') > 0 ||
+ navigator.userAgent.indexOf('Android') > 0) {
+ $("div.related ul li:not(.right) a").text("Top");
+ }
+
+ $("div.related:first ul li:not(.right) a").slice(1).each(function(i, item){
+ if (item.text.length > 20) {
+ var tmpstr = item.text
+ $(item).attr("title", tmpstr);
+ $(item).text(tmpstr.substr(0, 5) + "...");
+ alert(i + ":" + item.text + ":" + $(item).attr("title") + ":" + $(item).size());
+ }
+ });
+ $("div.related:last ul li:not(.right) a").slice(1).each(function(i, item){
+ if (item.text.length > 20) {
+ var tmpstr = item.text
+ $(item).attr("title", tmpstr);
+ $(item).text(tmpstr.substr(0, 5) + "...");
+ alert(i + ":" + item.text + ":" + $(item).attr("title") + ":" + $(item).size());
+ }
+ });
+});
+
+$(window).resize(function(){
+ if ($(window).width() <= 776) {
+ $("div.related:first ul li:not(.right):first a").text("Top");
+ $("div.related:last ul li:not(.right):first a").text("Top");
+ }
+ else {
+ $("div.related:first ul li:not(.right):first a").text("{{ shorttitle|e }}");
+ $("div.related:last ul li:not(.right):first a").text("{{ shorttitle|e }}");
+ }
+});
diff --git a/sphinx/themes/bizstyle/static/css3-mediaqueries.js b/sphinx/themes/bizstyle/static/css3-mediaqueries.js
new file mode 100644
index 00000000..3b906524
--- /dev/null
+++ b/sphinx/themes/bizstyle/static/css3-mediaqueries.js
@@ -0,0 +1 @@
+if(typeof Object.create!=="function"){Object.create=function(e){function t(){}t.prototype=e;return new t}}var ua={toString:function(){return navigator.userAgent},test:function(e){return this.toString().toLowerCase().indexOf(e.toLowerCase())>-1}};ua.version=(ua.toString().toLowerCase().match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1];ua.webkit=ua.test("webkit");ua.gecko=ua.test("gecko")&&!ua.webkit;ua.opera=ua.test("opera");ua.ie=ua.test("msie")&&!ua.opera;ua.ie6=ua.ie&&document.compatMode&&typeof document.documentElement.style.maxHeight==="undefined";ua.ie7=ua.ie&&document.documentElement&&typeof document.documentElement.style.maxHeight!=="undefined"&&typeof XDomainRequest==="undefined";ua.ie8=ua.ie&&typeof XDomainRequest!=="undefined";var domReady=function(){var e=[];var t=function(){if(!arguments.callee.done){arguments.callee.done=true;for(var t=0;t<e.length;t++){e[t]()}}};if(document.addEventListener){document.addEventListener("DOMContentLoaded",t,false)}if(ua.ie){(function(){try{document.documentElement.doScroll("left")}catch(e){setTimeout(arguments.callee,50);return}t()})();document.onreadystatechange=function(){if(document.readyState==="complete"){document.onreadystatechange=null;t()}}}if(ua.webkit&&document.readyState){(function(){if(document.readyState!=="loading"){t()}else{setTimeout(arguments.callee,10)}})()}window.onload=t;return function(t){if(typeof t==="function"){e[e.length]=t}return t}}();var cssHelper=function(){var e={BLOCKS:/[^\s{;][^{;]*\{(?:[^{}]*\{[^{}]*\}[^{}]*|[^{}]*)*\}/g,BLOCKS_INSIDE:/[^\s{][^{]*\{[^{}]*\}/g,DECLARATIONS:/[a-zA-Z\-]+[^;]*:[^;]+;/g,RELATIVE_URLS:/url\(['"]?([^\/\)'"][^:\)'"]+)['"]?\)/g,REDUNDANT_COMPONENTS:/(?:\/\*([^*\\\\]|\*(?!\/))+\*\/|@import[^;]+;)/g,REDUNDANT_WHITESPACE:/\s*(,|:|;|\{|\})\s*/g,WHITESPACE_IN_PARENTHESES:/\(\s*(\S*)\s*\)/g,MORE_WHITESPACE:/\s{2,}/g,FINAL_SEMICOLONS:/;\}/g,NOT_WHITESPACE:/\S+/g};var t,n=false;var r=[];var s=function(e){if(typeof e==="function"){r[r.length]=e}};var o=function(){for(var e=0;e<r.length;e++){r[e](t)}};var u={};var a=function(e,t){if(u[e]){var n=u[e].listeners;if(n){for(var r=0;r<n.length;r++){n[r](t)}}}};var f=function(e,t,n){if(ua.ie&&!window.XMLHttpRequest){window.XMLHttpRequest=function(){return new ActiveXObject("Microsoft.XMLHTTP")}}if(!XMLHttpRequest){return""}var r=new XMLHttpRequest;try{r.open("get",e,true);r.setRequestHeader("X_REQUESTED_WITH","XMLHttpRequest")}catch(i){n();return}var s=false;setTimeout(function(){s=true},5e3);document.documentElement.style.cursor="progress";r.onreadystatechange=function(){if(r.readyState===4&&!s){if(!r.status&&location.protocol==="file:"||r.status>=200&&r.status<300||r.status===304||navigator.userAgent.indexOf("Safari")>-1&&typeof r.status==="undefined"){t(r.responseText)}else{n()}document.documentElement.style.cursor="";r=null}};r.send("")};var l=function(t){t=t.replace(e.REDUNDANT_COMPONENTS,"");t=t.replace(e.REDUNDANT_WHITESPACE,"$1");t=t.replace(e.WHITESPACE_IN_PARENTHESES,"($1)");t=t.replace(e.MORE_WHITESPACE," ");t=t.replace(e.FINAL_SEMICOLONS,"}");return t};var c={stylesheet:function(t){var n={};var r=[],i=[],s=[],o=[];var u=t.cssHelperText;var a=t.getAttribute("media");if(a){var f=a.toLowerCase().split(",")}else{var f=["all"]}for(var l=0;l<f.length;l++){r[r.length]=c.mediaQuery(f[l],n)}var h=u.match(e.BLOCKS);if(h!==null){for(var l=0;l<h.length;l++){if(h[l].substring(0,7)==="@media "){var p=c.mediaQueryList(h[l],n);s=s.concat(p.getRules());i[i.length]=p}else{s[s.length]=o[o.length]=c.rule(h[l],n,null)}}}n.element=t;n.getCssText=function(){return u};n.getAttrMediaQueries=function(){return r};n.getMediaQueryLists=function(){return i};n.getRules=function(){return s};n.getRulesWithoutMQ=function(){return o};return n},mediaQueryList:function(t,n){var r={};var i=t.indexOf("{");var s=t.substring(0,i);t=t.substring(i+1,t.length-1);var o=[],u=[];var a=s.toLowerCase().substring(7).split(",");for(var f=0;f<a.length;f++){o[o.length]=c.mediaQuery(a[f],r)}var l=t.match(e.BLOCKS_INSIDE);if(l!==null){for(f=0;f<l.length;f++){u[u.length]=c.rule(l[f],n,r)}}r.type="mediaQueryList";r.getMediaQueries=function(){return o};r.getRules=function(){return u};r.getListText=function(){return s};r.getCssText=function(){return t};return r},mediaQuery:function(t,n){t=t||"";var r,i;if(n.type==="mediaQueryList"){r=n}else{i=n}var s=false,o;var u=[];var a=true;var f=t.match(e.NOT_WHITESPACE);for(var l=0;l<f.length;l++){var c=f[l];if(!o&&(c==="not"||c==="only")){if(c==="not"){s=true}}else if(!o){o=c}else if(c.charAt(0)==="("){var h=c.substring(1,c.length-1).split(":");u[u.length]={mediaFeature:h[0],value:h[1]||null}}}return{getQueryText:function(){return t},getAttrStyleSheet:function(){return i||null},getList:function(){return r||null},getValid:function(){return a},getNot:function(){return s},getMediaType:function(){return o},getExpressions:function(){return u}}},rule:function(e,t,n){var r={};var i=e.indexOf("{");var s=e.substring(0,i);var o=s.split(",");var u=[];var a=e.substring(i+1,e.length-1).split(";");for(var f=0;f<a.length;f++){u[u.length]=c.declaration(a[f],r)}r.getStylesheet=function(){return t||null};r.getMediaQueryList=function(){return n||null};r.getSelectors=function(){return o};r.getSelectorText=function(){return s};r.getDeclarations=function(){return u};r.getPropertyValue=function(e){for(var t=0;t<u.length;t++){if(u[t].getProperty()===e){return u[t].getValue()}}return null};return r},declaration:function(e,t){var n=e.indexOf(":");var r=e.substring(0,n);var i=e.substring(n+1);return{getRule:function(){return t||null},getProperty:function(){return r},getValue:function(){return i}}}};var h=function(e){if(typeof e.cssHelperText!=="string"){return}var n={stylesheet:null,mediaQueryLists:[],rules:[],selectors:{},declarations:[],properties:{}};var r=n.stylesheet=c.stylesheet(e);var s=n.mediaQueryLists=r.getMediaQueryLists();var o=n.rules=r.getRules();var u=n.selectors;var a=function(e){var t=e.getSelectors();for(var n=0;n<t.length;n++){var r=t[n];if(!u[r]){u[r]=[]}u[r][u[r].length]=e}};for(i=0;i<o.length;i++){a(o[i])}var f=n.declarations;for(i=0;i<o.length;i++){f=n.declarations=f.concat(o[i].getDeclarations())}var l=n.properties;for(i=0;i<f.length;i++){var h=f[i].getProperty();if(!l[h]){l[h]=[]}l[h][l[h].length]=f[i]}e.cssHelperParsed=n;t[t.length]=e;return n};var p=function(e,t){return;e.cssHelperText=l(t||e.innerHTML);return h(e)};var d=function(){n=true;t=[];var r=[];var i=function(){for(var e=0;e<r.length;e++){h(r[e])}var t=document.getElementsByTagName("style");for(e=0;e<t.length;e++){p(t[e])}n=false;o()};var s=document.getElementsByTagName("link");for(var u=0;u<s.length;u++){var a=s[u];if(a.getAttribute("rel").indexOf("style")>-1&&a.href&&a.href.length!==0&&!a.disabled){r[r.length]=a}}if(r.length>0){var c=0;var d=function(){c++;if(c===r.length){i()}};var v=function(t){var n=t.href;f(n,function(r){r=l(r).replace(e.RELATIVE_URLS,"url("+n.substring(0,n.lastIndexOf("/"))+"/$1)");t.cssHelperText=r;d()},d)};for(u=0;u<r.length;u++){v(r[u])}}else{i()}};var v={stylesheets:"array",mediaQueryLists:"array",rules:"array",selectors:"object",declarations:"array",properties:"object"};var m={stylesheets:null,mediaQueryLists:null,rules:null,selectors:null,declarations:null,properties:null};var g=function(e,t){if(m[e]!==null){if(v[e]==="array"){return m[e]=m[e].concat(t)}else{var n=m[e];for(var r in t){if(t.hasOwnProperty(r)){if(!n[r]){n[r]=t[r]}else{n[r]=n[r].concat(t[r])}}}return n}}};var y=function(e){m[e]=v[e]==="array"?[]:{};for(var n=0;n<t.length;n++){var r=e==="stylesheets"?"stylesheet":e;g(e,t[n].cssHelperParsed[r])}return m[e]};var b=function(e){if(typeof window.innerWidth!="undefined"){return window["inner"+e]}else if(typeof document.documentElement!=="undefined"&&typeof document.documentElement.clientWidth!=="undefined"&&document.documentElement.clientWidth!=0){return document.documentElement["client"+e]}};return{addStyle:function(e,t,n){var r=document.createElement("style");r.setAttribute("type","text/css");if(t&&t.length>0){r.setAttribute("media",t.join(","))}document.getElementsByTagName("head")[0].appendChild(r);if(r.styleSheet){r.styleSheet.cssText=e}else{r.appendChild(document.createTextNode(e))}r.addedWithCssHelper=true;if(typeof n==="undefined"||n===true){cssHelper.parsed(function(t){var n=p(r,e);for(var i in n){if(n.hasOwnProperty(i)){g(i,n[i])}}a("newStyleParsed",r)})}else{r.parsingDisallowed=true}return r},removeStyle:function(e){return e.parentNode.removeChild(e)},parsed:function(e){if(n){s(e)}else{if(typeof t!=="undefined"){if(typeof e==="function"){e(t)}}else{s(e);d()}}},stylesheets:function(e){cssHelper.parsed(function(t){e(m.stylesheets||y("stylesheets"))})},mediaQueryLists:function(e){cssHelper.parsed(function(t){e(m.mediaQueryLists||y("mediaQueryLists"))})},rules:function(e){cssHelper.parsed(function(t){e(m.rules||y("rules"))})},selectors:function(e){cssHelper.parsed(function(t){e(m.selectors||y("selectors"))})},declarations:function(e){cssHelper.parsed(function(t){e(m.declarations||y("declarations"))})},properties:function(e){cssHelper.parsed(function(t){e(m.properties||y("properties"))})},broadcast:a,addListener:function(e,t){if(typeof t==="function"){if(!u[e]){u[e]={listeners:[]}}u[e].listeners[u[e].listeners.length]=t}},removeListener:function(e,t){if(typeof t==="function"&&u[e]){var n=u[e].listeners;for(var r=0;r<n.length;r++){if(n[r]===t){n.splice(r,1);r-=1}}}},getViewportWidth:function(){return b("Width")},getViewportHeight:function(){return b("Height")}}}();domReady(function(){var t;var n={LENGTH_UNIT:/[0-9]+(em|ex|px|in|cm|mm|pt|pc)$/,RESOLUTION_UNIT:/[0-9]+(dpi|dpcm)$/,ASPECT_RATIO:/^[0-9]+\/[0-9]+$/,ABSOLUTE_VALUE:/^[0-9]*(\.[0-9]+)*$/};var r=[];var i=function(){var e="css3-mediaqueries-test";var t=document.createElement("div");t.id=e;var n=cssHelper.addStyle("@media all and (width) { #"+e+" { width: 1px !important; } }",[],false);document.body.appendChild(t);var r=t.offsetWidth===1;n.parentNode.removeChild(n);t.parentNode.removeChild(t);i=function(){return r};return r};var s=function(){t=document.createElement("div");t.style.cssText="position:absolute;top:-9999em;left:-9999em;"+"margin:0;border:none;padding:0;width:1em;font-size:1em;";document.body.appendChild(t);if(t.offsetWidth!==16){t.style.fontSize=16/t.offsetWidth+"em"}t.style.width=""};var o=function(e){t.style.width=e;var n=t.offsetWidth;t.style.width="";return n};var u=function(e,t){var r=e.length;var i=e.substring(0,4)==="min-";var s=!i&&e.substring(0,4)==="max-";if(t!==null){var u;var a;if(n.LENGTH_UNIT.exec(t)){u="length";a=o(t)}else if(n.RESOLUTION_UNIT.exec(t)){u="resolution";a=parseInt(t,10);var f=t.substring((a+"").length)}else if(n.ASPECT_RATIO.exec(t)){u="aspect-ratio";a=t.split("/")}else if(n.ABSOLUTE_VALUE){u="absolute";a=t}else{u="unknown"}}var l,c;if("device-width"===e.substring(r-12,r)){l=screen.width;if(t!==null){if(u==="length"){return i&&l>=a||s&&l<a||!i&&!s&&l===a}else{return false}}else{return l>0}}else if("device-height"===e.substring(r-13,r)){c=screen.height;if(t!==null){if(u==="length"){return i&&c>=a||s&&c<a||!i&&!s&&c===a}else{return false}}else{return c>0}}else if("width"===e.substring(r-5,r)){l=document.documentElement.clientWidth||document.body.clientWidth;if(t!==null){if(u==="length"){return i&&l>=a||s&&l<a||!i&&!s&&l===a}else{return false}}else{return l>0}}else if("height"===e.substring(r-6,r)){c=document.documentElement.clientHeight||document.body.clientHeight;if(t!==null){if(u==="length"){return i&&c>=a||s&&c<a||!i&&!s&&c===a}else{return false}}else{return c>0}}else if("device-aspect-ratio"===e.substring(r-19,r)){return u==="aspect-ratio"&&screen.width*a[1]===screen.height*a[0]}else if("color-index"===e.substring(r-11,r)){var h=Math.pow(2,screen.colorDepth);if(t!==null){if(u==="absolute"){return i&&h>=a||s&&h<a||!i&&!s&&h===a}else{return false}}else{return h>0}}else if("color"===e.substring(r-5,r)){var p=screen.colorDepth;if(t!==null){if(u==="absolute"){return i&&p>=a||s&&p<a||!i&&!s&&p===a}else{return false}}else{return p>0}}else if("resolution"===e.substring(r-10,r)){var d;if(f==="dpcm"){d=o("1cm")}else{d=o("1in")}if(t!==null){if(u==="resolution"){return i&&d>=a||s&&d<a||!i&&!s&&d===a}else{return false}}else{return d>0}}else{return false}};var a=function(e){var t=e.getValid();var n=e.getExpressions();var r=n.length;if(r>0){for(var i=0;i<r&&t;i++){t=u(n[i].mediaFeature,n[i].value)}var s=e.getNot();return t&&!s||s&&!t}return t};var f=function(e,t){var n=e.getMediaQueries();var i={};for(var s=0;s<n.length;s++){var o=n[s].getMediaType();if(n[s].getExpressions().length===0){continue}var u=true;if(o!=="all"&&t&&t.length>0){u=false;for(var f=0;f<t.length;f++){if(t[f]===o){u=true}}}if(u&&a(n[s])){i[o]=true}}var l=[],c=0;for(var h in i){if(i.hasOwnProperty(h)){if(c>0){l[c++]=","}l[c++]=h}}if(l.length>0){r[r.length]=cssHelper.addStyle("@media "+l.join("")+"{"+e.getCssText()+"}",t,false)}};var l=function(e,t){for(var n=0;n<e.length;n++){f(e[n],t)}};var c=function(e){var t=e.getAttrMediaQueries();var n=false;var i={};for(var s=0;s<t.length;s++){if(a(t[s])){i[t[s].getMediaType()]=t[s].getExpressions().length>0}}var o=[],u=[];for(var f in i){if(i.hasOwnProperty(f)){o[o.length]=f;if(i[f]){u[u.length]=f}if(f==="all"){n=true}}}if(u.length>0){r[r.length]=cssHelper.addStyle(e.getCssText(),u,false)}var c=e.getMediaQueryLists();if(n){l(c)}else{l(c,o)}};var h=function(e){for(var t=0;t<e.length;t++){c(e[t])}if(ua.ie){document.documentElement.style.display="block";setTimeout(function(){document.documentElement.style.display=""},0);setTimeout(function(){cssHelper.broadcast("cssMediaQueriesTested")},100)}else{cssHelper.broadcast("cssMediaQueriesTested")}};var p=function(){for(var e=0;e<r.length;e++){cssHelper.removeStyle(r[e])}r=[];cssHelper.stylesheets(h)};var d=0;var v=function(){var e=cssHelper.getViewportWidth();var t=cssHelper.getViewportHeight();if(ua.ie){var n=document.createElement("div");n.style.position="absolute";n.style.top="-9999em";n.style.overflow="scroll";document.body.appendChild(n);d=n.offsetWidth-n.clientWidth;document.body.removeChild(n)}var r;var s=function(){var n=cssHelper.getViewportWidth();var s=cssHelper.getViewportHeight();if(Math.abs(n-e)>d||Math.abs(s-t)>d){e=n;t=s;clearTimeout(r);r=setTimeout(function(){if(!i()){p()}else{cssHelper.broadcast("cssMediaQueriesTested")}},500)}};window.onresize=function(){var e=window.onresize||function(){};return function(){e();s()}}()};var m=document.documentElement;m.style.marginLeft="-32767px";setTimeout(function(){m.style.marginLeft=""},5e3);return function(){if(!i()){cssHelper.addListener("newStyleParsed",function(e){c(e.cssHelperParsed.stylesheet)});cssHelper.addListener("cssMediaQueriesTested",function(){if(ua.ie){m.style.width="1px"}setTimeout(function(){m.style.width="";m.style.marginLeft=""},0);cssHelper.removeListener("cssMediaQueriesTested",arguments.callee)});s();p()}else{m.style.marginLeft=""}v()}}());try{document.execCommand("BackgroundImageCache",false,true)}catch(e){} \ No newline at end of file
diff --git a/sphinx/themes/bizstyle/static/css3-mediaqueries_src.js b/sphinx/themes/bizstyle/static/css3-mediaqueries_src.js
new file mode 100644
index 00000000..65b44825
--- /dev/null
+++ b/sphinx/themes/bizstyle/static/css3-mediaqueries_src.js
@@ -0,0 +1,1104 @@
+/*
+css3-mediaqueries.js - CSS Helper and CSS3 Media Queries Enabler
+
+author: Wouter van der Graaf <wouter at dynora nl>
+version: 1.0 (20110330)
+license: MIT
+website: http://code.google.com/p/css3-mediaqueries-js/
+
+W3C spec: http://www.w3.org/TR/css3-mediaqueries/
+
+Note: use of embedded <style> is not recommended when using media queries, because IE has no way of returning the raw literal css text from a <style> element.
+*/
+
+
+// true prototypal inheritance (http://javascript.crockford.com/prototypal.html)
+if (typeof Object.create !== 'function') {
+ Object.create = function (o) {
+ function F() {}
+ F.prototype = o;
+ return new F();
+ };
+}
+
+
+// user agent sniffing shortcuts
+var ua = {
+ toString: function () {
+ return navigator.userAgent;
+ },
+ test: function (s) {
+ return this.toString().toLowerCase().indexOf(s.toLowerCase()) > -1;
+ }
+};
+ua.version = (ua.toString().toLowerCase().match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1];
+ua.webkit = ua.test('webkit');
+ua.gecko = ua.test('gecko') && !ua.webkit;
+ua.opera = ua.test('opera');
+ua.ie = ua.test('msie') && !ua.opera;
+ua.ie6 = ua.ie && document.compatMode && typeof document.documentElement.style.maxHeight === 'undefined';
+ua.ie7 = ua.ie && document.documentElement && typeof document.documentElement.style.maxHeight !== 'undefined' && typeof XDomainRequest === 'undefined';
+ua.ie8 = ua.ie && typeof XDomainRequest !== 'undefined';
+
+
+
+// initialize when DOM content is loaded
+var domReady = function () {
+ var fns = [];
+ var init = function () {
+ if (!arguments.callee.done) { // run init functions once
+ arguments.callee.done = true;
+ for (var i = 0; i < fns.length; i++) {
+ fns[i]();
+ }
+ }
+ };
+
+ // listeners for different browsers
+ if (document.addEventListener) {
+ document.addEventListener('DOMContentLoaded', init, false);
+ }
+ if (ua.ie) {
+ (function () {
+ try {
+ // throws errors until after ondocumentready
+ document.documentElement.doScroll('left');
+ }
+ catch (e) {
+ setTimeout(arguments.callee, 50);
+ return;
+ }
+ // no errors, fire
+ init();
+ })();
+ // trying to always fire before onload
+ document.onreadystatechange = function () {
+ if (document.readyState === 'complete') {
+ document.onreadystatechange = null;
+ init();
+ }
+ };
+ }
+ if (ua.webkit && document.readyState) {
+ (function () {
+ if (document.readyState !== 'loading') {
+ init();
+ }
+ else {
+ setTimeout(arguments.callee, 10);
+ }
+ })();
+ }
+ window.onload = init; // fallback
+
+ return function (fn) { // add fn to init functions
+ if (typeof fn === 'function') {
+ fns[fns.length] = fn;
+ }
+ return fn;
+ };
+}();
+
+
+
+// helper library for parsing css to objects
+var cssHelper = function () {
+
+ var regExp = {
+ BLOCKS: /[^\s{;][^{;]*\{(?:[^{}]*\{[^{}]*\}[^{}]*|[^{}]*)*\}/g,
+ BLOCKS_INSIDE: /[^\s{][^{]*\{[^{}]*\}/g,
+ DECLARATIONS: /[a-zA-Z\-]+[^;]*:[^;]+;/g,
+ RELATIVE_URLS: /url\(['"]?([^\/\)'"][^:\)'"]+)['"]?\)/g,
+ // strip whitespace and comments, @import is evil
+ REDUNDANT_COMPONENTS: /(?:\/\*([^*\\\\]|\*(?!\/))+\*\/|@import[^;]+;)/g,
+ REDUNDANT_WHITESPACE: /\s*(,|:|;|\{|\})\s*/g,
+ WHITESPACE_IN_PARENTHESES: /\(\s*(\S*)\s*\)/g,
+ MORE_WHITESPACE: /\s{2,}/g,
+ FINAL_SEMICOLONS: /;\}/g,
+ NOT_WHITESPACE: /\S+/g
+ };
+
+ var parsed, parsing = false;
+
+ var waiting = [];
+ var wait = function (fn) {
+ if (typeof fn === 'function') {
+ waiting[waiting.length] = fn;
+ }
+ };
+ var ready = function () {
+ for (var i = 0; i < waiting.length; i++) {
+ waiting[i](parsed);
+ }
+ };
+ var events = {};
+ var broadcast = function (n, v) {
+ if (events[n]) {
+ var listeners = events[n].listeners;
+ if (listeners) {
+ for (var i = 0; i < listeners.length; i++) {
+ listeners[i](v);
+ }
+ }
+ }
+ };
+
+ var requestText = function (url, fnSuccess, fnFailure) {
+ if (ua.ie && !window.XMLHttpRequest) {
+ window.XMLHttpRequest = function () {
+ return new ActiveXObject('Microsoft.XMLHTTP');
+ };
+ }
+ if (!XMLHttpRequest) {
+ return '';
+ }
+ var r = new XMLHttpRequest();
+ try {
+ r.open('get', url, true);
+ r.setRequestHeader('X_REQUESTED_WITH', 'XMLHttpRequest');
+ }
+ catch (e) {
+ fnFailure();
+ return;
+ }
+ var done = false;
+ setTimeout(function () {
+ done = true;
+ }, 5000);
+ document.documentElement.style.cursor = 'progress';
+ r.onreadystatechange = function () {
+ if (r.readyState === 4 && !done) {
+ if (!r.status && location.protocol === 'file:' ||
+ (r.status >= 200 && r.status < 300) ||
+ r.status === 304 ||
+ navigator.userAgent.indexOf('Safari') > -1 && typeof r.status === 'undefined') {
+ fnSuccess(r.responseText);
+ }
+ else {
+ fnFailure();
+ }
+ document.documentElement.style.cursor = '';
+ r = null; // avoid memory leaks
+ }
+ };
+ r.send('');
+ };
+
+ var sanitize = function (text) {
+ text = text.replace(regExp.REDUNDANT_COMPONENTS, '');
+ text = text.replace(regExp.REDUNDANT_WHITESPACE, '$1');
+ text = text.replace(regExp.WHITESPACE_IN_PARENTHESES, '($1)');
+ text = text.replace(regExp.MORE_WHITESPACE, ' ');
+ text = text.replace(regExp.FINAL_SEMICOLONS, '}'); // optional final semicolons
+ return text;
+ };
+
+ var objects = {
+ stylesheet: function (el) {
+ var o = {};
+ var amqs = [], mqls = [], rs = [], rsw = [];
+ var s = el.cssHelperText;
+
+ // add attribute media queries
+ var attr = el.getAttribute('media');
+ if (attr) {
+ var qts = attr.toLowerCase().split(',')
+ }
+ else {
+ var qts = ['all'] // imply 'all'
+ }
+ for (var i = 0; i < qts.length; i++) {
+ amqs[amqs.length] = objects.mediaQuery(qts[i], o);
+ }
+
+ // add media query lists and rules (top down order)
+ var blocks = s.match(regExp.BLOCKS); // @charset is not a block
+ if (blocks !== null) {
+ for (var i = 0; i < blocks.length; i++) {
+ if (blocks[i].substring(0, 7) === '@media ') { // media query (list)
+ var mql = objects.mediaQueryList(blocks[i], o);
+ rs = rs.concat(mql.getRules());
+ mqls[mqls.length] = mql;
+ }
+ else { // regular rule set, page context (@page) or font description (@font-face)
+ rs[rs.length] = rsw[rsw.length] = objects.rule(blocks[i], o, null);
+ }
+ }
+ }
+
+ o.element = el;
+ o.getCssText = function () {
+ return s;
+ };
+ o.getAttrMediaQueries = function () {
+ return amqs;
+ };
+ o.getMediaQueryLists = function () {
+ return mqls;
+ };
+ o.getRules = function () {
+ return rs;
+ };
+ o.getRulesWithoutMQ = function () {
+ return rsw;
+ };
+ return o;
+ },
+
+ mediaQueryList: function (s, stsh) {
+ var o = {};
+ var idx = s.indexOf('{');
+ var lt = s.substring(0, idx);
+ s = s.substring(idx + 1, s.length - 1);
+ var mqs = [], rs = [];
+
+ // add media queries
+ var qts = lt.toLowerCase().substring(7).split(',');
+ for (var i = 0; i < qts.length; i++) { // parse each media query
+ mqs[mqs.length] = objects.mediaQuery(qts[i], o);
+ }
+
+ // add rule sets
+ var rts = s.match(regExp.BLOCKS_INSIDE);
+ if (rts !== null) {
+ for (i = 0; i < rts.length; i++) {
+ rs[rs.length] = objects.rule(rts[i], stsh, o);
+ }
+ }
+
+ o.type = 'mediaQueryList';
+ o.getMediaQueries = function () {
+ return mqs;
+ };
+ o.getRules = function () {
+ return rs;
+ };
+ o.getListText = function () {
+ return lt;
+ };
+ o.getCssText = function () {
+ return s;
+ };
+ return o;
+ },
+
+ mediaQuery: function (s, listOrSheet) {
+ s = s || '';
+ var mql, stsh;
+ if (listOrSheet.type === 'mediaQueryList') {
+ mql = listOrSheet;
+ }
+ else {
+ stsh = listOrSheet;
+ }
+ var not = false, type;
+ var expr = [];
+ var valid = true;
+ var tokens = s.match(regExp.NOT_WHITESPACE);
+
+
+
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ if (!type && (token === 'not' || token === 'only')) { // 'not' and 'only' keywords
+ // keyword 'only' does nothing, as if it was not present
+ if (token === 'not') {
+ not = true;
+ }
+ }
+ else if (!type) { // media type
+ type = token;
+ }
+ else if (token.charAt(0) === '(') { // media feature expression
+ var pair = token.substring(1, token.length - 1).split(':');
+ expr[expr.length] = {
+ mediaFeature: pair[0],
+ value: pair[1] || null
+ };
+ }
+ }
+
+ return {
+ getQueryText: function () {
+ return s;
+ },
+ getAttrStyleSheet: function () {
+ return stsh || null;
+ },
+ getList: function () {
+ return mql || null;
+ },
+ getValid: function () {
+ return valid;
+ },
+ getNot: function () {
+ return not;
+ },
+ getMediaType: function () {
+ return type;
+ },
+ getExpressions: function () {
+ return expr;
+ }
+ };
+ },
+
+ rule: function (s, stsh, mql) {
+ var o = {};
+ var idx = s.indexOf('{');
+ var st = s.substring(0, idx);
+ var ss = st.split(',');
+ var ds = [];
+ var dts = s.substring(idx + 1, s.length - 1).split(';');
+ for (var i = 0; i < dts.length; i++) {
+ ds[ds.length] = objects.declaration(dts[i], o);
+ }
+
+ o.getStylesheet = function () {
+ return stsh || null;
+ };
+ o.getMediaQueryList = function () {
+ return mql || null;
+ };
+ o.getSelectors = function () {
+ return ss;
+ };
+ o.getSelectorText = function () {
+ return st;
+ };
+ o.getDeclarations = function () {
+ return ds;
+ };
+ o.getPropertyValue = function (n) {
+ for (var i = 0; i < ds.length; i++) {
+ if (ds[i].getProperty() === n) {
+ return ds[i].getValue();
+ }
+ }
+ return null;
+ };
+ return o;
+ },
+
+ declaration: function (s, r) {
+ var idx = s.indexOf(':');
+ var p = s.substring(0, idx);
+ var v = s.substring(idx + 1);
+ return {
+ getRule: function () {
+ return r || null;
+ },
+ getProperty: function () {
+ return p;
+ },
+ getValue: function () {
+ return v;
+ }
+ };
+ }
+ };
+
+ var parseText = function (el) {
+ if (typeof el.cssHelperText !== 'string') {
+ return;
+ }
+ var o = {
+ stylesheet: null,
+ mediaQueryLists: [],
+ rules: [],
+ selectors: {},
+ declarations: [],
+ properties: {}
+ };
+
+ // build stylesheet object
+ var stsh = o.stylesheet = objects.stylesheet(el);
+
+ // collect media query lists
+ var mqls = o.mediaQueryLists = stsh.getMediaQueryLists();
+
+ // collect all rules
+ var ors = o.rules = stsh.getRules();
+
+ // collect all selectors
+ var oss = o.selectors;
+ var collectSelectors = function (r) {
+ var ss = r.getSelectors();
+ for (var i = 0; i < ss.length; i++) {
+ var n = ss[i];
+ if (!oss[n]) {
+ oss[n] = [];
+ }
+ oss[n][oss[n].length] = r;
+ }
+ };
+ for (i = 0; i < ors.length; i++) {
+ collectSelectors(ors[i]);
+ }
+
+ // collect all declarations
+ var ods = o.declarations;
+ for (i = 0; i < ors.length; i++) {
+ ods = o.declarations = ods.concat(ors[i].getDeclarations());
+ }
+
+ // collect all properties
+ var ops = o.properties;
+ for (i = 0; i < ods.length; i++) {
+ var n = ods[i].getProperty();
+ if (!ops[n]) {
+ ops[n] = [];
+ }
+ ops[n][ops[n].length] = ods[i];
+ }
+
+ el.cssHelperParsed = o;
+ parsed[parsed.length] = el;
+ return o;
+ };
+
+ var parseEmbedded = function (el, s) {
+ return;
+ // This function doesn't work because of a bug in IE, where innerHTML gives us parsed css instead of raw literal.
+ el.cssHelperText = sanitize(s || el.innerHTML);
+ return parseText(el);
+ };
+
+ var parse = function () {
+ parsing = true;
+ parsed = [];
+ var linked = [];
+ var finish = function () {
+ for (var i = 0; i < linked.length; i++) {
+ parseText(linked[i]);
+ }
+ var styles = document.getElementsByTagName('style');
+ for (i = 0; i < styles.length; i++) {
+ parseEmbedded(styles[i]);
+ }
+ parsing = false;
+ ready();
+ };
+ var links = document.getElementsByTagName('link');
+ for (var i = 0; i < links.length; i++) {
+ var link = links[i];
+ if (link.getAttribute('rel').indexOf('style') > -1 && link.href && link.href.length !== 0 && !link.disabled) {
+ linked[linked.length] = link;
+ }
+ }
+ if (linked.length > 0) {
+ var c = 0;
+ var checkForFinish = function () {
+ c++;
+ if (c === linked.length) { // parse in right order, so after last link is read
+ finish();
+ }
+ };
+ var processLink = function (link) {
+ var href = link.href;
+ requestText(href, function (text) {
+ // fix url's
+ text = sanitize(text).replace(regExp.RELATIVE_URLS, 'url(' + href.substring(0, href.lastIndexOf('/')) + '/$1)');
+ link.cssHelperText = text;
+ checkForFinish();
+ }, checkForFinish);
+ };
+ for (i = 0; i < linked.length; i++) {
+ processLink(linked[i]);
+ }
+ }
+ else {
+ finish();
+ }
+ };
+
+ var types = {
+ stylesheets: 'array',
+ mediaQueryLists: 'array',
+ rules: 'array',
+ selectors: 'object',
+ declarations: 'array',
+ properties: 'object'
+ };
+
+ var collections = {
+ stylesheets: null,
+ mediaQueryLists: null,
+ rules: null,
+ selectors: null,
+ declarations: null,
+ properties: null
+ };
+
+ var addToCollection = function (name, v) {
+ if (collections[name] !== null) {
+ if (types[name] === 'array') {
+ return (collections[name] = collections[name].concat(v));
+ }
+ else {
+ var c = collections[name];
+ for (var n in v) {
+ if (v.hasOwnProperty(n)) {
+ if (!c[n]) {
+ c[n] = v[n];
+ }
+ else {
+ c[n] = c[n].concat(v[n]);
+ }
+ }
+ }
+ return c;
+ }
+ }
+ };
+
+ var collect = function (name) {
+ collections[name] = (types[name] === 'array') ? [] : {};
+ for (var i = 0; i < parsed.length; i++) {
+ var pname = name === 'stylesheets' ? 'stylesheet' : name; // the exception
+ addToCollection(name, parsed[i].cssHelperParsed[pname]);
+ }
+ return collections[name];
+ };
+
+ // viewport size
+ var getViewportSize = function (d) {
+ if (typeof window.innerWidth != 'undefined') {
+ return window['inner' + d];
+ }
+ else if (typeof document.documentElement !== 'undefined'
+ && typeof document.documentElement.clientWidth !== 'undefined'
+ && document.documentElement.clientWidth != 0) {
+ return document.documentElement['client' + d];
+ }
+ };
+
+ // public static functions
+ return {
+ addStyle: function (s, mediaTypes, process) {
+ var el = document.createElement('style');
+ el.setAttribute('type', 'text/css');
+ if (mediaTypes && mediaTypes.length > 0) {
+ el.setAttribute('media', mediaTypes.join(','));
+ }
+ document.getElementsByTagName('head')[0].appendChild(el);
+ if (el.styleSheet) { // IE
+ el.styleSheet.cssText = s;
+ }
+ else {
+ el.appendChild(document.createTextNode(s));
+ }
+ el.addedWithCssHelper = true;
+ if (typeof process === 'undefined' || process === true) {
+ cssHelper.parsed(function (parsed) {
+ var o = parseEmbedded(el, s);
+ for (var n in o) {
+ if (o.hasOwnProperty(n)) {
+ addToCollection(n, o[n]);
+ }
+ }
+ broadcast('newStyleParsed', el);
+ });
+ }
+ else {
+ el.parsingDisallowed = true;
+ }
+ return el;
+ },
+
+ removeStyle: function (el) {
+ return el.parentNode.removeChild(el);
+ },
+
+ parsed: function (fn) {
+ if (parsing) {
+ wait(fn);
+ }
+ else {
+ if (typeof parsed !== 'undefined') {
+ if (typeof fn === 'function') {
+ fn(parsed);
+ }
+ }
+ else {
+ wait(fn);
+ parse();
+ }
+ }
+ },
+
+ stylesheets: function (fn) {
+ cssHelper.parsed(function (parsed) {
+ fn(collections.stylesheets || collect('stylesheets'));
+ });
+ },
+
+ mediaQueryLists: function (fn) {
+ cssHelper.parsed(function (parsed) {
+ fn(collections.mediaQueryLists || collect('mediaQueryLists'));
+ });
+ },
+
+ rules: function (fn) {
+ cssHelper.parsed(function (parsed) {
+ fn(collections.rules || collect('rules'));
+ });
+ },
+
+ selectors: function (fn) {
+ cssHelper.parsed(function (parsed) {
+ fn(collections.selectors || collect('selectors'));
+ });
+ },
+
+ declarations: function (fn) {
+ cssHelper.parsed(function (parsed) {
+ fn(collections.declarations || collect('declarations'));
+ });
+ },
+
+ properties: function (fn) {
+ cssHelper.parsed(function (parsed) {
+ fn(collections.properties || collect('properties'));
+ });
+ },
+
+ broadcast: broadcast,
+
+ addListener: function (n, fn) { // in case n is 'styleadd': added function is called everytime style is added and parsed
+ if (typeof fn === 'function') {
+ if (!events[n]) {
+ events[n] = {
+ listeners: []
+ };
+ }
+ events[n].listeners[events[n].listeners.length] = fn;
+ }
+ },
+
+ removeListener: function (n, fn) {
+ if (typeof fn === 'function' && events[n]) {
+ var ls = events[n].listeners;
+ for (var i = 0; i < ls.length; i++) {
+ if (ls[i] === fn) {
+ ls.splice(i, 1);
+ i -= 1;
+ }
+ }
+ }
+ },
+
+ getViewportWidth: function () {
+ return getViewportSize('Width');
+ },
+
+ getViewportHeight: function () {
+ return getViewportSize('Height');
+ }
+ };
+}();
+
+
+
+// function to test and apply parsed media queries against browser capabilities
+domReady(function enableCssMediaQueries() {
+ var meter;
+
+ var regExp = {
+ LENGTH_UNIT: /[0-9]+(em|ex|px|in|cm|mm|pt|pc)$/,
+ RESOLUTION_UNIT: /[0-9]+(dpi|dpcm)$/,
+ ASPECT_RATIO: /^[0-9]+\/[0-9]+$/,
+ ABSOLUTE_VALUE: /^[0-9]*(\.[0-9]+)*$/
+ };
+
+ var styles = [];
+
+ var nativeSupport = function () {
+ // check support for media queries
+ var id = 'css3-mediaqueries-test';
+ var el = document.createElement('div');
+ el.id = id;
+ var style = cssHelper.addStyle('@media all and (width) { #' + id +
+ ' { width: 1px !important; } }', [], false); // false means don't parse this temp style
+ document.body.appendChild(el);
+ var ret = el.offsetWidth === 1;
+ style.parentNode.removeChild(style);
+ el.parentNode.removeChild(el);
+ nativeSupport = function () {
+ return ret;
+ };
+ return ret;
+ };
+
+ var createMeter = function () { // create measuring element
+ meter = document.createElement('div');
+ meter.style.cssText = 'position:absolute;top:-9999em;left:-9999em;' +
+ 'margin:0;border:none;padding:0;width:1em;font-size:1em;'; // cssText is needed for IE, works for the others
+ document.body.appendChild(meter);
+ // meter must have browser default font size of 16px
+ if (meter.offsetWidth !== 16) {
+ meter.style.fontSize = 16 / meter.offsetWidth + 'em';
+ }
+ meter.style.width = '';
+ };
+
+ var measure = function (value) {
+ meter.style.width = value;
+ var amount = meter.offsetWidth;
+ meter.style.width = '';
+ return amount;
+ };
+
+ var testMediaFeature = function (feature, value) {
+ // non-testable features: monochrome|min-monochrome|max-monochrome|scan|grid
+ var l = feature.length;
+ var min = (feature.substring(0, 4) === 'min-');
+ var max = (!min && feature.substring(0, 4) === 'max-');
+
+ if (value !== null) { // determine value type and parse to usable amount
+ var valueType;
+ var amount;
+ if (regExp.LENGTH_UNIT.exec(value)) {
+ valueType = 'length';
+ amount = measure(value);
+ }
+ else if (regExp.RESOLUTION_UNIT.exec(value)) {
+ valueType = 'resolution';
+ amount = parseInt(value, 10);
+ var unit = value.substring((amount + '').length);
+ }
+ else if (regExp.ASPECT_RATIO.exec(value)) {
+ valueType = 'aspect-ratio';
+ amount = value.split('/');
+ }
+ else if (regExp.ABSOLUTE_VALUE) {
+ valueType = 'absolute';
+ amount = value;
+ }
+ else {
+ valueType = 'unknown';
+ }
+ }
+
+ var width, height;
+ if ('device-width' === feature.substring(l - 12, l)) { // screen width
+ width = screen.width;
+ if (value !== null) {
+ if (valueType === 'length') {
+ return ((min && width >= amount) || (max && width < amount) || (!min && !max && width === amount));
+ }
+ else {
+ return false;
+ }
+ }
+ else { // test width without value
+ return width > 0;
+ }
+ }
+ else if ('device-height' === feature.substring(l - 13, l)) { // screen height
+ height = screen.height;
+ if (value !== null) {
+ if (valueType === 'length') {
+ return ((min && height >= amount) || (max && height < amount) || (!min && !max && height === amount));
+ }
+ else {
+ return false;
+ }
+ }
+ else { // test height without value
+ return height > 0;
+ }
+ }
+ else if ('width' === feature.substring(l - 5, l)) { // viewport width
+ width = document.documentElement.clientWidth || document.body.clientWidth; // the latter for IE quirks mode
+ if (value !== null) {
+ if (valueType === 'length') {
+ return ((min && width >= amount) || (max && width < amount) || (!min && !max && width === amount));
+ }
+ else {
+ return false;
+ }
+ }
+ else { // test width without value
+ return width > 0;
+ }
+ }
+ else if ('height' === feature.substring(l - 6, l)) { // viewport height
+ height = document.documentElement.clientHeight || document.body.clientHeight; // the latter for IE quirks mode
+ if (value !== null) {
+ if (valueType === 'length') {
+ return ((min && height >= amount) || (max && height < amount) || (!min && !max && height === amount));
+ }
+ else {
+ return false;
+ }
+ }
+ else { // test height without value
+ return height > 0;
+ }
+ }
+ else if ('device-aspect-ratio' === feature.substring(l - 19, l)) { // screen aspect ratio
+ return valueType === 'aspect-ratio' && screen.width * amount[1] === screen.height * amount[0];
+ }
+ else if ('color-index' === feature.substring(l - 11, l)) { // number of colors
+ var colors = Math.pow(2, screen.colorDepth);
+ if (value !== null) {
+ if (valueType === 'absolute') {
+ return ((min && colors >= amount) || (max && colors < amount) || (!min && !max && colors === amount));
+ }
+ else {
+ return false;
+ }
+ }
+ else { // test height without value
+ return colors > 0;
+ }
+ }
+ else if ('color' === feature.substring(l - 5, l)) { // bits per color component
+ var color = screen.colorDepth;
+ if (value !== null) {
+ if (valueType === 'absolute') {
+ return ((min && color >= amount) || (max && color < amount) || (!min && !max && color === amount));
+ }
+ else {
+ return false;
+ }
+ }
+ else { // test height without value
+ return color > 0;
+ }
+ }
+ else if ('resolution' === feature.substring(l - 10, l)) {
+ var res;
+ if (unit === 'dpcm') {
+ res = measure('1cm');
+ }
+ else {
+ res = measure('1in');
+ }
+ if (value !== null) {
+ if (valueType === 'resolution') {
+ return ((min && res >= amount) || (max && res < amount) || (!min && !max && res === amount));
+ }
+ else {
+ return false;
+ }
+ }
+ else { // test height without value
+ return res > 0;
+ }
+ }
+ else {
+ return false;
+ }
+ };
+
+ var testMediaQuery = function (mq) {
+ var test = mq.getValid();
+ var expressions = mq.getExpressions();
+ var l = expressions.length;
+ if (l > 0) {
+ for (var i = 0; i < l && test; i++) {
+ test = testMediaFeature(expressions[i].mediaFeature, expressions[i].value);
+ }
+ var not = mq.getNot();
+ return (test && !not || not && !test);
+ }
+ return test;
+ };
+
+ var testMediaQueryList = function (mql, ts) {
+ // ts is null or an array with any media type but 'all'.
+ var mqs = mql.getMediaQueries();
+ var t = {};
+ for (var i = 0; i < mqs.length; i++) {
+ var type = mqs[i].getMediaType();
+ if (mqs[i].getExpressions().length === 0) {
+ continue;
+ // TODO: Browser check! Assuming old browsers do apply the bare media types, even in a list with media queries.
+ }
+ var typeAllowed = true;
+ if (type !== 'all' && ts && ts.length > 0) {
+ typeAllowed = false;
+ for (var j = 0; j < ts.length; j++) {
+ if (ts[j] === type) {
+ typeAllowed = true;
+ }
+ }
+ }
+ if (typeAllowed && testMediaQuery(mqs[i])) {
+ t[type] = true;
+ }
+ }
+ var s = [], c = 0;
+ for (var n in t) {
+ if (t.hasOwnProperty(n)) {
+ if (c > 0) {
+ s[c++] = ',';
+ }
+ s[c++] = n;
+ }
+ }
+ if (s.length > 0) {
+ styles[styles.length] = cssHelper.addStyle('@media ' + s.join('') + '{' + mql.getCssText() + '}', ts, false);
+ }
+ };
+
+ var testMediaQueryLists = function (mqls, ts) {
+ for (var i = 0; i < mqls.length; i++) {
+ testMediaQueryList(mqls[i], ts);
+ }
+ };
+
+ var testStylesheet = function (stsh) {
+ var amqs = stsh.getAttrMediaQueries();
+ var allPassed = false;
+ var t = {};
+ for (var i = 0; i < amqs.length; i++) {
+ if (testMediaQuery(amqs[i])) {
+ t[amqs[i].getMediaType()] = amqs[i].getExpressions().length > 0;
+ }
+ }
+ var ts = [], tswe = [];
+ for (var n in t) {
+ if (t.hasOwnProperty(n)) {
+ ts[ts.length] = n;
+ if (t[n]) {
+ tswe[tswe.length] = n
+ }
+ if (n === 'all') {
+ allPassed = true;
+ }
+ }
+ }
+ if (tswe.length > 0) { // types with query expressions that passed the test
+ styles[styles.length] = cssHelper.addStyle(stsh.getCssText(), tswe, false);
+ }
+ var mqls = stsh.getMediaQueryLists();
+ if (allPassed) {
+ // If 'all' in media attribute passed the test, then test all @media types in linked CSS and create style with those types.
+ testMediaQueryLists(mqls);
+ }
+ else {
+ // Or else, test only media attribute types that passed the test and also 'all'.
+ // For positive '@media all', create style with attribute types that passed their test.
+ testMediaQueryLists(mqls, ts);
+ }
+ };
+
+ var testStylesheets = function (stshs) {
+ for (var i = 0; i < stshs.length; i++) {
+ testStylesheet(stshs[i]);
+ }
+ if (ua.ie) {
+ // force repaint in IE
+ document.documentElement.style.display = 'block';
+ setTimeout(function () {
+ document.documentElement.style.display = '';
+ }, 0);
+ // delay broadcast somewhat for IE
+ setTimeout(function () {
+ cssHelper.broadcast('cssMediaQueriesTested');
+ }, 100);
+ }
+ else {
+ cssHelper.broadcast('cssMediaQueriesTested');
+ }
+ };
+
+ var test = function () {
+ for (var i = 0; i < styles.length; i++) {
+ cssHelper.removeStyle(styles[i]);
+ }
+ styles = [];
+ cssHelper.stylesheets(testStylesheets);
+ };
+
+ var scrollbarWidth = 0;
+ var checkForResize = function () {
+ var cvpw = cssHelper.getViewportWidth();
+ var cvph = cssHelper.getViewportHeight();
+
+ // determine scrollbar width in IE, see resizeHandler
+ if (ua.ie) {
+ var el = document.createElement('div');
+ el.style.position = 'absolute';
+ el.style.top = '-9999em';
+ el.style.overflow = 'scroll';
+ document.body.appendChild(el);
+ scrollbarWidth = el.offsetWidth - el.clientWidth;
+ document.body.removeChild(el);
+ }
+
+ var timer;
+ var resizeHandler = function () {
+ var vpw = cssHelper.getViewportWidth();
+ var vph = cssHelper.getViewportHeight();
+ // check whether vp size has really changed, because IE also triggers resize event when body size changes
+ // 20px allowance to accomodate short appearance of scrollbars in IE in some cases
+ if (Math.abs(vpw - cvpw) > scrollbarWidth || Math.abs(vph - cvph) > scrollbarWidth) {
+ cvpw = vpw;
+ cvph = vph;
+ clearTimeout(timer);
+ timer = setTimeout(function () {
+ if (!nativeSupport()) {
+ test();
+ }
+ else {
+ cssHelper.broadcast('cssMediaQueriesTested');
+ }
+ }, 500);
+ }
+ };
+
+ window.onresize = function () {
+ var x = window.onresize || function () {}; // save original
+ return function () {
+ x();
+ resizeHandler();
+ };
+ }();
+ };
+
+ // prevent jumping of layout by hiding everything before painting <body>
+ var docEl = document.documentElement;
+ docEl.style.marginLeft = '-32767px';
+
+ // make sure it comes back after a while
+ setTimeout(function () {
+ docEl.style.marginLeft = '';
+ }, 5000);
+
+ return function () {
+ if (!nativeSupport()) { // if browser doesn't support media queries
+ cssHelper.addListener('newStyleParsed', function (el) {
+ testStylesheet(el.cssHelperParsed.stylesheet);
+ });
+ // return visibility after media queries are tested
+ cssHelper.addListener('cssMediaQueriesTested', function () {
+ // force repaint in IE by changing width
+ if (ua.ie) {
+ docEl.style.width = '1px';
+ }
+ setTimeout(function () {
+ docEl.style.width = ''; // undo width
+ docEl.style.marginLeft = ''; // undo hide
+ }, 0);
+ // remove this listener to prevent following execution
+ cssHelper.removeListener('cssMediaQueriesTested', arguments.callee);
+ });
+ createMeter();
+ test();
+ }
+ else {
+ docEl.style.marginLeft = ''; // undo visibility hidden
+ }
+ checkForResize();
+ };
+}());
+
+
+// bonus: hotfix for IE6 SP1 (bug KB823727)
+try {
+ document.execCommand('BackgroundImageCache', false, true);
+} catch (e) {}
diff --git a/sphinx/themes/bizstyle/theme.conf b/sphinx/themes/bizstyle/theme.conf
new file mode 100644
index 00000000..724eb127
--- /dev/null
+++ b/sphinx/themes/bizstyle/theme.conf
@@ -0,0 +1,9 @@
+[theme]
+inherit = basic
+stylesheet = bizstyle.css
+pygments_style = friendly
+
+[options]
+rightsidebar = false
+
+maincolor = #336699
diff --git a/sphinx/themes/default/static/default.css_t b/sphinx/themes/default/static/default.css_t
index cbdc7fbb..137a9e75 100644
--- a/sphinx/themes/default/static/default.css_t
+++ b/sphinx/themes/default/static/default.css_t
@@ -281,7 +281,7 @@ pre {
border-right: none;
}
-tt {
+code {
background-color: #ecf0f3;
padding: 0 1px 0 1px;
font-size: 0.95em;
@@ -291,11 +291,11 @@ th {
background-color: #ede;
}
-.warning tt {
+.warning code {
background: #efc2c2;
}
-.note tt {
+.note code {
background: #d6d6d6;
}
@@ -308,3 +308,8 @@ div.viewcode-block:target {
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
+
+div.code-block-caption {
+ color: #efefef;
+ background-color: #1c4e63;
+}
diff --git a/sphinx/themes/epub/static/epub.css b/sphinx/themes/epub/static/epub.css
index 30912b9a..a03c0627 100644
--- a/sphinx/themes/epub/static/epub.css
+++ b/sphinx/themes/epub/static/epub.css
@@ -363,6 +363,10 @@ dl.glossary dt {
font-size: 130%;
}
+.sig-paren {
+ font-size: larger;
+}
+
.versionmodified {
font-style: italic;
}
@@ -429,26 +433,26 @@ table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
-tt {
+code {
font-family: monospace;
}
-tt.descname {
+code.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
-tt.descclassname {
+code.descclassname {
background-color: transparent;
}
-tt.xref, a tt {
+code.xref, a code {
background-color: transparent;
font-weight: bold;
}
-h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
background-color: transparent;
}
@@ -531,4 +535,4 @@ table .link-target {
src: url("res:///Data/fonts/LiberationNarrow-BoldItalic.otf")
format("opentype");
}
-*/ \ No newline at end of file
+*/
diff --git a/sphinx/themes/haiku/layout.html b/sphinx/themes/haiku/layout.html
index 569763ba..20d5d3f9 100644
--- a/sphinx/themes/haiku/layout.html
+++ b/sphinx/themes/haiku/layout.html
@@ -32,7 +32,7 @@
{% endmacro %}
{% block content %}
- <div class="header">
+ <div class="header" role="banner">
{%- block haikuheader %}
{%- if theme_full_logo != "false" %}
<a href="{{ pathto('index') }}">
@@ -48,7 +48,7 @@
{%- endif %}
{%- endblock %}
</div>
- <div class="topnav">
+ <div class="topnav" role="navigation" aria-label="top navigation">
{{ nav() }}
</div>
<div class="content">
@@ -60,7 +60,7 @@
{%- endif %}#}
{% block body %}{% endblock %}
</div>
- <div class="bottomnav">
+ <div class="bottomnav" role="navigation" aria-label="bottom navigation">
{{ nav() }}
</div>
{% endblock %}
diff --git a/sphinx/themes/haiku/static/bg-page.png b/sphinx/themes/haiku/static/bg-page.png
index c6f3bc47..0103ee1a 100644
--- a/sphinx/themes/haiku/static/bg-page.png
+++ b/sphinx/themes/haiku/static/bg-page.png
Binary files differ
diff --git a/sphinx/themes/haiku/static/haiku.css_t b/sphinx/themes/haiku/static/haiku.css_t
index bd81db0a..c6cb42d8 100644
--- a/sphinx/themes/haiku/static/haiku.css_t
+++ b/sphinx/themes/haiku/static/haiku.css_t
@@ -307,7 +307,7 @@ td {
vertical-align: top;
}
-tt {
+code {
background-color: #e2e2e2;
font-size: 1.0em;
font-family: monospace;
diff --git a/sphinx/themes/nature/static/nature.css_t b/sphinx/themes/nature/static/nature.css_t
index ff891488..8818e447 100644
--- a/sphinx/themes/nature/static/nature.css_t
+++ b/sphinx/themes/nature/static/nature.css_t
@@ -226,7 +226,7 @@ pre {
-moz-box-shadow: 1px 1px 1px #d8d8d8;
}
-tt {
+code {
background-color: #ecf0f3;
color: #222;
/* padding: 1px 2px; */
@@ -243,3 +243,9 @@ div.viewcode-block:target {
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
+
+div.code-block-caption {
+ background-color: #ddd;
+ color: #222;
+ border: 1px solid #C6C9CB;
+}
diff --git a/sphinx/themes/pyramid/layout.html b/sphinx/themes/pyramid/layout.html
index 8780ceae..318a3662 100644
--- a/sphinx/themes/pyramid/layout.html
+++ b/sphinx/themes/pyramid/layout.html
@@ -10,7 +10,7 @@
{% block header %}
{%- if logo %}
-<div class="header">
+<div class="header" role="banner">
<div class="logo">
<a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
diff --git a/sphinx/themes/pyramid/static/dialog-note.png b/sphinx/themes/pyramid/static/dialog-note.png
index 263fbd58..70868211 100644
--- a/sphinx/themes/pyramid/static/dialog-note.png
+++ b/sphinx/themes/pyramid/static/dialog-note.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/dialog-seealso.png b/sphinx/themes/pyramid/static/dialog-seealso.png
index 3eb7b05c..a27a0fcb 100644
--- a/sphinx/themes/pyramid/static/dialog-seealso.png
+++ b/sphinx/themes/pyramid/static/dialog-seealso.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/dialog-todo.png b/sphinx/themes/pyramid/static/dialog-todo.png
index babc4b6c..9caa91e8 100644
--- a/sphinx/themes/pyramid/static/dialog-todo.png
+++ b/sphinx/themes/pyramid/static/dialog-todo.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/dialog-warning.png b/sphinx/themes/pyramid/static/dialog-warning.png
index 7233d45d..4f598b12 100644
--- a/sphinx/themes/pyramid/static/dialog-warning.png
+++ b/sphinx/themes/pyramid/static/dialog-warning.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/epub.css b/sphinx/themes/pyramid/static/epub.css
index 7465a421..60383755 100644
--- a/sphinx/themes/pyramid/static/epub.css
+++ b/sphinx/themes/pyramid/static/epub.css
@@ -281,7 +281,7 @@ pre {
border-right: none;
}
-tt {
+code {
background-color: #ecf0f3;
padding: 0 1px 0 1px;
font-size: 0.95em;
@@ -291,11 +291,11 @@ th {
background-color: #ede;
}
-.warning tt {
+.warning code {
background: #efc2c2;
}
-.note tt {
+.note code {
background: #d6d6d6;
}
diff --git a/sphinx/themes/pyramid/static/middlebg.png b/sphinx/themes/pyramid/static/middlebg.png
index 2369cfb7..b3a89f4e 100644
--- a/sphinx/themes/pyramid/static/middlebg.png
+++ b/sphinx/themes/pyramid/static/middlebg.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/pyramid.css_t b/sphinx/themes/pyramid/static/pyramid.css_t
index 168e52db..f60f82d2 100644
--- a/sphinx/themes/pyramid/static/pyramid.css_t
+++ b/sphinx/themes/pyramid/static/pyramid.css_t
@@ -295,7 +295,7 @@ pre {
border-left-style: none;
}
-tt {
+code {
background-color: transparent;
color: #222;
font-size: 1.1em;
@@ -336,7 +336,12 @@ a:hover em.std-term {
font-style: normal;
}
-tt.xref {
+code.xref {
font-weight: normal;
font-style: normal;
}
+
+div.code-block-caption {
+ background-color: #ddd;
+ color: #222;
+}
diff --git a/sphinx/themes/scrolls/layout.html b/sphinx/themes/scrolls/layout.html
index a27f60a9..0940d220 100644
--- a/sphinx/themes/scrolls/layout.html
+++ b/sphinx/themes/scrolls/layout.html
@@ -20,7 +20,7 @@
<h1 class="heading"><a href="{{ pathto('index') }}"
title="back to the documentation overview"><span>{{ title|striptags|e }}</span></a></h1>
</div>
- <div class="relnav">
+ <div class="relnav" role="navigation" aria-label="related navigation">
{%- if prev %}
<a href="{{ prev.link|e }}">&laquo; {{ prev.title }}</a> |
{%- endif %}
@@ -31,7 +31,7 @@
</div>
<div id="contentwrapper">
{%- if display_toc %}
- <div id="toc">
+ <div id="toc" role="navigation" aria-label="table of contents navigation">
<h3>{{ _('Table Of Contents') }}</h3>
{{ toc }}
</div>
diff --git a/sphinx/themes/scrolls/static/darkmetal.png b/sphinx/themes/scrolls/static/darkmetal.png
index e8c9ff62..3ed486d5 100644
--- a/sphinx/themes/scrolls/static/darkmetal.png
+++ b/sphinx/themes/scrolls/static/darkmetal.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/logo.png b/sphinx/themes/scrolls/static/logo.png
index d1961cf0..3dc573e0 100644
--- a/sphinx/themes/scrolls/static/logo.png
+++ b/sphinx/themes/scrolls/static/logo.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/metal.png b/sphinx/themes/scrolls/static/metal.png
index 97166f13..e51010b5 100644
--- a/sphinx/themes/scrolls/static/metal.png
+++ b/sphinx/themes/scrolls/static/metal.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/navigation.png b/sphinx/themes/scrolls/static/navigation.png
index 1e248d4d..5be5b318 100644
--- a/sphinx/themes/scrolls/static/navigation.png
+++ b/sphinx/themes/scrolls/static/navigation.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/scrolls.css_t b/sphinx/themes/scrolls/static/scrolls.css_t
index 197aef29..2040d97f 100644
--- a/sphinx/themes/scrolls/static/scrolls.css_t
+++ b/sphinx/themes/scrolls/static/scrolls.css_t
@@ -195,7 +195,7 @@ pre {
font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
}
-tt {
+code {
font-size: 13px;
font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
color: black;
@@ -204,7 +204,7 @@ tt {
border-bottom: 1px solid #eee;
}
-a.reference:hover tt {
+a.reference:hover code {
border-bottom-color: #aaa;
}
@@ -250,7 +250,10 @@ h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink,
-dt:hover > a.headerlink {
+dt:hover > a.headerlink,
+caption:hover > a.headerlink,
+p.caption:hover > a.headerlink,
+div.code-block-caption:hover > a.headerlink {
visibility: visible;
}
@@ -305,6 +308,10 @@ dt .descname {
margin-right: 4px;
}
+dt .sig-paren {
+ font-size: larger;
+}
+
dt .descname, dt .descclassname {
padding: 0;
background: transparent;
diff --git a/sphinx/themes/scrolls/static/watermark.png b/sphinx/themes/scrolls/static/watermark.png
index eb1b6be9..903a96ed 100644
--- a/sphinx/themes/scrolls/static/watermark.png
+++ b/sphinx/themes/scrolls/static/watermark.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/watermark_blur.png b/sphinx/themes/scrolls/static/watermark_blur.png
index 563f6cde..02269006 100644
--- a/sphinx/themes/scrolls/static/watermark_blur.png
+++ b/sphinx/themes/scrolls/static/watermark_blur.png
Binary files differ
diff --git a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t
index 0f3b9aa6..90b5d23a 100644
--- a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t
+++ b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t
@@ -204,20 +204,20 @@ a.headerlink:hover {
color: white!important;
}
-cite, code, tt {
+cite, code, code {
font-family: 'Consolas', 'Deja Vu Sans Mono',
'Bitstream Vera Sans Mono', monospace;
font-size: 0.95em;
letter-spacing: 0.01em;
}
-tt {
+code {
background-color: #f2f2f2;
border-bottom: 1px solid #ddd;
color: #333;
}
-tt.descname, tt.descclassname, tt.xref {
+code.descname, code.descclassname, code.xref {
border: 0;
}
@@ -226,12 +226,12 @@ hr {
margin: 2em;
}
-a tt {
+a code {
border: 0;
color: #CA7900;
}
-a tt:hover {
+a code:hover {
color: #2491CF;
}
@@ -337,3 +337,9 @@ div.viewcode-block:target {
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
+
+div.code-block-caption {
+ background-color: #ddd;
+ color: #222;
+ border: 1px solid #ccc;
+}
diff --git a/sphinx/themes/traditional/static/traditional.css_t b/sphinx/themes/traditional/static/traditional.css_t
index c0328b28..4efb1ff4 100644
--- a/sphinx/themes/traditional/static/traditional.css_t
+++ b/sphinx/themes/traditional/static/traditional.css_t
@@ -318,7 +318,7 @@ div#comments div.comment h4 {
}
div#comments div.comment pre,
-div#comments div.comment tt {
+div#comments div.comment code {
background-color: #ddd;
color: #111;
border: none;
@@ -616,23 +616,23 @@ pre {
border-right: none;
}
-tt {
+code {
font-family: monospace;
background-color: #ecf0f3;
padding: 0 1px 0 1px;
}
-tt.descname {
+code.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
-tt.descclassname {
+code.descclassname {
background-color: transparent;
}
-tt.xref, a tt {
+code.xref, a code {
background-color: transparent;
font-weight: bold;
}
@@ -651,7 +651,7 @@ tt.xref, a tt {
margin-left: 1.5em;
}
-h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
background-color: transparent;
}
@@ -659,6 +659,10 @@ h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
font-size: 1.3em;
}
+.sig-paren {
+ font-size: larger;
+}
+
.versionmodified {
font-style: italic;
}
@@ -698,3 +702,7 @@ div.viewcode-block:target {
margin: -1px -10px;
padding: 0 10px;
}
+
+div.code-block-caption {
+ background-color: #cceeff;
+}
diff --git a/sphinx/theming.py b/sphinx/theming.py
index abc09c17..100a8931 100644
--- a/sphinx/theming.py
+++ b/sphinx/theming.py
@@ -13,9 +13,11 @@ import os
import shutil
import zipfile
import tempfile
-import ConfigParser
from os import path
+from six import string_types, iteritems
+from six.moves import configparser
+
try:
import pkg_resources
except ImportError:
@@ -28,6 +30,7 @@ from sphinx.errors import ThemeError
NODEFAULT = object()
THEMECONF = 'theme.conf'
+
class Theme(object):
"""
Represents the theme chosen in the configuration.
@@ -92,7 +95,8 @@ class Theme(object):
self.themedir = tempfile.mkdtemp('sxt')
self.themedir_created = True
for name in tinfo.namelist():
- if name.endswith('/'): continue
+ if name.endswith('/'):
+ continue
dirname = path.dirname(name)
if not path.isdir(path.join(self.themedir, dirname)):
os.makedirs(path.join(self.themedir, dirname))
@@ -100,12 +104,12 @@ class Theme(object):
fp.write(tinfo.read(name))
fp.close()
- self.themeconf = ConfigParser.RawConfigParser()
+ self.themeconf = configparser.RawConfigParser()
self.themeconf.read(path.join(self.themedir, THEMECONF))
try:
inherit = self.themeconf.get('theme', 'inherit')
- except ConfigParser.NoOptionError:
+ except configparser.NoOptionError:
raise ThemeError('theme %r doesn\'t have "inherit" setting' % name)
if inherit == 'none':
self.base = None
@@ -121,7 +125,7 @@ class Theme(object):
"""
try:
return self.themeconf.get(section, name)
- except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
+ except (configparser.NoOptionError, configparser.NoSectionError):
if self.base is not None:
return self.base.get_confstr(section, name, default)
if default is NODEFAULT:
@@ -141,9 +145,9 @@ class Theme(object):
for conf in reversed(chain):
try:
options.update(conf.items('options'))
- except ConfigParser.NoSectionError:
+ except configparser.NoSectionError:
pass
- for option, value in overrides.iteritems():
+ for option, value in iteritems(overrides):
if option not in options:
raise ThemeError('unsupported theme option %r given' % option)
options[option] = value
@@ -188,7 +192,7 @@ def load_theme_plugins():
except:
path = func_or_path
- if isinstance(path, basestring):
+ if isinstance(path, string_types):
theme_paths.append(path)
else:
raise ThemeError('Plugin %r does not response correctly.' %
diff --git a/sphinx/transforms.py b/sphinx/transforms.py
index 0e103acf..a62fa99a 100644
--- a/sphinx/transforms.py
+++ b/sphinx/transforms.py
@@ -22,8 +22,6 @@ 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,
@@ -36,6 +34,7 @@ default_substitutions = set([
'today',
])
+
class DefaultSubstitutions(Transform):
"""
Replace some substitutions if they aren't defined in the document.
@@ -70,10 +69,10 @@ class MoveModuleTargets(Transform):
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):
+ if ('ismod' in node 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)
@@ -88,10 +87,10 @@ class HandleCodeBlocks(Transform):
# 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):
+ in node.children):
node.replace_self(node.children)
# combine successive doctest blocks
- #for node in self.document.traverse(nodes.doctest_block):
+ # for node in self.document.traverse(nodes.doctest_block):
# if node not in node.parent.children:
# continue
# parindex = node.parent.index(node)
@@ -102,6 +101,31 @@ class HandleCodeBlocks(Transform):
# del node.parent[parindex+1]
+class AutoNumbering(Transform):
+ """
+ Register IDs of tables, figures and literal_blocks to assign numbers.
+ """
+ default_priority = 210
+
+ def apply(self):
+ def has_child(node, cls):
+ return any(isinstance(child, cls) for child in node)
+
+ for node in self.document.traverse(nodes.Element):
+ if isinstance(node, nodes.figure):
+ if has_child(node, nodes.caption):
+ self.document.note_implicit_target(node)
+ elif isinstance(node, nodes.image):
+ if has_child(node.parent, nodes.caption):
+ self.document.note_implicit_target(node.parent)
+ elif isinstance(node, nodes.table):
+ if has_child(node, nodes.title):
+ self.document.note_implicit_target(node)
+ elif isinstance(node, nodes.literal_block):
+ if has_child(node.parent, nodes.caption):
+ self.document.note_implicit_target(node.parent)
+
+
class SortIds(Transform):
"""
Sort secion IDs so that the "id[0-9]+" one comes last.
@@ -143,10 +167,7 @@ class CustomLocaleReporter(object):
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
+ document.reporter.get_source_and_line = self.get_source_and_line
def get_source_and_line(self, lineno=None):
return self.source, self.line
@@ -178,7 +199,7 @@ class Locale(Transform):
parser = RSTParser()
- #phase1: replace reference ids with translated names
+ # 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
@@ -203,7 +224,7 @@ class Locale(Transform):
pass
# XXX doctest and other block markup
if not isinstance(patch, nodes.paragraph):
- continue # skip for now
+ continue # skip for now
processed = False # skip flag
@@ -286,15 +307,14 @@ class Locale(Transform):
node.children = patch.children
node['translated'] = True
-
- #phase2: translation
+ # 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
+ if not msgstr or msgstr == msg: # as-of-yet untranslated
continue
# Avoid "Literal block expected; none found." warnings.
@@ -314,12 +334,13 @@ class Locale(Transform):
pass
# XXX doctest and other block markup
if not isinstance(patch, nodes.paragraph):
- continue # skip for now
+ 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
@@ -344,7 +365,7 @@ class Locale(Transform):
for id in new['ids']:
self.document.ids[id] = new
list_replace_or_append(
- self.document.autofootnote_refs, old, new)
+ self.document.autofootnote_refs, old, new)
if refname:
list_replace_or_append(
self.document.footnote_refs.setdefault(refname, []),
@@ -409,6 +430,7 @@ class Locale(Transform):
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'):
@@ -440,22 +462,23 @@ class Locale(Transform):
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
+ if 'index' in env.config.gettext_enables:
+ # 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):
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index 91b7111c..024e25b1 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -21,22 +21,24 @@ from os import path
from codecs import open, BOM_UTF8
from collections import deque
+from six import iteritems, text_type, binary_type
+from six.moves import range
import docutils
from docutils.utils import relative_path
import jinja2
import sphinx
-from sphinx.errors import PycodeError
-from sphinx.util.pycompat import bytes
+from sphinx.errors import PycodeError, SphinxParallelError
from sphinx.util.console import strip_colors
+from sphinx.util.osutil import fs_encoding
# 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
+ 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
+ explicit_title_re, caption_ref_re
from sphinx.util.matching import patfilter
# Generally useful regular expressions.
@@ -54,7 +56,7 @@ def docname_join(basedocname, docname):
def path_stabilize(filepath):
"normalize path separater and unicode string"
newpath = filepath.replace(os.path.sep, SEP)
- if isinstance(newpath, unicode):
+ if isinstance(newpath, text_type):
newpath = unicodedata.normalize('NFC', newpath)
return newpath
@@ -122,12 +124,17 @@ class FilenameUniqDict(dict):
return uniquename
def purge_doc(self, docname):
- for filename, (docs, unique) in self.items():
+ for filename, (docs, unique) in list(self.items()):
docs.discard(docname)
if not docs:
del self[filename]
self._existing.discard(unique)
+ def merge_other(self, docnames, other):
+ for filename, (docs, unique) in other.items():
+ for doc in docs & docnames:
+ self.add_file(doc, filename)
+
def __getstate__(self):
return self._existing
@@ -184,7 +191,11 @@ _DEBUG_HEADER = '''\
def save_traceback(app):
"""Save the current exception's traceback in a temporary file."""
import platform
- exc = traceback.format_exc()
+ exc = sys.exc_info()[1]
+ if isinstance(exc, SphinxParallelError):
+ exc_format = '(Error in parallel process)\n' + exc.traceback
+ else:
+ exc_format = traceback.format_exc()
fd, path = tempfile.mkstemp('.log', 'sphinx-err-')
last_msgs = ''
if app is not None:
@@ -198,11 +209,14 @@ def save_traceback(app):
jinja2.__version__,
last_msgs)).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'))
+ for extname, extmod in iteritems(app._extensions):
+ modfile = getattr(extmod, '__file__', 'unknown')
+ if isinstance(modfile, bytes):
+ modfile = modfile.decode(fs_encoding, 'replace')
+ os.write(fd, ('# %s (%s) from %s\n' % (
+ extname, app._extension_metadata[extname]['version'],
+ modfile)).encode('utf-8'))
+ os.write(fd, exc_format.encode('utf-8'))
os.close(fd)
return path
@@ -216,7 +230,7 @@ def get_module_source(modname):
if modname not in sys.modules:
try:
__import__(modname)
- except Exception, err:
+ except Exception as err:
raise PycodeError('error importing %r' % modname, err)
mod = sys.modules[modname]
filename = getattr(mod, '__file__', None)
@@ -224,12 +238,12 @@ def get_module_source(modname):
if loader and getattr(loader, 'get_filename', None):
try:
filename = loader.get_filename(modname)
- except Exception, err:
+ except Exception as 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:
+ except Exception as err:
raise PycodeError('error getting source for %r' % modname, err)
if filename is None:
raise PycodeError('no source found for module %r' % modname)
@@ -246,6 +260,20 @@ def get_module_source(modname):
return 'file', filename
+def get_full_modname(modname, attribute):
+ __import__(modname)
+ module = sys.modules[modname]
+
+ # Allow an attribute to have multiple parts and incidentially allow
+ # repeated .s in the attribute.
+ value = module
+ for attr in attribute.split('.'):
+ if attr:
+ value = getattr(value, attr)
+
+ return getattr(value, '__module__', None)
+
+
# a regex to recognize coding cookies
_coding_re = re.compile(r'coding[:=]\s*([-\w.]+)')
@@ -336,7 +364,7 @@ def parselinenos(spec, total):
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))
+ items.extend(range(start, end))
except Exception:
raise ValueError('invalid line number spec: %r' % spec)
return items
@@ -344,7 +372,7 @@ def parselinenos(spec, total):
def force_decode(string, encoding):
"""Forcibly get a unicode string out of a bytestring."""
- if isinstance(string, bytes):
+ if isinstance(string, binary_type):
try:
if encoding:
string = string.decode(encoding)
@@ -376,7 +404,7 @@ def rpartition(s, t):
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))
+ parts = [x.strip() for x in 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
@@ -428,11 +456,13 @@ class PeekableIterator(object):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
"""Return the next item from the iterator."""
if self.remaining:
return self.remaining.popleft()
- return self._iterator.next()
+ return next(self._iterator)
+
+ next = __next__ # Python 2 compatibility
def push(self, item):
"""Push the `item` on the internal stack, it will be returned on the
@@ -442,6 +472,23 @@ class PeekableIterator(object):
def peek(self):
"""Return the next item without changing the state of the iterator."""
- item = self.next()
+ item = next(self)
self.push(item)
return item
+
+
+def get_figtype(node):
+ """Return figtype for given node."""
+ def has_child(node, cls):
+ return any(isinstance(child, cls) for child in node)
+
+ from docutils import nodes
+ if isinstance(node, nodes.figure):
+ return 'figure'
+ elif isinstance(node, nodes.table):
+ return 'table'
+ elif isinstance(node, nodes.container):
+ if has_child(node, nodes.literal_block):
+ return 'code-block'
+
+ return None
diff --git a/sphinx/util/console.py b/sphinx/util/console.py
index 24a22d75..fa7a4a9f 100644
--- a/sphinx/util/console.py
+++ b/sphinx/util/console.py
@@ -13,6 +13,12 @@ import os
import sys
import re
+try:
+ # check if colorama is installed to support color on Windows
+ import colorama
+except ImportError:
+ colorama = None
+
_ansi_re = re.compile('\x1b\\[(\\d\\d;){0,2}\\d\\dm')
codes = {}
@@ -42,6 +48,9 @@ def term_width_line(text):
return text.ljust(_tw + len(text) - len(_ansi_re.sub('', text))) + '\r'
def color_terminal():
+ if sys.platform == 'win32' and colorama is not None:
+ colorama.init()
+ return True
if not hasattr(sys.stdout, 'isatty'):
return False
if not sys.stdout.isatty():
@@ -55,6 +64,8 @@ def color_terminal():
def nocolor():
+ if sys.platform == 'win32' and colorama is not None:
+ colorama.deinit()
codes.clear()
def coloron():
diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py
index d6f46ab9..abb73288 100644
--- a/sphinx/util/docfields.py
+++ b/sphinx/util/docfields.py
@@ -99,7 +99,8 @@ class GroupedField(Field):
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 += self.make_xref(self.rolename, domain, fieldarg,
+ addnodes.literal_strong)
par += nodes.Text(' -- ')
par += content
listnode += nodes.list_item('', par)
@@ -137,7 +138,8 @@ class TypedField(GroupedField):
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)
+ par += self.make_xref(self.rolename, domain, fieldarg,
+ addnodes.literal_strong)
if fieldarg in types:
par += nodes.Text(' (')
# NOTE: using .pop() here to prevent a single type node to be
@@ -238,10 +240,8 @@ class DocFieldTransformer(object):
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)
+ content = [n for n in content if isinstance(n, nodes.Inline) or
+ isinstance(n, nodes.Text)]
if content:
types.setdefault(typename, {})[fieldarg] = content
continue
diff --git a/sphinx/util/docstrings.py b/sphinx/util/docstrings.py
index 71381305..6b66eee9 100644
--- a/sphinx/util/docstrings.py
+++ b/sphinx/util/docstrings.py
@@ -23,7 +23,7 @@ def prepare_docstring(s, ignore=1):
"""
lines = s.expandtabs().splitlines()
# Find minimum indentation of any non-blank lines after ignored lines.
- margin = sys.maxint
+ margin = sys.maxsize
for line in lines[ignore:]:
content = len(line.lstrip())
if content:
@@ -33,7 +33,7 @@ def prepare_docstring(s, ignore=1):
for i in range(ignore):
if i < len(lines):
lines[i] = lines[i].lstrip()
- if margin < sys.maxint:
+ if margin < sys.maxsize:
for i in range(ignore, len(lines)): lines[i] = lines[i][margin:]
# Remove any leading blank lines.
while lines and not lines[0]:
diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py
new file mode 100644
index 00000000..58906781
--- /dev/null
+++ b/sphinx/util/i18n.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.i18n
+ ~~~~~~~~~~~~~~~~
+
+ Builder superclass for all builders.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from os import path
+from collections import namedtuple
+
+from babel.messages.pofile import read_po
+from babel.messages.mofile import write_mo
+
+from sphinx.util.osutil import walk
+
+
+LocaleFileInfoBase = namedtuple('CatalogInfo', 'base_dir,domain')
+
+
+class CatalogInfo(LocaleFileInfoBase):
+
+ @property
+ def po_file(self):
+ return self.domain + '.po'
+
+ @property
+ def mo_file(self):
+ return self.domain + '.mo'
+
+ @property
+ def po_path(self):
+ return path.join(self.base_dir, self.po_file)
+
+ @property
+ def mo_path(self):
+ return path.join(self.base_dir, self.mo_file)
+
+ def is_outdated(self):
+ return (
+ not path.exists(self.mo_path) or
+ path.getmtime(self.mo_path) < path.getmtime(self.po_path))
+
+ def write_mo(self, locale):
+ with open(self.po_path, 'rt') as po:
+ with open(self.mo_path, 'wb') as mo:
+ write_mo(mo, read_po(po, locale))
+
+
+def get_catalogs(locale_dirs, locale, gettext_compact=False, force_all=False):
+ """
+ :param list locale_dirs:
+ list of path as `['locale_dir1', 'locale_dir2', ...]` to find
+ translation catalogs. Each path contains a structure such as
+ `<locale>/LC_MESSAGES/domain.po`.
+ :param str locale: a language as `'en'`
+ :param boolean gettext_compact:
+ * False: keep domains directory structure (default).
+ * True: domains in the sub directory will be merged into 1 file.
+ :param boolean force_all:
+ Set True if you want to get all catalogs rather than updated catalogs.
+ default is False.
+ :return: [CatalogInfo(), ...]
+ """
+ if not locale:
+ return [] # locale is not specified
+
+ catalogs = set()
+ for locale_dir in locale_dirs:
+ base_dir = path.join(locale_dir, locale, 'LC_MESSAGES')
+
+ if not path.exists(base_dir):
+ continue # locale path is not found
+
+ for dirpath, dirnames, filenames in walk(base_dir, followlinks=True):
+ filenames = [f for f in filenames if f.endswith('.po')]
+ for filename in filenames:
+ base = path.splitext(filename)[0]
+ domain = path.relpath(path.join(dirpath, base), base_dir)
+ if gettext_compact and path.sep in domain:
+ domain = path.split(domain)[0]
+ cat = CatalogInfo(base_dir, domain)
+ if force_all or cat.is_outdated():
+ catalogs.add(cat)
+
+ return catalogs
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index cdbfea76..f82f1f45 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -9,17 +9,17 @@
: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 six import PY3, binary_type
+from six.moves import builtins
+
from sphinx.util import force_decode
-from sphinx.util.pycompat import bytes, builtins
-if sys.version_info >= (3, 0):
+if PY3:
from functools import partial
def getargspec(func):
"""Like inspect.getargspec but supports functools.partial as well."""
@@ -55,12 +55,12 @@ if sys.version_info >= (3, 0):
raise TypeError('%r is not a Python function' % func)
return inspect.getfullargspec(func)
-elif sys.version_info >= (2, 5):
+else: # 2.6, 2.7
from functools import partial
def getargspec(func):
"""Like inspect.getargspec but supports functools.partial as well."""
if inspect.ismethod(func):
- func = func.im_func
+ func = func.__func__
parts = 0, ()
if type(func) is partial:
keywords = func.keywords
@@ -70,8 +70,8 @@ elif sys.version_info >= (2, 5):
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
+ args, varargs, varkw = inspect.getargs(func.__code__)
+ func_defaults = func.__defaults__
if func_defaults is None:
func_defaults = []
else:
@@ -86,12 +86,7 @@ elif sys.version_info >= (2, 5):
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
+ return inspect.ArgSpec(args, varargs, varkw, func_defaults)
def isdescriptor(x):
@@ -134,7 +129,7 @@ def safe_repr(object):
s = repr(object)
except Exception:
raise ValueError
- if isinstance(s, bytes):
+ if isinstance(s, binary_type):
return force_decode(s, None).replace('\n', ' ')
return s.replace('\n', ' ')
diff --git a/sphinx/util/jsdump.py b/sphinx/util/jsdump.py
index 85845a72..ede4ae7d 100644
--- a/sphinx/util/jsdump.py
+++ b/sphinx/util/jsdump.py
@@ -12,6 +12,8 @@
import re
+from six import iteritems, integer_types, string_types
+
from sphinx.util.pycompat import u
_str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
@@ -74,7 +76,7 @@ double in super""".split())
def dumps(obj, key=False):
if key:
- if not isinstance(obj, basestring):
+ if not isinstance(obj, string_types):
obj = str(obj)
if _nameonly_re.match(obj) and obj not in reswords:
return obj # return it as a bare word
@@ -84,16 +86,16 @@ def dumps(obj, key=False):
return 'null'
elif obj is True or obj is False:
return obj and 'true' or 'false'
- elif isinstance(obj, (int, long, float)):
+ elif isinstance(obj, integer_types + (float,)):
return str(obj)
elif isinstance(obj, dict):
return '{%s}' % ','.join('%s:%s' % (
dumps(key, True),
dumps(value)
- ) for key, value in obj.iteritems())
+ ) for key, value in iteritems(obj))
elif isinstance(obj, (tuple, list, set)):
return '[%s]' % ','.join(dumps(x) for x in obj)
- elif isinstance(obj, basestring):
+ elif isinstance(obj, string_types):
return encode_string(obj)
raise TypeError(type(obj))
diff --git a/sphinx/util/jsonimpl.py b/sphinx/util/jsonimpl.py
index 8ccbf0cc..ac5c54ae 100644
--- a/sphinx/util/jsonimpl.py
+++ b/sphinx/util/jsonimpl.py
@@ -9,28 +9,18 @@
: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):
+import json
+
+from six import text_type
+from six.moves import UserString
+
+
+class SphinxJSONEncoder(json.JSONEncoder):
"""JSONEncoder subclass that forces translation proxies."""
def default(self, obj):
- if isinstance(obj, UserString.UserString):
- return unicode(obj)
- return JSONEncoder.default(self, obj)
+ if isinstance(obj, UserString):
+ return text_type(obj)
+ return json.JSONEncoder.default(self, obj)
def dump(obj, fp, *args, **kwds):
diff --git a/sphinx/util/matching.py b/sphinx/util/matching.py
index 51b2056d..da8cfa32 100644
--- a/sphinx/util/matching.py
+++ b/sphinx/util/matching.py
@@ -77,4 +77,4 @@ def patfilter(names, pat):
if pat not in _pat_cache:
_pat_cache[pat] = re.compile(_translate_pattern(pat))
match = _pat_cache[pat].match
- return filter(match, names)
+ return list(filter(match, names))
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index eb3b86b5..681046f2 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -10,8 +10,8 @@
"""
import re
-import sys
+from six import text_type
from docutils import nodes
from sphinx import addnodes
@@ -201,7 +201,7 @@ def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc):
tree = tree.deepcopy()
for toctreenode in tree.traverse(addnodes.toctree):
newnodes = []
- includefiles = map(unicode, toctreenode['includefiles'])
+ includefiles = map(text_type, toctreenode['includefiles'])
for includefile in includefiles:
try:
builder.info(colorfunc(includefile) + " ", nonl=1)
@@ -215,6 +215,9 @@ def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc):
else:
sof = addnodes.start_of_file(docname=includefile)
sof.children = subtree.children
+ for sectionnode in sof.traverse(nodes.section):
+ if 'docname' not in sectionnode:
+ sectionnode['docname'] = includefile
newnodes.append(sof)
toctreenode.parent.replace(toctreenode, newnodes)
return tree
@@ -239,12 +242,7 @@ def set_source_info(directive, node):
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)
+ node.source, node.line = inliner.reporter.get_source_and_line(lineno)
# monkey-patch Element.copy to copy the rawsource
@@ -252,17 +250,3 @@ 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
index e98c49b2..2ac06d61 100644
--- a/sphinx/util/osutil.py
+++ b/sphinx/util/osutil.py
@@ -8,6 +8,7 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
import os
import re
@@ -20,6 +21,8 @@ import gettext
from os import path
import contextlib
+from six import PY2, text_type
+
# Errnos that we need.
EEXIST = getattr(errno, 'EEXIST', 0)
ENOENT = getattr(errno, 'ENOENT', 0)
@@ -64,12 +67,15 @@ def ensuredir(path):
"""Ensure that a path exists."""
try:
os.makedirs(path)
- except OSError, err:
+ except OSError as err:
# 0 for Jython/Win32
if err.errno not in [0, EEXIST]:
raise
+# This function is same as os.walk of Python2.6, 2.7, 3.2, 3.3 except a
+# customization that check UnicodeError.
+# The customization obstacle to replace the function with the os.walk.
def walk(top, topdown=True, followlinks=False):
"""Backport of os.walk from 2.6, where the *followlinks* argument was
added.
@@ -81,9 +87,9 @@ def walk(top, topdown=True, followlinks=False):
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))
+ print('%s:: ERROR: non-ASCII filename not supported on this '
+ 'filesystem encoding %r, skipped.' % (name, fs_encoding),
+ file=sys.stderr)
continue
if path.isdir(fullpath):
dirs.append(name)
@@ -144,21 +150,20 @@ 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):
+if PY2:
# 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)
+ return time.strftime(text_type(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)
+ return os.path.relpath(path, start)
except ValueError:
return path
@@ -172,26 +177,19 @@ def find_catalog(docname, compaction):
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]
+ files = [path.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):
@@ -199,9 +197,14 @@ def abspath(pathdir):
return pathdir
+def getcwd():
+ if hasattr(os, 'getcwdu'):
+ return os.getcwdu()
+ return os.getcwd()
+
+
@contextlib.contextmanager
def cd(target_dir):
- from sphinx.util.pycompat import getcwd
cwd = getcwd()
try:
os.chdir(target_dir)
diff --git a/sphinx/util/parallel.py b/sphinx/util/parallel.py
new file mode 100644
index 00000000..5f9e8eff
--- /dev/null
+++ b/sphinx/util/parallel.py
@@ -0,0 +1,131 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.parallel
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Parallel building utilities.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import traceback
+
+try:
+ import multiprocessing
+ import threading
+except ImportError:
+ multiprocessing = threading = None
+
+from six.moves import queue
+
+from sphinx.errors import SphinxParallelError
+
+# our parallel functionality only works for the forking Process
+parallel_available = multiprocessing and (os.name == 'posix')
+
+
+class SerialTasks(object):
+ """Has the same interface as ParallelTasks, but executes tasks directly."""
+
+ def __init__(self, nproc=1):
+ pass
+
+ def add_task(self, task_func, arg=None, result_func=None):
+ if arg is not None:
+ res = task_func(arg)
+ else:
+ res = task_func()
+ if result_func:
+ result_func(res)
+
+ def join(self):
+ pass
+
+
+class ParallelTasks(object):
+ """Executes *nproc* tasks in parallel after forking."""
+
+ def __init__(self, nproc):
+ self.nproc = nproc
+ # list of threads to join when waiting for completion
+ self._taskid = 0
+ self._threads = {}
+ self._nthreads = 0
+ # queue of result objects to process
+ self.result_queue = queue.Queue()
+ self._nprocessed = 0
+ # maps tasks to result functions
+ self._result_funcs = {}
+ # allow only "nproc" worker processes at once
+ self._semaphore = threading.Semaphore(self.nproc)
+
+ def _process(self, pipe, func, arg):
+ try:
+ if arg is None:
+ ret = func()
+ else:
+ ret = func(arg)
+ pipe.send((False, ret))
+ except BaseException as err:
+ pipe.send((True, (err, traceback.format_exc())))
+
+ def _process_thread(self, tid, func, arg):
+ precv, psend = multiprocessing.Pipe(False)
+ proc = multiprocessing.Process(target=self._process,
+ args=(psend, func, arg))
+ proc.start()
+ result = precv.recv()
+ self.result_queue.put((tid, arg) + result)
+ proc.join()
+ self._semaphore.release()
+
+ def add_task(self, task_func, arg=None, result_func=None):
+ tid = self._taskid
+ self._taskid += 1
+ self._semaphore.acquire()
+ thread = threading.Thread(target=self._process_thread,
+ args=(tid, task_func, arg))
+ thread.setDaemon(True)
+ thread.start()
+ self._nthreads += 1
+ self._threads[tid] = thread
+ self._result_funcs[tid] = result_func or (lambda *x: None)
+ # try processing results already in parallel
+ try:
+ tid, arg, exc, result = self.result_queue.get(False)
+ except queue.Empty:
+ pass
+ else:
+ del self._threads[tid]
+ if exc:
+ raise SphinxParallelError(*result)
+ self._result_funcs.pop(tid)(arg, result)
+ self._nprocessed += 1
+
+ def join(self):
+ while self._nprocessed < self._nthreads:
+ tid, arg, exc, result = self.result_queue.get()
+ del self._threads[tid]
+ if exc:
+ raise SphinxParallelError(*result)
+ self._result_funcs.pop(tid)(arg, result)
+ self._nprocessed += 1
+
+ # there shouldn't be any threads left...
+ for t in self._threads.values():
+ t.join()
+
+
+def make_chunks(arguments, nproc, maxbatch=10):
+ # determine how many documents to read in one go
+ nargs = len(arguments)
+ chunksize = min(nargs // nproc, maxbatch)
+ if chunksize == 0:
+ chunksize = 1
+ nchunks, rest = divmod(nargs, chunksize)
+ if rest:
+ nchunks += 1
+ # partition documents in "chunks" that will be written by one Process
+ return [arguments[i*chunksize:(i+1)*chunksize] for i in range(nchunks)]
diff --git a/sphinx/util/png.py b/sphinx/util/png.py
index 65fc4d8d..397adb24 100644
--- a/sphinx/util/png.py
+++ b/sphinx/util/png.py
@@ -12,14 +12,13 @@
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')
+DEPTH_CHUNK_START = b'tEXtDepth\x00'
+IEND_CHUNK = b'\x00\x00\x00\x00IEND\xAE\x42\x60\x82'
def read_png_depth(filename):
diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py
index a2b8d37a..5031dd9b 100644
--- a/sphinx/util/pycompat.py
+++ b/sphinx/util/pycompat.py
@@ -11,24 +11,17 @@
import sys
import codecs
-import encodings
+
+from six import PY3, text_type, exec_
# ------------------------------------------------------------------------------
# Python 2/3 compatibility
-if sys.version_info >= (3, 0):
+if PY3:
# 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 = ''
- # getcwd function
- from os import getcwd
- # StringIO/BytesIO classes
- from io import StringIO, BytesIO, TextIOWrapper
+ from io import TextIOWrapper
# safely encode a string for printing to the terminal
def terminal_safe(s):
return s.encode('ascii', 'backslashreplace').decode('ascii')
@@ -44,25 +37,24 @@ if sys.version_info >= (3, 0):
source = refactoring_tool._read_python_source(filepath)[0]
try:
tree = refactoring_tool.refactor_string(source, 'conf.py')
- except ParseError, err:
+ except ParseError as 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
+ return text_type(tree)
+ from html import escape as htmlescape # >= Python 3.2
+
+ class UnicodeMixin:
+ """Mixin class to handle defining the proper __str__/__unicode__
+ methods in Python 2 or 3."""
+
+ def __str__(self):
+ return self.__unicode__()
else:
# Python 2
- from types import ClassType
- class_types = (type, ClassType)
- b = str
- bytes = str
u = 'u'
- from os import getcwdu as getcwd
- from StringIO import StringIO
- BytesIO = StringIO
# no need to refactor on 2.x versions
convert_with_2to3 = None
def TextIOWrapper(stream, encoding):
@@ -72,10 +64,16 @@ else:
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()
+ sys_encoding = __import__('locale').getpreferredencoding()
# use Python 3 name
- import __builtin__ as builtins
+ from cgi import escape as htmlescape # 2.6, 2.7
+
+ class UnicodeMixin(object):
+ """Mixin class to handle defining the proper __str__/__unicode__
+ methods in Python 2 or 3."""
+
+ def __str__(self):
+ return self.__unicode__().encode('utf8')
def execfile_(filepath, _globals):
@@ -88,9 +86,9 @@ def execfile_(filepath, _globals):
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'))
+ # py26 accept only LF eol instead of CRLF
+ if sys.version_info[:2] == (2, 6):
+ source = source.replace(b'\r\n', b'\n')
# compile to a code object, handle syntax errors
filepath_enc = filepath.encode(fs_encoding)
@@ -104,186 +102,4 @@ def execfile_(filepath, _globals):
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
-
- from collections import deque
-
-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
-
- from collections import deque as _deque
- def deque(maxlen):
- return _deque()
-
-# ------------------------------------------------------------------------------
-# 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
+ exec_(code, _globals)
diff --git a/sphinx/util/tags.py b/sphinx/util/tags.py
index 2a9b2a02..d5141587 100644
--- a/sphinx/util/tags.py
+++ b/sphinx/util/tags.py
@@ -35,9 +35,9 @@ class BooleanParser(Parser):
node = nodes.Const(None, lineno=token.lineno)
else:
node = nodes.Name(token.value, 'load', lineno=token.lineno)
- self.stream.next()
+ next(self.stream)
elif token.type == 'lparen':
- self.stream.next()
+ next(self.stream)
node = self.parse_expression()
self.stream.expect('rparen')
else:
diff --git a/sphinx/util/texescape.py b/sphinx/util/texescape.py
index c0619f46..6fcf9ff0 100644
--- a/sphinx/util/texescape.py
+++ b/sphinx/util/texescape.py
@@ -9,93 +9,95 @@
:license: BSD, see LICENSE for details.
"""
+from __future__ import unicode_literals
+
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{}'),
+ ('$', r'\$'),
+ ('%', r'\%'),
+ ('&', r'\&'),
+ ('#', r'\#'),
+ ('_', r'\_'),
+ ('{', r'\{'),
+ ('}', r'\}'),
+ ('[', r'{[}'),
+ (']', r'{]}'),
+ ('`', r'{}`'),
+ ('\\',r'\textbackslash{}'),
+ ('~', r'\textasciitilde{}'),
+ ('<', r'\textless{}'),
+ ('>', r'\textgreater{}'),
+ ('^', r'\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\)'),
+ ('¶', r'\P{}'),
+ ('§', r'\S{}'),
+ ('€', r'\texteuro{}'),
+ ('∞', r'\(\infty\)'),
+ ('±', r'\(\pm\)'),
+ ('→', r'\(\rightarrow\)'),
+ ('‣', r'\(\rightarrow\)'),
# used to separate -- in options
- (u'', ur'{}'),
+ ('', r'{}'),
# 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'),
+ ('─', r'-'),
+ ('⎽', r'\_'),
+ ('╲', r'\textbackslash{}'),
+ ('|', r'\textbar{}'),
+ ('│', r'\textbar{}'),
+ ('ℯ', r'e'),
+ ('â…ˆ', r'i'),
+ ('â‚', r'1'),
+ ('â‚‚', r'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\)'),
+ ('α', r'\(\alpha\)'),
+ ('β', r'\(\beta\)'),
+ ('γ', r'\(\gamma\)'),
+ ('δ', r'\(\delta\)'),
+ ('ε', r'\(\epsilon\)'),
+ ('ζ', r'\(\zeta\)'),
+ ('η', r'\(\eta\)'),
+ ('θ', r'\(\theta\)'),
+ ('ι', r'\(\iota\)'),
+ ('κ', r'\(\kappa\)'),
+ ('λ', r'\(\lambda\)'),
+ ('μ', r'\(\mu\)'),
+ ('ν', r'\(\nu\)'),
+ ('ξ', r'\(\xi\)'),
+ ('ο', r'o'),
+ ('Ï€', r'\(\pi\)'),
+ ('Ï', r'\(\rho\)'),
+ ('σ', r'\(\sigma\)'),
+ ('Ï„', r'\(\tau\)'),
+ ('Ï…', '\\(\\upsilon\\)'),
+ ('φ', r'\(\phi\)'),
+ ('χ', r'\(\chi\)'),
+ ('ψ', r'\(\psi\)'),
+ ('ω', r'\(\omega\)'),
+ ('Α', r'A'),
+ ('Î’', r'B'),
+ ('Γ', r'\(\Gamma\)'),
+ ('Δ', r'\(\Delta\)'),
+ ('Ε', r'E'),
+ ('Ζ', r'Z'),
+ ('Η', r'H'),
+ ('Θ', r'\(\Theta\)'),
+ ('Ι', r'I'),
+ ('Κ', r'K'),
+ ('Λ', r'\(\Lambda\)'),
+ ('Μ', r'M'),
+ ('Î', r'N'),
+ ('Ξ', r'\(\Xi\)'),
+ ('Ο', r'O'),
+ ('Π', r'\(\Pi\)'),
+ ('Ρ', r'P'),
+ ('Σ', r'\(\Sigma\)'),
+ ('Τ', r'T'),
+ ('Î¥', '\\(\\Upsilon\\)'),
+ ('Φ', r'\(\Phi\)'),
+ ('Χ', r'X'),
+ ('Ψ', r'\(\Psi\)'),
+ ('Ω', r'\(\Omega\)'),
+ ('Ω', r'\(\Omega\)'),
]
tex_escape_map = {}
@@ -105,8 +107,8 @@ 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'_'
+ tex_replace_map[ord(a)] = '_'
for a, b in tex_replacements:
- if a in u'[]{}\\': continue
+ if a in '[]{}\\': continue
tex_hl_escape_map_new[ord(a)] = b
diff --git a/sphinx/versioning.py b/sphinx/versioning.py
index f10e0f21..1be4d39b 100644
--- a/sphinx/versioning.py
+++ b/sphinx/versioning.py
@@ -11,9 +11,16 @@
"""
from uuid import uuid4
from operator import itemgetter
+from itertools import product
-from sphinx.util.pycompat import product, zip_longest, all
+from six import iteritems
+from six.moves import range, zip_longest
+try:
+ import Levenshtein
+ IS_SPEEDUP = True
+except ImportError:
+ IS_SPEEDUP = False
# anything below that ratio is considered equal/changed
VERSIONING_RATIO = 65
@@ -55,6 +62,9 @@ def merge_doctrees(old, new, condition):
if old_node is None:
new_nodes.append(new_node)
continue
+ if not getattr(old_node, 'uid', None):
+ # maybe config.gettext_uuid has been changed.
+ old_node.uid = uuid4().hex
if new_node is None:
old_nodes.append(old_node)
continue
@@ -80,7 +90,7 @@ def merge_doctrees(old, new, condition):
# 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))
+ ratios = sorted(iteritems(ratios), key=itemgetter(1))
for (old_node, new_node), ratio in ratios:
if new_node in seen:
continue
@@ -104,7 +114,11 @@ def get_ratio(old, new):
"""
if not all([old, new]):
return VERSIONING_RATIO
- return levenshtein_distance(old, new) / (len(old) / 100.0)
+
+ if IS_SPEEDUP:
+ return Levenshtein.distance(old, new) / (len(old) / 100.0)
+ else:
+ return levenshtein_distance(old, new) / (len(old) / 100.0)
def levenshtein_distance(a, b):
@@ -115,7 +129,7 @@ def levenshtein_distance(a, b):
a, b = b, a
if not a:
return len(b)
- previous_row = xrange(len(b) + 1)
+ previous_row = range(len(b) + 1)
for i, column1 in enumerate(a):
current_row = [i + 1]
for j, column2 in enumerate(b):
diff --git a/sphinx/websupport/__init__.py b/sphinx/websupport/__init__.py
index 0e9131d0..4cdedc0d 100644
--- a/sphinx/websupport/__init__.py
+++ b/sphinx/websupport/__init__.py
@@ -10,12 +10,11 @@
"""
import sys
-import cPickle as pickle
import posixpath
from os import path
+from six.moves import cPickle as pickle
from jinja2 import Environment, FileSystemLoader
-
from docutils.core import publish_parts
from sphinx.application import Sphinx
diff --git a/sphinx/websupport/search/__init__.py b/sphinx/websupport/search/__init__.py
index 45068d29..f2a67b4d 100644
--- a/sphinx/websupport/search/__init__.py
+++ b/sphinx/websupport/search/__init__.py
@@ -11,6 +11,8 @@
import re
+from six import text_type
+
class BaseSearch(object):
def __init__(self, path):
@@ -109,7 +111,7 @@ class BaseSearch(object):
context_end < len(text) and '...' or ''])
try:
- return unicode(context, errors='ignore')
+ return text_type(context, errors='ignore')
except TypeError:
return context
diff --git a/sphinx/websupport/search/whooshsearch.py b/sphinx/websupport/search/whooshsearch.py
index 6d1f9de4..17adf058 100644
--- a/sphinx/websupport/search/whooshsearch.py
+++ b/sphinx/websupport/search/whooshsearch.py
@@ -14,6 +14,8 @@ from whoosh.fields import Schema, ID, TEXT
from whoosh.qparser import QueryParser
from whoosh.analysis import StemmingAnalyzer
+from six import text_type
+
from sphinx.util.osutil import ensuredir
from sphinx.websupport.search import BaseSearch
@@ -43,7 +45,7 @@ class WhooshSearch(BaseSearch):
self.index_writer.commit()
def add_document(self, pagename, title, text):
- self.index_writer.add_document(path=unicode(pagename),
+ self.index_writer.add_document(path=text_type(pagename),
title=title,
text=text)
diff --git a/sphinx/websupport/storage/sqlalchemy_db.py b/sphinx/websupport/storage/sqlalchemy_db.py
index 7baf8830..afabeade 100644
--- a/sphinx/websupport/storage/sqlalchemy_db.py
+++ b/sphinx/websupport/storage/sqlalchemy_db.py
@@ -131,7 +131,7 @@ class Comment(Base):
proposal_diff = Column(Text)
path = Column(String(256), index=True)
- node_id = Column(String, ForeignKey(db_prefix + 'nodes.id'))
+ node_id = Column(String(32), ForeignKey(db_prefix + 'nodes.id'))
node = relation(Node, backref="comments")
votes = relation(CommentVote, backref="comment",
diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py
index c69c2e09..836464a3 100644
--- a/sphinx/writers/html.py
+++ b/sphinx/writers/html.py
@@ -14,6 +14,7 @@ import posixpath
import os
import copy
+from six import string_types
from docutils import nodes
from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator
@@ -70,11 +71,11 @@ class HTMLTranslator(BaseTranslator):
self.no_smarty = 0
self.builder = builder
self.highlightlang = builder.config.highlight_language
- self.highlightlinenothreshold = sys.maxint
+ self.highlightlinenothreshold = sys.maxsize
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):
+ if not isinstance(self.permalink_text, string_types):
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
@@ -101,18 +102,13 @@ class HTMLTranslator(BaseTranslator):
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.add_permalink_ref(node, 'definition')
self.body.append('</dt>\n')
def visit_desc_addname(self, node):
- self.body.append(self.starttag(node, 'tt', '', CLASS='descclassname'))
+ self.body.append(self.starttag(node, 'code', '', CLASS='descclassname'))
def depart_desc_addname(self, node):
- self.body.append('</tt>')
+ self.body.append('</code>')
def visit_desc_type(self, node):
pass
@@ -125,12 +121,12 @@ class HTMLTranslator(BaseTranslator):
pass
def visit_desc_name(self, node):
- self.body.append(self.starttag(node, 'tt', '', CLASS='descname'))
+ self.body.append(self.starttag(node, 'code', '', CLASS='descname'))
def depart_desc_name(self, node):
- self.body.append('</tt>')
+ self.body.append('</code>')
def visit_desc_parameterlist(self, node):
- self.body.append('<big>(</big>')
+ self.body.append('<span class="sig-paren">(</span>')
self.first_param = 1
self.optional_param_level = 0
# How many required parameters are left.
@@ -138,7 +134,7 @@ class HTMLTranslator(BaseTranslator):
for c in node.children])
self.param_separator = node.child_text_separator
def depart_desc_parameterlist(self, node):
- self.body.append('<big>)</big>')
+ self.body.append('<span class="sig-paren">)</span>')
# If required parameters are still to come, then put the comma after
# the parameter. Otherwise, put the comma before. This ensures that
@@ -211,6 +207,12 @@ class HTMLTranslator(BaseTranslator):
self.body.append(('%s' + self.secnumber_suffix) %
'.'.join(map(str, node['secnumber'])))
+ def visit_number_reference(self, node):
+ self.visit_reference(node)
+
+ def depart_number_reference(self, node):
+ self.depart_reference(node)
+
# overwritten -- we don't want source comments to show up in the HTML
def visit_comment(self, node):
raise nodes.SkipNode
@@ -233,14 +235,44 @@ class HTMLTranslator(BaseTranslator):
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.name == 'singlehtml':
+ docname = node.parent.get('docname')
+ anchorname = '#' + node.parent['ids'][0]
+ if (docname, anchorname) not in self.builder.secnumbers:
+ anchorname = (docname, '') # try first heading which has no anchor
+ else:
+ anchorname = (docname, anchorname)
+ else:
+ 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)
+ def add_fignumber(self, node):
+ def append_fignumber(figtype, figure_id):
+ if figure_id in self.builder.fignumbers.get(figtype, {}):
+ self.body.append('<span class="caption-number">')
+ prefix = self.builder.config.numfig_prefix.get(figtype, '')
+ numbers = self.builder.fignumbers[figtype][figure_id]
+ self.body.append(prefix % '.'.join(map(str, numbers)) + ' ')
+ self.body.append('</span>')
+
+ if isinstance(node.parent, nodes.figure):
+ append_fignumber('figure', node.parent['ids'][0])
+ elif isinstance(node.parent, nodes.table):
+ append_fignumber('table', node.parent['ids'][0])
+ elif isinstance(node.parent, nodes.container):
+ append_fignumber('code-block', node.parent['ids'][0])
+
+ def add_permalink_ref(self, node, typename):
+ if node['ids'] and self.permalink_text and self.builder.add_permalinks:
+ title = _('Permalink to this %s' % typename)
+ format = u'<a class="headerlink" href="#%s" title="%s">%s</a>'
+ self.body.append(format % (node['ids'][0], title, self.permalink_text))
+
# overwritten to avoid emitting empty <ul></ul>
def visit_bullet_list(self, node):
if len(node) == 1 and node[0].tagname == 'toctree':
@@ -251,6 +283,9 @@ class HTMLTranslator(BaseTranslator):
def visit_title(self, node):
BaseTranslator.visit_title(self, node)
self.add_secnumber(node)
+ self.add_fignumber(node)
+ if isinstance(node.parent, nodes.table):
+ self.body.append('<span class="caption-text">')
# overwritten
def visit_literal_block(self, node):
@@ -261,11 +296,11 @@ class HTMLTranslator(BaseTranslator):
linenos = node.rawsource.count('\n') >= \
self.highlightlinenothreshold - 1
highlight_args = node.get('highlight_args', {})
- if node.has_key('language'):
+ if 'language' in node:
# code-block directives
lang = node['language']
highlight_args['force'] = True
- if node.has_key('linenos'):
+ if 'linenos' in node:
linenos = node['linenos']
def warner(msg):
self.builder.warn(msg, (self.builder.current_docname, node.line))
@@ -277,6 +312,28 @@ class HTMLTranslator(BaseTranslator):
self.body.append(starttag + highlighted + '</div>\n')
raise nodes.SkipNode
+ def visit_caption(self, node):
+ if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
+ self.body.append('<div class="code-block-caption">')
+ else:
+ BaseTranslator.visit_caption(self, node)
+ self.add_fignumber(node)
+ self.body.append(self.starttag(node, 'span', '', CLASS='caption-text'))
+
+ def depart_caption(self, node):
+ self.body.append('</span>')
+
+ # append permalink if available
+ if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
+ self.add_permalink_ref(node.parent, 'code')
+ elif isinstance(node.parent, nodes.figure):
+ self.add_permalink_ref(node.parent, 'image')
+
+ if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
+ self.body.append('</div>\n')
+ else:
+ BaseTranslator.depart_caption(self, node)
+
def visit_doctest_block(self, node):
self.visit_literal_block(node)
@@ -288,12 +345,12 @@ class HTMLTranslator(BaseTranslator):
# overwritten
def visit_literal(self, node):
- self.body.append(self.starttag(node, 'tt', '',
+ self.body.append(self.starttag(node, 'code', '',
CLASS='docutils literal'))
self.protect_literal_text += 1
def depart_literal(self, node):
self.protect_literal_text -= 1
- self.body.append('</tt>')
+ self.body.append('</code>')
def visit_productionlist(self, node):
self.body.append(self.starttag(node, 'pre'))
@@ -371,13 +428,13 @@ class HTMLTranslator(BaseTranslator):
if node['uri'].lower().endswith('svg') or \
node['uri'].lower().endswith('svgz'):
atts = {'src': node['uri']}
- if node.has_key('width'):
+ if 'width' in node:
atts['width'] = node['width']
- if node.has_key('height'):
+ if 'height' in node:
atts['height'] = node['height']
- if node.has_key('alt'):
+ if 'alt' in node:
atts['alt'] = node['alt']
- if node.has_key('align'):
+ if 'align' in node:
self.body.append('<div align="%s" class="align-%s">' %
(node['align'], node['align']))
self.context.append('</div>\n')
@@ -386,21 +443,21 @@ class HTMLTranslator(BaseTranslator):
self.body.append(self.emptytag(node, 'img', '', **atts))
return
- if node.has_key('scale'):
+ if 'scale' in node:
# 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')):
+ if Image and not ('width' in node
+ and 'height' in node):
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'):
+ if 'width' not in node:
node['width'] = str(im.size[0])
- if not node.has_key('height'):
+ if 'height' not in node:
node['height'] = str(im.size[1])
try:
im.fp.close()
@@ -518,6 +575,11 @@ class HTMLTranslator(BaseTranslator):
def depart_literal_emphasis(self, node):
return self.depart_emphasis(node)
+ def visit_literal_strong(self, node):
+ return self.visit_strong(node)
+ def depart_literal_strong(self, node):
+ return self.depart_strong(node)
+
def visit_abbreviation(self, node):
attrs = {}
if node.hasattr('explanation'):
@@ -533,20 +595,19 @@ class HTMLTranslator(BaseTranslator):
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]
+ node.parent.hasattr('ids') and node.parent['ids']):
# 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))
+ self.add_permalink_ref(node.parent, 'headline')
elif close_tag.startswith('</a></h'):
self.body.append(u'</a><a class="headerlink" href="#%s" ' %
- aname +
+ node.parent['ids'][0] +
u'title="%s">%s' % (
_('Permalink to this headline'),
self.permalink_text))
+ elif isinstance(node.parent, nodes.table):
+ self.body.append('</span>')
+ self.add_permalink_ref(node.parent, 'table')
BaseTranslator.depart_title(self, node)
@@ -628,6 +689,14 @@ class SmartyPantsHTMLTranslator(HTMLTranslator):
self.depart_emphasis(node)
self.no_smarty -= 1
+ def visit_literal_strong(self, node):
+ self.no_smarty += 1
+ self.visit_strong(node)
+
+ def depart_literal_strong(self, node):
+ self.depart_strong(node)
+ self.no_smarty -= 1
+
def visit_desc_signature(self, node):
self.no_smarty += 1
HTMLTranslator.visit_desc_signature(self, node)
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index 8c9b1f5c..dd85a806 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -16,6 +16,7 @@ import re
import sys
from os import path
+from six import itervalues, text_type
from docutils import nodes, writers
from docutils.writers.latex2e import Babel
@@ -25,7 +26,6 @@ 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
@@ -42,6 +42,7 @@ HEADER = r'''%% Generated by Sphinx.
%(longtable)s
\usepackage{sphinx}
\usepackage{multirow}
+%(usepackages)s
%(preamble)s
\title{%(title)s}
@@ -89,9 +90,11 @@ class LaTeXWriter(writers.Writer):
def __init__(self, builder):
writers.Writer.__init__(self)
self.builder = builder
+ self.translator_class = (
+ self.builder.translator_class or LaTeXTranslator)
def translate(self):
- visitor = LaTeXTranslator(self.document, self.builder)
+ visitor = self.translator_class(self.document, self.builder)
self.document.walkabout(visitor)
self.output = visitor.astext()
@@ -151,6 +154,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
'fontpkg': '\\usepackage{times}',
'fncychap': '\\usepackage[Bjarne]{fncychap}',
'longtable': '\\usepackage{longtable}',
+ 'usepackages': '',
'preamble': '',
'title': '',
'date': '',
@@ -165,6 +169,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
'footer': '',
'printindex': '\\printindex',
'transition': '\n\n\\bigskip\\hrule{}\\bigskip\n\n',
+ 'figure_align': 'htbp',
}
# sphinx specific document classes
@@ -231,6 +236,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.elements['fncychap'] = ''
else:
self.elements['classoptions'] += ',english'
+ if getattr(builder, 'usepackages', None):
+ def declare_package(packagename, options=None):
+ if options:
+ return '\\usepackage[%s]{%s}' % (options, packagename)
+ else:
+ return '\\usepackage{%s}' % (packagename,)
+ usepackages = (declare_package(*p) for p in builder.usepackages)
+ self.elements['usepackages'] += "\n".join(usepackages)
# allow the user to override them all
self.elements.update(builder.config.latex_elements)
if self.elements['extraclassoptions']:
@@ -249,7 +262,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
# 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]]
+ sys.maxsize]]
self.footnotestack = []
self.curfilestack = []
self.handled_abbrs = set()
@@ -263,6 +276,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.next_section_ids = set()
self.next_figure_ids = set()
self.next_table_ids = set()
+ self.next_literal_ids = set()
# flags
self.in_title = 0
self.in_production_list = 0
@@ -306,7 +320,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
return '\\autopageref*{%s}' % self.idescape(id)
def idescape(self, id):
- return unicode(id).translate(tex_replace_map).\
+ return text_type(id).translate(tex_replace_map).\
encode('ascii', 'backslashreplace').decode('ascii').\
replace('\\', '_')
@@ -319,7 +333,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
if i > 0:
ret.append('\\indexspace\n')
ret.append('\\bigletter{%s}\n' %
- unicode(letter).translate(tex_escape_map))
+ text_type(letter).translate(tex_escape_map))
for entry in entries:
if not entry[3]:
continue
@@ -335,7 +349,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
# 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 domain in itervalues(self.builder.env.domains):
for indexcls in domain.indices:
indexname = '%s-%s' % (domain.name, indexcls.name)
if isinstance(indices_config, list):
@@ -381,7 +395,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
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.encode(bi[0]), self.idescape(bi[0]), target, bi[1]))
self.body.append(u'\\end{thebibliography}\n')
self.bibitems = []
@@ -668,6 +682,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
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)
+ 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('\n\\begin{longtable}')
endmacro = '\\end{longtable}\n\n'
@@ -695,11 +712,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
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:
+ self.body.append(u'\\caption{%s}' % self.table.caption)
for id in self.next_table_ids:
self.body.append(self.hypertarget(id, anchor=False))
self.next_table_ids.clear()
+ self.body.append(u'\\\\\n')
if self.table.longtable:
self.body.append('\\hline\n')
self.body.extend(self.tableheaders)
@@ -710,7 +727,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
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.body.append(r'\hline \multicolumn{%s}{|r|}{{\textsf{%s}}} \\ \hline'
% (self.table.colcount,
_('Continued on next page')))
self.body.append('\n\\endfoot\n\n')
@@ -743,14 +760,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
# Redirect head output until header is finished. see visit_tbody.
self.body = self.tableheaders
def depart_thead(self, node):
- self.body.append('\\hline')
+ pass
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')
+ pass
def visit_row(self, node):
self.table.col = 0
@@ -758,6 +775,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
if self.previous_spanning_row == 1:
self.previous_spanning_row = 0
self.body.append('\\\\\n')
+ self.body.append('\\hline')
self.table.rowcount += 1
def visit_entry(self, node):
@@ -1006,7 +1024,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
# 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)
+ self.body.append('\\begin{figure}[%s]%s\n' % (
+ self.elements['figure_align'], 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')
@@ -1098,12 +1117,18 @@ class LaTeXTranslator(nodes.NodeVisitor):
return
elif isinstance(next, nodes.table):
# same for tables, but only if they have a caption
- for n in node:
+ for n in next:
if isinstance(n, nodes.title):
if node.get('refid'):
self.next_table_ids.add(node['refid'])
self.next_table_ids.update(node['ids'])
return
+ elif isinstance(next, nodes.container) and next.get('literal_block'):
+ # same for literal_block, but only if they have a caption
+ if node.get('refid'):
+ self.next_literal_ids.add(node['refid'])
+ self.next_literal_ids.update(node['ids'])
+ return
except IndexError:
pass
if 'refuri' in node:
@@ -1134,26 +1159,26 @@ class LaTeXTranslator(nodes.NodeVisitor):
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))
+ p1, p2 = [self.encode(x) for x in 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))
+ p1, p2, p3 = [self.encode(x)
+ for x in 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))
+ p1, p2 = [self.encode(x) for x in 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))
+ p1, p2 = [self.encode(x) for x in 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:
+ except ValueError as err:
self.builder.warn(str(err))
raise nodes.SkipNode
@@ -1163,6 +1188,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
raise nodes.SkipNode
def visit_reference(self, node):
+ for id in node.get('ids'):
+ self.body += self.hypertarget(id, anchor=True)
uri = node.get('refuri', '')
if not uri and node.get('refid'):
uri = '%' + self.curfilestack[-1] + '#' + node['refid']
@@ -1220,6 +1247,18 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_reference(self, node):
self.body.append(self.context.pop())
+ def visit_number_reference(self, node):
+ if node.get('refid'):
+ id = self.curfilestack[-1] + ':' + node['refid']
+ else:
+ id = node.get('refuri', '')[1:].replace('#', ':')
+
+ ref = '\\ref{%s}' % self.idescape(id)
+ title = node.get('title', '#')
+ self.body.append(title.replace('#', ref))
+
+ raise nodes.SkipNode
+
def visit_download_reference(self, node):
pass
def depart_download_reference(self, node):
@@ -1247,6 +1286,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_strong(self, node):
self.body.append('}')
+ def visit_literal_strong(self, node):
+ self.body.append(r'\textbf{\texttt{')
+ self.no_contractions += 1
+ def depart_literal_strong(self, node):
+ self.body.append('}}')
+ self.no_contractions -= 1
+
def visit_abbreviation(self, node):
abbr = node.astext()
self.body.append(r'\textsc{')
@@ -1475,9 +1521,17 @@ class LaTeXTranslator(nodes.NodeVisitor):
pass
def visit_container(self, node):
- pass
+ if node.get('literal_block'):
+ ids = ''
+ for id in self.next_literal_ids:
+ ids += self.hypertarget(id, anchor=False)
+ self.next_literal_ids.clear()
+ self.body.append('\n\\begin{literal-block}\n')
+ self.context.append(ids + '\n\\end{literal-block}\n')
+
def depart_container(self, node):
- pass
+ if node.get('literal_block'):
+ self.body.append(self.context.pop())
def visit_decoration(self, node):
pass
@@ -1498,7 +1552,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
# text handling
def encode(self, text):
- text = unicode(text).translate(tex_escape_map)
+ text = text_type(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.
diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py
index 4b51588a..bc842057 100644
--- a/sphinx/writers/manpage.py
+++ b/sphinx/writers/manpage.py
@@ -10,14 +10,11 @@
"""
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 docutils.writers.manpage import (
+ MACRO_DEF,
+ Writer,
+ Translator as BaseTranslator
+)
from sphinx import addnodes
from sphinx.locale import admonitionlabels, _
@@ -29,9 +26,11 @@ class ManualPageWriter(Writer):
def __init__(self, builder):
Writer.__init__(self)
self.builder = builder
+ self.translator_class = (
+ self.builder.translator_class or ManualPageTranslator)
def translate(self):
- visitor = ManualPageTranslator(self.builder, self.document)
+ visitor = self.translator_class(self.builder, self.document)
self.visitor = visitor
self.document.walkabout(visitor)
self.output = visitor.astext()
@@ -247,6 +246,11 @@ class ManualPageTranslator(BaseTranslator):
'>'])
raise nodes.SkipNode
+ def visit_number_reference(self, node):
+ text = nodes.Text(node.get('title', '#'))
+ self.visit_Text(text)
+ raise nodes.SkipNode
+
def visit_centered(self, node):
self.ensure_eol()
self.body.append('.sp\n.ce\n')
@@ -304,6 +308,11 @@ class ManualPageTranslator(BaseTranslator):
def depart_literal_emphasis(self, node):
return self.depart_emphasis(node)
+ def visit_literal_strong(self, node):
+ return self.visit_strong(node)
+ def depart_literal_strong(self, node):
+ return self.depart_strong(node)
+
def visit_abbreviation(self, node):
pass
def depart_abbreviation(self, node):
diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py
index fcfce03e..93d4d6aa 100644
--- a/sphinx/writers/texinfo.py
+++ b/sphinx/writers/texinfo.py
@@ -10,10 +10,11 @@
"""
import re
-import string
import textwrap
from os import path
+from six import itervalues
+from six.moves import range
from docutils import nodes, writers
from sphinx import addnodes, __version__
@@ -119,9 +120,12 @@ class TexinfoWriter(writers.Writer):
def __init__(self, builder):
writers.Writer.__init__(self)
self.builder = builder
+ self.translator_class = (
+ self.builder.translator_class or TexinfoTranslator)
def translate(self):
- self.visitor = visitor = TexinfoTranslator(self.document, self.builder)
+ self.visitor = visitor = self.translator_class(
+ self.document, self.builder)
self.document.walkabout(visitor)
visitor.finish()
for attr in self.visitor_attributes:
@@ -457,7 +461,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
indices_config = self.builder.config.texinfo_domain_indices
if indices_config:
- for domain in self.builder.env.domains.itervalues():
+ for domain in itervalues(self.builder.env.domains):
for indexcls in domain.indices:
indexname = '%s-%s' % (domain.name, indexcls.name)
if isinstance(indices_config, list):
@@ -655,7 +659,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
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,)):
+ if isinstance(node.parent, (nodes.title, addnodes.desc_type)):
return
if isinstance(node[0], nodes.image):
return
@@ -718,6 +722,11 @@ class TexinfoTranslator(nodes.NodeVisitor):
def depart_reference(self, node):
pass
+ def visit_number_reference(self, node):
+ text = nodes.Text(node.get('title', '#'))
+ self.visit_Text(text)
+ raise nodes.SkipNode
+
def visit_title_reference(self, node):
text = node.astext()
self.body.append('@cite{%s}' % self.escape_arg(text))
@@ -974,7 +983,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
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)):
+ for i in range(node.get('morecols', 0)):
self.body.append('\n@tab\n')
## Field Lists
@@ -1050,9 +1059,11 @@ class TexinfoTranslator(nodes.NodeVisitor):
raise nodes.SkipNode
def visit_container(self, node):
- pass
+ if node.get('literal_block'):
+ self.body.append('\n\n@float LiteralBlock\n')
def depart_container(self, node):
- pass
+ if node.get('literal_block'):
+ self.body.append('\n@end float\n\n')
def visit_decoration(self, node):
pass
@@ -1091,13 +1102,15 @@ class TexinfoTranslator(nodes.NodeVisitor):
self.body.append('\n@end float\n\n')
def visit_caption(self, node):
- if not isinstance(node.parent, nodes.figure):
+ if (isinstance(node.parent, nodes.figure) or
+ (isinstance(node.parent, nodes.container) and node.parent.get('literal_block'))):
+ self.body.append('\n@caption{')
+ else:
self.builder.warn('caption not inside a figure.',
(self.curfilestack[-1], node.line))
- return
- self.body.append('\n@caption{')
def depart_caption(self, node):
- if isinstance(node.parent, nodes.figure):
+ if (isinstance(node.parent, nodes.figure) or
+ (isinstance(node.parent, nodes.container) and node.parent.get('literal_block'))):
self.body.append('}\n')
def visit_image(self, node):
@@ -1207,6 +1220,11 @@ class TexinfoTranslator(nodes.NodeVisitor):
def depart_literal_emphasis(self, node):
self.body.append('}')
+ def visit_literal_strong(self, node):
+ self.body.append('@code{')
+ def depart_literal_strong(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):
diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py
index e6238364..efd32df3 100644
--- a/sphinx/writers/text.py
+++ b/sphinx/writers/text.py
@@ -13,12 +13,13 @@ import re
import textwrap
from itertools import groupby
+from six.moves import zip_longest
+
from docutils import nodes, writers
from docutils.utils import column_width
from sphinx import addnodes
from sphinx.locale import admonitionlabels, _
-from sphinx.util.pycompat import zip_longest
class TextWrapper(textwrap.TextWrapper):
@@ -141,9 +142,10 @@ class TextWriter(writers.Writer):
def __init__(self, builder):
writers.Writer.__init__(self)
self.builder = builder
+ self.translator_class = self.builder.translator_class or TextTranslator
def translate(self):
- visitor = TextTranslator(self.document, self.builder)
+ visitor = self.translator_class(self.document, self.builder)
self.document.walkabout(visitor)
self.output = visitor.body
@@ -460,7 +462,7 @@ class TextTranslator(nodes.NodeVisitor):
pass
def visit_entry(self, node):
- if node.has_key('morerows') or node.has_key('morecols'):
+ if 'morerows' in node or 'morecols' in node:
raise NotImplementedError('Column or row spanning cells are '
'not implemented.')
self.new_state(0)
@@ -489,7 +491,7 @@ class TextTranslator(nodes.NodeVisitor):
for i, cell in enumerate(line):
par = my_wrap(cell, width=colwidths[i])
if par:
- maxwidth = max(map(column_width, par))
+ maxwidth = max(column_width(x) for x in par)
else:
maxwidth = 0
realwidths[i] = max(realwidths[i], maxwidth)
@@ -746,6 +748,11 @@ class TextTranslator(nodes.NodeVisitor):
def depart_reference(self, node):
pass
+ def visit_number_reference(self, node):
+ text = nodes.Text(node.get('title', '#'))
+ self.visit_Text(text)
+ raise nodes.SkipNode
+
def visit_download_reference(self, node):
pass
def depart_download_reference(self, node):
@@ -766,6 +773,11 @@ class TextTranslator(nodes.NodeVisitor):
def depart_strong(self, node):
self.add_text('**')
+ def visit_literal_strong(self, node):
+ self.add_text('**')
+ def depart_literal_strong(self, node):
+ self.add_text('**')
+
def visit_abbreviation(self, node):
self.add_text('')
def depart_abbreviation(self, node):
diff --git a/sphinx/writers/xml.py b/sphinx/writers/xml.py
index cfae484e..179a9ab4 100644
--- a/sphinx/writers/xml.py
+++ b/sphinx/writers/xml.py
@@ -18,6 +18,8 @@ class XMLWriter(BaseXMLWriter):
def __init__(self, builder):
BaseXMLWriter.__init__(self)
self.builder = builder
+ if self.builder.translator_class:
+ self.translator_class = self.builder.translator_class
def translate(self, *args, **kwargs):
self.document.settings.newlines = \
diff --git a/tests/coverage.py b/tests/coverage.py
index 95f6f844..f9341d8b 100755
--- a/tests/coverage.py
+++ b/tests/coverage.py
@@ -52,7 +52,9 @@ coverage.py -a [-d dir] [-o dir1,dir2,...] FILE1 FILE2 ...
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."""
+COVERAGE_FILE environment variable to save it somewhere else.
+"""
+from __future__ import print_function
__version__ = "2.85.20080914" # see detailed history at the end of this file.
@@ -64,17 +66,14 @@ import re
import string
import symbol
import sys
+import atexit
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
+from six import string_types
+
# 2. IMPLEMENTATION
#
@@ -187,9 +186,9 @@ class StatementFindingAstVisitor(compiler.visitor.ASTVisitor):
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]):
+ elif lineno in self.excluded or \
+ lineno in self.suite_spots and \
+ self.suite_spots[lineno][1] in self.excluded:
return 0
# Otherwise, this is an executable line.
else:
@@ -218,8 +217,8 @@ class StatementFindingAstVisitor(compiler.visitor.ASTVisitor):
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))
+ if l in self.suite_spots:
+ self.doSuite(None, suite, exclude=l in self.excluded)
break
else:
self.doSuite(None, suite)
@@ -328,9 +327,9 @@ class coverage:
def help(self, error=None): #pragma: no cover
if error:
- print error
- print
- print __doc__
+ print(error)
+ print()
+ print(__doc__)
sys.exit(1)
def command_line(self, argv, help_fn=None):
@@ -354,9 +353,9 @@ class coverage:
long_opts = optmap.values()
options, args = getopt.getopt(argv, short_opts, long_opts)
for o, a in options:
- if optmap.has_key(o):
+ if o in optmap:
settings[optmap[o]] = 1
- elif optmap.has_key(o + ':'):
+ elif o + ':' in optmap:
settings[optmap[o + ':']] = a
elif o[2:] in long_opts:
settings[o[2:]] = 1
@@ -398,11 +397,11 @@ class coverage:
self.start()
import __main__
sys.path[0] = os.path.dirname(sys.argv[0])
- execfile(sys.argv[0], __main__.__dict__)
+ exec(compile(open(sys.argv[0]).read(), sys.argv[0], 'exec'), __main__.__dict__)
if settings.get('collect'):
self.collect()
if not args:
- args = self.cexecuted.keys()
+ args = list(self.cexecuted.keys())
ignore_errors = settings.get('ignore-errors')
show_missing = settings.get('show-missing')
@@ -493,7 +492,7 @@ class coverage:
import marshal
cexecuted = marshal.load(cache)
cache.close()
- if isinstance(cexecuted, types.DictType):
+ if isinstance(cexecuted, dict):
return cexecuted
else:
return {}
@@ -514,14 +513,14 @@ class coverage:
def merge_data(self, new_data):
for file_name, file_data in new_data.items():
- if self.cexecuted.has_key(file_name):
+ if file_name in self.cexecuted:
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):
+ if line_number not in cache_data:
cache_data[line_number] = new_data[line_number]
def abs_file(self, filename):
@@ -554,7 +553,7 @@ class coverage:
# normalized case). See [GDR 2001-12-04b, 3.3].
def canonical_filename(self, filename):
- if not self.canonical_filename_cache.has_key(filename):
+ if filename not in self.canonical_filename_cache:
f = filename
if os.path.isabs(f) and not os.path.exists(f):
if not self.get_zip_data(f):
@@ -578,7 +577,7 @@ class coverage:
# 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):
+ if f not in self.cexecuted:
self.cexecuted[f] = {}
self.cexecuted[f][lineno] = 1
self.c = {}
@@ -601,7 +600,7 @@ class coverage:
# statements that cross lines.
def analyze_morf(self, morf):
- if self.analysis_cache.has_key(morf):
+ if morf in self.analysis_cache:
return self.analysis_cache[morf]
filename = self.morf_filename(morf)
ext = os.path.splitext(filename)[1]
@@ -621,7 +620,7 @@ class coverage:
lines, excluded_lines, line_map = self.find_executable_statements(
source, exclude=self.exclude_re
)
- except SyntaxError, synerr:
+ except SyntaxError as synerr:
raise CoverageException(
"Couldn't parse '%s' as Python source: '%s' at line %d" %
(filename, synerr.msg, synerr.lineno)
@@ -744,10 +743,8 @@ class coverage:
visitor = StatementFindingAstVisitor(statements, excluded, suite_spots)
compiler.walk(ast, visitor, walker=visitor)
- lines = statements.keys()
- lines.sort()
- excluded_lines = excluded.keys()
- excluded_lines.sort()
+ lines = sorted(statements.keys())
+ excluded_lines = sorted(excluded.keys())
return lines, excluded_lines, suite_spots
# format_lines(statements, lines). Format a list of line numbers
@@ -792,13 +789,13 @@ class coverage:
def analysis2(self, morf):
filename, statements, excluded, line_map = self.analyze_morf(morf)
self.canonicalize_filenames()
- if not self.cexecuted.has_key(filename):
+ if filename not in self.cexecuted:
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):
+ if l in self.cexecuted[filename]:
break
else:
missing.append(line)
@@ -837,12 +834,12 @@ class coverage:
def report(self, morfs, show_missing=1, ignore_errors=0, file=None,
omit_prefixes=[]):
- if not isinstance(morfs, types.ListType):
+ if not isinstance(morfs, list):
morfs = [morfs]
# On windows, the shell doesn't expand wildcards. Do it here.
globbed = []
for morf in morfs:
- if isinstance(morf, strclass):
+ if isinstance(morf, string_types):
globbed.extend(glob.glob(morf))
else:
globbed.append(morf)
@@ -851,7 +848,7 @@ class coverage:
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)))
+ 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"
@@ -861,8 +858,8 @@ class coverage:
fmt_coverage = fmt_coverage + " %s"
if not file:
file = sys.stdout
- print >>file, header
- print >>file, "-" * len(header)
+ print(header, file=file)
+ print("-" * len(header), file=file)
total_statements = 0
total_executed = 0
for morf in morfs:
@@ -878,7 +875,7 @@ class coverage:
args = (name, n, m, pc)
if show_missing:
args = args + (readable,)
- print >>file, fmt_coverage % args
+ print(fmt_coverage % args, file=file)
total_statements = total_statements + n
total_executed = total_executed + m
except KeyboardInterrupt: #pragma: no cover
@@ -886,9 +883,9 @@ class coverage:
except:
if not ignore_errors:
typ, msg = sys.exc_info()[:2]
- print >>file, fmt_err % (name, typ, msg)
+ print(fmt_err % (name, typ, msg), file=file)
if len(morfs) > 1:
- print >>file, "-" * len(header)
+ print("-" * len(header), file=file)
if total_statements > 0:
pc = 100.0 * total_executed / total_statements
else:
@@ -896,7 +893,7 @@ class coverage:
args = ("TOTAL", total_statements, total_executed, pc)
if show_missing:
args = args + ("",)
- print >>file, fmt_coverage % args
+ print(fmt_coverage % args, file=file)
# annotate(morfs, ignore_errors).
@@ -1006,14 +1003,7 @@ def 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
+atexit.register(the_coverage.save)
def main():
the_coverage.command_line(sys.argv[1:])
diff --git a/tests/etree13/ElementPath.py b/tests/etree13/ElementPath.py
index b097d816..d26a0d7a 100644
--- a/tests/etree13/ElementPath.py
+++ b/tests/etree13/ElementPath.py
@@ -177,7 +177,7 @@ class _SelectorContext:
def find(elem, path):
try:
- return findall(elem, path).next()
+ return next(findall(elem, path))
except StopIteration:
return None
@@ -194,17 +194,17 @@ def findall(elem, path):
if path[:1] == "/":
raise SyntaxError("cannot use absolute path on element")
stream = iter(xpath_tokenizer(path))
- next = stream.next; token = next()
+ next_ = lambda: next(stream); token = next_()
selector = []
while 1:
try:
- selector.append(ops[token[0]](next, token))
+ selector.append(ops[token[0]](next_, token))
except StopIteration:
raise SyntaxError("invalid path")
try:
- token = next()
+ token = next_()
if token[0] == "/":
- token = next()
+ token = next_()
except StopIteration:
break
_cache[path] = selector
@@ -220,7 +220,7 @@ def findall(elem, path):
def findtext(elem, path, default=None):
try:
- elem = findall(elem, path).next()
+ elem = next(findall(elem, path))
return elem.text
except StopIteration:
return default
diff --git a/tests/etree13/ElementTree.py b/tests/etree13/ElementTree.py
index f459c7f8..0dd12ddb 100644
--- a/tests/etree13/ElementTree.py
+++ b/tests/etree13/ElementTree.py
@@ -79,6 +79,10 @@
# --------------------------------------------------------------------
from __future__ import generators
+from __future__ import absolute_import
+
+from six import string_types
+
__all__ = [
# public symbols
@@ -144,7 +148,7 @@ class _SimpleElementPath(object):
return result
try:
- import ElementPath
+ from . import ElementPath
except ImportError:
# FIXME: issue warning in this case?
ElementPath = _SimpleElementPath()
@@ -242,7 +246,7 @@ class Element(object):
def __len__(self):
return len(self._children)
- def __nonzero__(self):
+ def __bool__(self):
import warnings
warnings.warn(
"The behavior of this method will change in future versions. "
@@ -250,6 +254,7 @@ class Element(object):
FutureWarning
)
return len(self._children) != 0 # emulate old behaviour
+ __nonzero__ = __bool__ # for python2 compatibility
##
# Returns the given subelement.
@@ -827,7 +832,7 @@ def _namespaces(elem, encoding, default_namespace=None):
tag = elem.tag
if isinstance(tag, QName) and tag.text not in qnames:
add_qname(tag.text)
- elif isinstance(tag, basestring):
+ elif isinstance(tag, string_types):
if tag not in qnames:
add_qname(tag)
elif tag is not None and tag is not Comment and tag is not PI:
@@ -862,7 +867,7 @@ def _serialize_xml(write, elem, encoding, qnames, namespaces):
write("<" + tag)
items = elem.items()
if items or namespaces:
- items.sort() # lexical order
+ items = sorted(items) # lexical order
for k, v in items:
if isinstance(k, QName):
k = k.text
@@ -873,7 +878,7 @@ def _serialize_xml(write, elem, encoding, qnames, namespaces):
write(" %s=\"%s\"" % (qnames[k], v))
if namespaces:
items = namespaces.items()
- items.sort(key=lambda x: x[1]) # sort on prefix
+ items = sorted(items, key=lambda x: x[1]) # sort on prefix
for v, k in items:
if k:
k = ":" + k
@@ -919,7 +924,7 @@ def _serialize_html(write, elem, encoding, qnames, namespaces):
write("<" + tag)
items = elem.items()
if items or namespaces:
- items.sort() # lexical order
+ items = sorted(items) # lexical order
for k, v in items:
if isinstance(k, QName):
k = k.text
@@ -931,7 +936,7 @@ def _serialize_html(write, elem, encoding, qnames, namespaces):
write(" %s=\"%s\"" % (qnames[k], v))
if namespaces:
items = namespaces.items()
- items.sort(key=lambda x: x[1]) # sort on prefix
+ items = sorted(items, key=lambda x: x[1]) # sort on prefix
for v, k in items:
if k:
k = ":" + k
@@ -1183,7 +1188,7 @@ class _IterParseIterator(object):
append((event, None))
parser.EndNamespaceDeclHandler = handler
- def next(self):
+ def __next__(self):
while 1:
try:
item = self._events[self._index]
@@ -1204,6 +1209,8 @@ class _IterParseIterator(object):
self._index = self._index + 1
return item
+ next = __next__ # Python 2 compatibility
+
def __iter__(self):
return self
@@ -1524,7 +1531,7 @@ class XMLParser(object):
def feed(self, data):
try:
self._parser.Parse(data, 0)
- except self._error, v:
+ except self._error as v:
self._raiseerror(v)
##
@@ -1536,7 +1543,7 @@ class XMLParser(object):
def close(self):
try:
self._parser.Parse("", 1) # end of data
- except self._error, v:
+ except self._error as v:
self._raiseerror(v)
tree = self.target.close()
del self.target, self._parser # get rid of circular references
diff --git a/tests/etree13/HTMLTreeBuilder.py b/tests/etree13/HTMLTreeBuilder.py
index 4c5a24f6..cf332c75 100644
--- a/tests/etree13/HTMLTreeBuilder.py
+++ b/tests/etree13/HTMLTreeBuilder.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
#
# ElementTree
# $Id$
@@ -53,7 +54,9 @@ import htmlentitydefs
import re, string, sys
import mimetools, StringIO
-import ElementTree
+from six import text_type
+
+from . import ElementTree
AUTOCLOSE = "p", "li", "tr", "th", "td", "head", "body"
IGNOREEND = "img", "hr", "meta", "link", "br"
@@ -198,7 +201,7 @@ class HTMLTreeBuilder(HTMLParser):
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")
+ data = text_type(data, self.encoding, "ignore")
self.__builder.data(data)
##
diff --git a/tests/path.py b/tests/path.py
index fa90a6f5..573d3d3c 100755
--- a/tests/path.py
+++ b/tests/path.py
@@ -12,20 +12,22 @@ import sys
import shutil
from codecs import open
+from six import PY2, text_type
+
FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding()
-class path(unicode):
+class path(text_type):
"""
Represents a path which behaves like a string.
"""
- if sys.version_info < (3, 0):
+ if PY2:
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)
+ return text_type.__new__(cls, s)
+ return text_type.__new__(cls, s)
@property
def parent(self):
@@ -34,6 +36,9 @@ class path(unicode):
"""
return self.__class__(os.path.dirname(self))
+ def basename(self):
+ return os.path.basename(self)
+
def abspath(self):
"""
Returns the absolute path.
@@ -118,6 +123,9 @@ class path(unicode):
"""
os.unlink(self)
+ def utime(self, arg):
+ os.utime(self, arg)
+
def write_text(self, text, **kwargs):
"""
Writes the given `text` to the file.
@@ -178,7 +186,7 @@ class path(unicode):
"""
return os.path.lexists(self)
- def makedirs(self, mode=0777):
+ def makedirs(self, mode=0o777):
"""
Recursively create directories.
"""
@@ -190,7 +198,10 @@ class path(unicode):
"""
return self.__class__(os.path.join(self, *map(self.__class__, args)))
+ def listdir(self):
+ return os.listdir(self)
+
__div__ = __truediv__ = joinpath
def __repr__(self):
- return '%s(%s)' % (self.__class__.__name__, unicode.__repr__(self))
+ return '%s(%s)' % (self.__class__.__name__, text_type.__repr__(self))
diff --git a/tests/root/autodoc.txt b/tests/root/autodoc.txt
index d4b3404c..aa0dffba 100644
--- a/tests/root/autodoc.txt
+++ b/tests/root/autodoc.txt
@@ -45,3 +45,5 @@ Just testing a few autodoc possibilities...
:members: ca1, ia1
Specific members (2 total)
+
+.. automodule:: autodoc_missing_imports
diff --git a/tests/root/autodoc_missing_imports.py b/tests/root/autodoc_missing_imports.py
new file mode 100644
index 00000000..7a717345
--- /dev/null
+++ b/tests/root/autodoc_missing_imports.py
@@ -0,0 +1,9 @@
+
+import missing_module
+from missing_module import missing_name
+import missing_package1.missing_module1
+from missing_package2 import missing_module2
+from missing_package3.missing_module3 import missing_name
+
+class TestAutodoc(object):
+ """TestAutodoc docstring."""
diff --git a/tests/root/conf.py b/tests/root/conf.py
index 8025ba33..5186f371 100644
--- a/tests/root/conf.py
+++ b/tests/root/conf.py
@@ -3,12 +3,9 @@
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']
+ 'sphinx.ext.coverage', 'sphinx.ext.extlinks', 'ext']
jsmath_path = 'dummy.js'
@@ -18,16 +15,16 @@ master_doc = 'contents'
source_suffix = '.txt'
project = 'Sphinx <Tests>'
-copyright = '2010, Georg Brandl & Team'
+copyright = '2010-2014, 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
+numfig = True
rst_epilog = '.. |subst| replace:: global substitution'
@@ -35,7 +32,8 @@ html_theme = 'testtheme'
html_theme_path = ['.']
html_theme_options = {'testopt': 'testoverride'}
html_sidebars = {'**': 'customsb.html',
- 'contents': ['contentssb.html', 'localtoc.html'] }
+ 'contents': ['contentssb.html', 'localtoc.html',
+ 'globaltoc.html']}
html_style = 'default.css'
html_static_path = ['_static', 'templated.css_t']
html_extra_path = ['robots.txt']
@@ -45,15 +43,15 @@ 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'),
+ ('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'),
+ ('contents', 'SphinxTests', 'Sphinx Tests',
+ 'Georg Brandl \\and someone else', 'Sphinx Testing', 'Miscellaneous'),
]
man_pages = [
@@ -66,43 +64,26 @@ 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)}
+autodoc_mock_imports = [
+ 'missing_module',
+ 'missing_package1.missing_module1',
+ 'missing_package2.missing_module2',
+ 'missing_package3.missing_module3',
+]
+
# 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)
@@ -110,15 +91,19 @@ def userdesc_parse(env, sig, signode):
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)
diff --git a/tests/root/contents.txt b/tests/root/contents.txt
index 7486750d..d786b914 100644
--- a/tests/root/contents.txt
+++ b/tests/root/contents.txt
@@ -21,15 +21,14 @@ Contents:
bom
math
autodoc
- autosummary
metadata
extensions
- doctest
extensions
- versioning/index
footnote
lists
+ http://sphinx-doc.org/
+ Latest reference <http://sphinx-doc.org/latest/>
Python <http://python.org/>
Indices and tables
@@ -43,3 +42,14 @@ References
==========
.. [Ref1] Reference target.
+.. [Ref_1] Reference target 2.
+
+Test for issue #1157
+====================
+
+This used to crash:
+
+.. toctree::
+
+.. toctree::
+ :hidden:
diff --git a/tests/root/img.png b/tests/root/img.png
index 72c12d13..4c8f8992 100644
--- a/tests/root/img.png
+++ b/tests/root/img.png
Binary files differ
diff --git a/tests/root/includes.txt b/tests/root/includes.txt
index 904f0677..907b81e9 100644
--- a/tests/root/includes.txt
+++ b/tests/root/includes.txt
@@ -40,6 +40,7 @@ Literalinclude options
.. cssclass:: inc-lines
.. literalinclude:: literal.inc
:lines: 6-7,9
+ :lineno-start: 6
.. cssclass:: inc-startend
.. literalinclude:: literal.inc
@@ -57,6 +58,9 @@ Literalinclude options
.. literalinclude:: literal.inc
:end-before: class Foo
+.. literalinclude:: literal.inc
+ :diff: literal_orig.inc
+
.. cssclass:: inc-tab3
.. literalinclude:: tabs.inc
:tab-width: 3
@@ -67,6 +71,22 @@ Literalinclude options
:tab-width: 8
:language: python
+.. cssclass:: inc-pyobj-lines-match
+.. literalinclude:: literal.inc
+ :pyobject: Foo
+ :lineno-match:
+
+.. cssclass:: inc-lines-match
+.. literalinclude:: literal.inc
+ :lines: 6-7,8
+ :lineno-match:
+
+.. cssclass:: inc-startend-match
+.. literalinclude:: literal.inc
+ :start-after: coding: utf-8
+ :end-before: class Foo
+ :lineno-match:
+
Test if dedenting before parsing works.
.. highlight:: python
diff --git a/tests/root/literal_orig.inc b/tests/root/literal_orig.inc
new file mode 100644
index 00000000..14fd214c
--- /dev/null
+++ b/tests/root/literal_orig.inc
@@ -0,0 +1,13 @@
+# Literally included file using Python highlighting
+# -*- coding: utf-8 -*-
+
+foo = "Including Unicode characters: üöä" # This will be changed
+
+class FooOrig:
+ pass
+
+class BarOrig:
+ def baz():
+ pass
+
+def bar(): pass
diff --git a/tests/root/markup.txt b/tests/root/markup.txt
index 34e8fdb8..1ad7a13b 100644
--- a/tests/root/markup.txt
+++ b/tests/root/markup.txt
@@ -132,7 +132,9 @@ Adding \n to test unescaping.
*Linking inline markup*
* :pep:`8`
+* :pep:`Python Enhancement Proposal #8 <8>`
* :rfc:`1`
+* :rfc:`Request for Comments #1 <1>`
* :envvar:`HOME`
* :keyword:`with`
* :token:`try statement <try_stmt>`
@@ -140,6 +142,10 @@ Adding \n to test unescaping.
* :ref:`here <some-label>`
* :ref:`my-figure`
* :ref:`my-table`
+* :ref:`my-code-block`
+* :numref:`my-figure`
+* :numref:`my-table`
+* :numref:`my-code-block`
* :doc:`subdir/includes`
* ``:download:`` is tested in includes.txt
* :option:`Python -c option <python -c>`
@@ -226,8 +232,11 @@ Version markup
Code blocks
-----------
+.. _my-code-block:
+
.. code-block:: ruby
:linenos:
+ :caption: my ruby code
def ruby?
false
@@ -240,6 +249,7 @@ Misc stuff
Stuff [#]_
Reference lookup: [Ref1]_ (defined in another file).
+Reference lookup underscore: [Ref_1]_
.. seealso:: something, something else, something more
@@ -353,6 +363,25 @@ Only directive
Always present, because set through conf.py/command line.
+Any role
+--------
+
+.. default-role:: any
+
+Test referencing to `headings <with>` and `objects <func_without_body>`.
+Also `modules <mod>` and `classes <Time>`.
+
+More domains:
+
+* `JS <bar.baz>`
+* `C <SphinxType>`
+* `myobj` (user markup)
+* `n::Array`
+* `perl -c`
+
+.. default-role::
+
+
.. rubric:: Footnotes
.. [#] Like footnotes.
diff --git a/tests/root/metadata.txt b/tests/root/metadata.txt
index 9b3044ba..821816a9 100644
--- a/tests/root/metadata.txt
+++ b/tests/root/metadata.txt
@@ -32,6 +32,10 @@
language, containing examples of all basic reStructuredText
constructs and many advanced constructs.
+:nocomments:
+:orphan:
+:tocdepth: 1
+
.. meta::
:keywords: reStructuredText, demonstration, demo, parser
:description lang=en: A demonstration of the reStructuredText
diff --git a/tests/root/objects.txt b/tests/root/objects.txt
index 57e82212..ebed06ea 100644
--- a/tests/root/objects.txt
+++ b/tests/root/objects.txt
@@ -101,6 +101,7 @@ Referring to :func:`nothing <>`.
:type hour: DuplicateType
:param hour: Duplicate param. Should not lead to crashes.
:type hour: DuplicateType
+ :param .Cls extcls: A class from another module.
C items
@@ -117,14 +118,6 @@ C items
.. c:var:: sphinx_global
-Old C items (from oldcmarkup ext)
----------------------------------
-
-.. cfunction:: Sphinx_Func()
-
-Refer to :cfunc:`Sphinx_Func`.
-
-
Javascript items
================
@@ -177,6 +170,10 @@ Others
.. cmdoption:: -c
+.. option:: +p
+
+Link to :option:`perl +p`.
+
User markup
===========
diff --git a/tests/root/special/code.py b/tests/root/special/code.py
index 70c48d2e..b7934b23 100644
--- a/tests/root/special/code.py
+++ b/tests/root/special/code.py
@@ -1,2 +1,2 @@
-print "line 1"
-print "line 2"
+print("line 1")
+print("line 2")
diff --git a/tests/root/subdir/img.png b/tests/root/subdir/img.png
index 72c12d13..4c8f8992 100644
--- a/tests/root/subdir/img.png
+++ b/tests/root/subdir/img.png
Binary files differ
diff --git a/tests/root/subdir/simg.png b/tests/root/subdir/simg.png
index 72c12d13..4c8f8992 100644
--- a/tests/root/subdir/simg.png
+++ b/tests/root/subdir/simg.png
Binary files differ
diff --git a/tests/root/undecodable.txt b/tests/root/undecodable.txt
new file mode 100644
index 00000000..a4cf5c37
--- /dev/null
+++ b/tests/root/undecodable.txt
@@ -0,0 +1,3 @@
+:orphan:
+
+here: »
diff --git a/tests/roots/test-api-set-translator/conf.py b/tests/roots/test-api-set-translator/conf.py
new file mode 100644
index 00000000..3c160664
--- /dev/null
+++ b/tests/roots/test-api-set-translator/conf.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+## set this by test
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+from sphinx.writers.html import HTMLTranslator
+from sphinx.writers.latex import LaTeXTranslator
+from sphinx.writers.manpage import ManualPageTranslator
+from sphinx.writers.texinfo import TexinfoTranslator
+from sphinx.writers.text import TextTranslator
+from sphinx.writers.websupport import WebSupportTranslator
+from docutils.writers.docutils_xml import XMLTranslator
+
+
+project = 'test'
+master_doc = 'index'
+
+
+class ConfHTMLTranslator(HTMLTranslator):
+ pass
+
+
+class ConfDirHTMLTranslator(HTMLTranslator):
+ pass
+
+
+class ConfSingleHTMLTranslator(HTMLTranslator):
+ pass
+
+
+class ConfPickleTranslator(HTMLTranslator):
+ pass
+
+
+class ConfJsonTranslator(HTMLTranslator):
+ pass
+
+
+class ConfLaTeXTranslator(LaTeXTranslator):
+ pass
+
+
+class ConfManualPageTranslator(ManualPageTranslator):
+ pass
+
+
+class ConfTexinfoTranslator(TexinfoTranslator):
+ pass
+
+
+class ConfTextTranslator(TextTranslator):
+ pass
+
+
+class ConfWebSupportTranslator(WebSupportTranslator):
+ pass
+
+
+class ConfXMLTranslator(XMLTranslator):
+ pass
+
+
+class ConfPseudoXMLTranslator(XMLTranslator):
+ pass
+
+
+def setup(app):
+ app.set_translator('html', ConfHTMLTranslator)
+ app.set_translator('dirhtml', ConfDirHTMLTranslator)
+ app.set_translator('singlehtml', ConfSingleHTMLTranslator)
+ app.set_translator('pickle', ConfPickleTranslator)
+ app.set_translator('json', ConfJsonTranslator)
+ app.set_translator('latex', ConfLaTeXTranslator)
+ app.set_translator('man', ConfManualPageTranslator)
+ app.set_translator('texinfo', ConfTexinfoTranslator)
+ app.set_translator('text', ConfTextTranslator)
+ app.set_translator('websupport', ConfWebSupportTranslator)
+ app.set_translator('xml', ConfXMLTranslator)
+ app.set_translator('pseudoxml', ConfPseudoXMLTranslator)
diff --git a/tests/roots/test-api-set-translator/index.rst b/tests/roots/test-api-set-translator/index.rst
new file mode 100644
index 00000000..e5a29cf2
--- /dev/null
+++ b/tests/roots/test-api-set-translator/index.rst
@@ -0,0 +1,3 @@
+=======================
+Test API set_translator
+======================= \ No newline at end of file
diff --git a/tests/roots/test-api-set-translator/nonext/conf.py b/tests/roots/test-api-set-translator/nonext/conf.py
new file mode 100644
index 00000000..5a92f736
--- /dev/null
+++ b/tests/roots/test-api-set-translator/nonext/conf.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+
+sys.path.insert(0, os.path.dirname(os.path.abspath('.')))
+
+project = 'test'
+master_doc = 'index'
diff --git a/tests/roots/test-api-set-translator/translator.py b/tests/roots/test-api-set-translator/translator.py
new file mode 100644
index 00000000..015b4aa2
--- /dev/null
+++ b/tests/roots/test-api-set-translator/translator.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+from sphinx.writers.html import HTMLTranslator
+
+class ExtHTMLTranslator(HTMLTranslator):
+ pass
diff --git a/tests/roots/test-autosummary/conf.py b/tests/roots/test-autosummary/conf.py
index 542696e9..d9a44748 100644
--- a/tests/roots/test-autosummary/conf.py
+++ b/tests/roots/test-autosummary/conf.py
@@ -1,3 +1,7 @@
+import sys, os
+
+sys.path.insert(0, os.path.abspath('.'))
+
extensions = ['sphinx.ext.autosummary']
# The suffix of source filenames.
diff --git a/tests/roots/test-autosummary/contents.rst b/tests/roots/test-autosummary/contents.rst
index 3f16af99..cd4b7c5e 100644
--- a/tests/roots/test-autosummary/contents.rst
+++ b/tests/roots/test-autosummary/contents.rst
@@ -2,5 +2,6 @@
.. autosummary::
:nosignatures:
:toctree:
-
+
dummy_module
+ sphinx
diff --git a/tests/root/autosummary.txt b/tests/roots/test-autosummary/sphinx.rst
index fc1a35a0..fc1a35a0 100644
--- a/tests/root/autosummary.txt
+++ b/tests/roots/test-autosummary/sphinx.rst
diff --git a/tests/roots/test-build-text/conf.py b/tests/roots/test-build-text/conf.py
new file mode 100644
index 00000000..1ba342a6
--- /dev/null
+++ b/tests/roots/test-build-text/conf.py
@@ -0,0 +1,2 @@
+master_doc = 'contents'
+source_suffix = '.txt'
diff --git a/tests/roots/test-build-text/contents.txt b/tests/roots/test-build-text/contents.txt
new file mode 100644
index 00000000..420d1428
--- /dev/null
+++ b/tests/roots/test-build-text/contents.txt
@@ -0,0 +1,8 @@
+.. toctree::
+
+ maxwidth
+ lineblock
+ nonascii_title
+ nonascii_table
+ nonascii_maxwidth
+ table
diff --git a/tests/roots/test-build-text/lineblock.txt b/tests/roots/test-build-text/lineblock.txt
new file mode 100644
index 00000000..b9cd0ed7
--- /dev/null
+++ b/tests/roots/test-build-text/lineblock.txt
@@ -0,0 +1,6 @@
+* one
+
+ | line-block 1
+ | line-block 2
+
+followed paragraph.
diff --git a/tests/roots/test-build-text/maxwidth.txt b/tests/roots/test-build-text/maxwidth.txt
new file mode 100644
index 00000000..c36f8a02
--- /dev/null
+++ b/tests/roots/test-build-text/maxwidth.txt
@@ -0,0 +1,6 @@
+.. seealso:: ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham
+
+* ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham
+* ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham ham
+
+spam egg
diff --git a/tests/roots/test-build-text/nonascii_maxwidth.txt b/tests/roots/test-build-text/nonascii_maxwidth.txt
new file mode 100644
index 00000000..e9f0fd9b
--- /dev/null
+++ b/tests/roots/test-build-text/nonascii_maxwidth.txt
@@ -0,0 +1,5 @@
+abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc
+
+日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語 日本語
+
+abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語 abc 日本語
diff --git a/tests/roots/test-build-text/nonascii_table.txt b/tests/roots/test-build-text/nonascii_table.txt
new file mode 100644
index 00000000..709e0f2f
--- /dev/null
+++ b/tests/roots/test-build-text/nonascii_table.txt
@@ -0,0 +1,7 @@
+.. list-table::
+
+ - - spam
+ - egg
+
+ - - 日本語
+ - 日本語
diff --git a/tests/roots/test-build-text/nonascii_title.txt b/tests/roots/test-build-text/nonascii_title.txt
new file mode 100644
index 00000000..6d3b1f61
--- /dev/null
+++ b/tests/roots/test-build-text/nonascii_title.txt
@@ -0,0 +1,2 @@
+日本語
+======
diff --git a/tests/roots/test-build-text/table.txt b/tests/roots/test-build-text/table.txt
new file mode 100644
index 00000000..84328940
--- /dev/null
+++ b/tests/roots/test-build-text/table.txt
@@ -0,0 +1,7 @@
+ +-----+-----+
+ | XXX | XXX |
+ +-----+-----+
+ | | XXX |
+ +-----+-----+
+ | XXX | |
+ +-----+-----+
diff --git a/custom_fixers/__init__.py b/tests/roots/test-circular/conf.py
index e69de29b..e69de29b 100644
--- a/custom_fixers/__init__.py
+++ b/tests/roots/test-circular/conf.py
diff --git a/tests/roots/test-circular/contents.rst b/tests/roots/test-circular/contents.rst
new file mode 100644
index 00000000..294e674d
--- /dev/null
+++ b/tests/roots/test-circular/contents.rst
@@ -0,0 +1,4 @@
+.. toctree::
+
+ sub
+
diff --git a/tests/roots/test-circular/sub.rst b/tests/roots/test-circular/sub.rst
new file mode 100644
index 00000000..070c3974
--- /dev/null
+++ b/tests/roots/test-circular/sub.rst
@@ -0,0 +1,3 @@
+.. toctree::
+
+ contents
diff --git a/tests/roots/test-directive-code/caption.rst b/tests/roots/test-directive-code/caption.rst
new file mode 100644
index 00000000..5a2fe4a1
--- /dev/null
+++ b/tests/roots/test-directive-code/caption.rst
@@ -0,0 +1,21 @@
+Dedent
+======
+
+Code blocks
+-----------
+
+.. code-block:: ruby
+ :caption: caption *test* rb
+
+ def ruby?
+ false
+ end
+
+
+Literal Include
+---------------
+
+.. literalinclude:: literal.inc
+ :language: python
+ :caption: caption **test** py
+ :lines: 10-11
diff --git a/tests/roots/test-directive-code/conf.py b/tests/roots/test-directive-code/conf.py
new file mode 100644
index 00000000..f81c30bc
--- /dev/null
+++ b/tests/roots/test-directive-code/conf.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'index'
diff --git a/tests/roots/test-directive-code/dedent.rst b/tests/roots/test-directive-code/dedent.rst
new file mode 100644
index 00000000..9ec1c0ee
--- /dev/null
+++ b/tests/roots/test-directive-code/dedent.rst
@@ -0,0 +1,35 @@
+Dedent
+======
+
+Literal Include
+---------------
+
+.. literalinclude:: literal.inc
+ :language: python
+ :lines: 10-11
+ :dedent: 0
+
+.. literalinclude:: literal.inc
+ :language: python
+ :lines: 10-11
+ :dedent: 1
+
+.. literalinclude:: literal.inc
+ :language: python
+ :lines: 10-11
+ :dedent: 2
+
+.. literalinclude:: literal.inc
+ :language: python
+ :lines: 10-11
+ :dedent: 3
+
+.. literalinclude:: literal.inc
+ :language: python
+ :lines: 10-11
+ :dedent: 4
+
+.. literalinclude:: literal.inc
+ :language: python
+ :lines: 10-11
+ :dedent: 1000
diff --git a/tests/roots/test-directive-code/dedent_code.rst b/tests/roots/test-directive-code/dedent_code.rst
new file mode 100644
index 00000000..3e8dacd6
--- /dev/null
+++ b/tests/roots/test-directive-code/dedent_code.rst
@@ -0,0 +1,53 @@
+Dedent
+======
+
+Code blocks
+-----------
+
+.. code-block:: ruby
+ :linenos:
+ :dedent: 0
+
+ def ruby?
+ false
+ end
+
+.. code-block:: ruby
+ :linenos:
+ :dedent: 1
+
+ def ruby?
+ false
+ end
+
+.. code-block:: ruby
+ :linenos:
+ :dedent: 2
+
+ def ruby?
+ false
+ end
+
+.. code-block:: ruby
+ :linenos:
+ :dedent: 3
+
+ def ruby?
+ false
+ end
+
+.. code-block:: ruby
+ :linenos:
+ :dedent: 4
+
+ def ruby?
+ false
+ end
+
+.. code-block:: ruby
+ :linenos:
+ :dedent: 1000
+
+ def ruby?
+ false
+ end
diff --git a/tests/roots/test-directive-code/index.rst b/tests/roots/test-directive-code/index.rst
new file mode 100644
index 00000000..dab6b708
--- /dev/null
+++ b/tests/roots/test-directive-code/index.rst
@@ -0,0 +1,25 @@
+test-directive-code
+===================
+
+.. toctree::
+ :glob:
+
+ *
+
+
+Code blocks
+-----------
+
+.. code-block:: ruby
+ :linenos:
+
+ def ruby?
+ false
+ end
+
+
+Literal Includes
+----------------
+
+.. literalinclude:: literal.inc
+ :language: python
diff --git a/tests/roots/test-directive-code/lineno_match.rst b/tests/roots/test-directive-code/lineno_match.rst
new file mode 100644
index 00000000..4e3b3835
--- /dev/null
+++ b/tests/roots/test-directive-code/lineno_match.rst
@@ -0,0 +1,17 @@
+Literal Includes with Line Numbers Matching
+===========================================
+
+.. literalinclude:: literal.inc
+ :language: python
+ :pyobject: Bar
+ :lineno-match:
+
+.. literalinclude:: literal.inc
+ :language: python
+ :lines: 5-6,7,8-9
+ :lineno-match:
+
+.. literalinclude:: literal.inc
+ :language: python
+ :start-after: pass
+ :lineno-match:
diff --git a/tests/roots/test-directive-code/lineno_start.rst b/tests/roots/test-directive-code/lineno_start.rst
new file mode 100644
index 00000000..1beaabbf
--- /dev/null
+++ b/tests/roots/test-directive-code/lineno_start.rst
@@ -0,0 +1,6 @@
+Literal Includes with Line Numbers Starting from 200
+====================================================
+
+.. literalinclude:: literal.inc
+ :language: python
+ :lineno-start: 200
diff --git a/tests/roots/test-directive-code/linenos.rst b/tests/roots/test-directive-code/linenos.rst
new file mode 100644
index 00000000..2f64498d
--- /dev/null
+++ b/tests/roots/test-directive-code/linenos.rst
@@ -0,0 +1,6 @@
+Literal Includes with Line Numbers
+==================================
+
+.. literalinclude:: literal.inc
+ :language: python
+ :linenos:
diff --git a/tests/roots/test-directive-code/literal.inc b/tests/roots/test-directive-code/literal.inc
new file mode 100644
index 00000000..694f15ed
--- /dev/null
+++ b/tests/roots/test-directive-code/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/roots/test-directive-only/conf.py b/tests/roots/test-directive-only/conf.py
new file mode 100644
index 00000000..eb3a3d0d
--- /dev/null
+++ b/tests/roots/test-directive-only/conf.py
@@ -0,0 +1,2 @@
+
+project = 'test-directive-only'
diff --git a/tests/roots/test-only-directive/contents.rst b/tests/roots/test-directive-only/contents.rst
index 9a93be9e..80ec0031 100644
--- a/tests/roots/test-only-directive/contents.rst
+++ b/tests/roots/test-directive-only/contents.rst
@@ -1,4 +1,4 @@
-test-only-directive
+test-directive-only
===================
.. toctree::
diff --git a/tests/roots/test-only-directive/only.rst b/tests/roots/test-directive-only/only.rst
index 4a3eb48a..4a3eb48a 100644
--- a/tests/roots/test-only-directive/only.rst
+++ b/tests/roots/test-directive-only/only.rst
diff --git a/tests/roots/test-doctest/conf.py b/tests/roots/test-doctest/conf.py
new file mode 100644
index 00000000..f6a12edb
--- /dev/null
+++ b/tests/roots/test-doctest/conf.py
@@ -0,0 +1,5 @@
+extensions = ['sphinx.ext.doctest']
+
+project = 'test project for doctest'
+master_doc = 'doctest.txt'
+source_suffix = '.txt'
diff --git a/tests/root/doctest.txt b/tests/roots/test-doctest/doctest.txt
index d029cd88..ce4d88bd 100644
--- a/tests/root/doctest.txt
+++ b/tests/roots/test-doctest/doctest.txt
@@ -125,5 +125,5 @@ Special directives
.. testcleanup:: *
- import test_doctest
- test_doctest.cleanup_call()
+ import test_ext_doctest
+ test_ext_doctest.cleanup_call()
diff --git a/tests/roots/test-docutilsconf/contents.txt b/tests/roots/test-docutilsconf/contents.txt
index 3d0003b8..b20204e6 100644
--- a/tests/roots/test-docutilsconf/contents.txt
+++ b/tests/roots/test-docutilsconf/contents.txt
@@ -1,15 +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
-
+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-ext-viewcode/conf.py b/tests/roots/test-ext-viewcode/conf.py
new file mode 100644
index 00000000..a99a72bb
--- /dev/null
+++ b/tests/roots/test-ext-viewcode/conf.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+
+import sys
+import os
+
+sys.path.insert(0, os.path.abspath('.'))
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
+master_doc = 'index'
+
+
+if 'test_linkcode' in tags:
+ extensions.remove('sphinx.ext.viewcode')
+ extensions.append('sphinx.ext.linkcode')
+
+ 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()
diff --git a/tests/roots/test-ext-viewcode/index.rst b/tests/roots/test-ext-viewcode/index.rst
new file mode 100644
index 00000000..b5776cfa
--- /dev/null
+++ b/tests/roots/test-ext-viewcode/index.rst
@@ -0,0 +1,34 @@
+viewcode
+========
+
+.. py:module:: spam
+
+.. autofunction:: func1
+
+.. autofunction:: func2
+
+.. autofunction:: spam.mod1.func1
+
+.. autofunction:: spam.mod2.func2
+
+.. autofunction:: Class1
+
+.. autofunction:: Class2
+
+.. autofunction:: spam.mod1.Class1
+
+.. autofunction:: spam.mod2.Class2
+
+
+.. literalinclude:: spam/__init__.py
+ :language: python
+ :pyobject: func1
+
+.. literalinclude:: spam/mod1.py
+ :language: python
+ :pyobject: func1
+
+
+.. toctree::
+
+ objects
diff --git a/tests/roots/test-ext-viewcode/objects.rst b/tests/roots/test-ext-viewcode/objects.rst
new file mode 100644
index 00000000..8d304bec
--- /dev/null
+++ b/tests/roots/test-ext-viewcode/objects.rst
@@ -0,0 +1,169 @@
+Testing object descriptions
+===========================
+
+.. function:: func_without_module(a, b, *c[, d])
+
+ Does something.
+
+.. function:: func_without_body()
+
+.. 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
+ :param .Cls extcls: A class from another module.
+
+
+C items
+=======
+
+.. c:function:: Sphinx_DoSomething()
+
+.. c:member:: SphinxStruct.member
+
+.. c:macro:: SPHINX_USE_PYTHON
+
+.. c:type:: SphinxType
+
+.. c:var:: sphinx_global
+
+
+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
+
+.. option:: +p
+
+Link to :option:`perl +p`.
+
+
+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/roots/test-ext-viewcode/spam/__init__.py b/tests/roots/test-ext-viewcode/spam/__init__.py
new file mode 100644
index 00000000..2c8603c1
--- /dev/null
+++ b/tests/roots/test-ext-viewcode/spam/__init__.py
@@ -0,0 +1,7 @@
+from __future__ import absolute_import
+
+from .mod1 import func1, Class1
+from .mod2 import (
+ func2,
+ Class2,
+)
diff --git a/tests/roots/test-ext-viewcode/spam/mod1.py b/tests/roots/test-ext-viewcode/spam/mod1.py
new file mode 100644
index 00000000..7133fc82
--- /dev/null
+++ b/tests/roots/test-ext-viewcode/spam/mod1.py
@@ -0,0 +1,15 @@
+"""
+mod1
+"""
+
+def func1(a, b):
+ """
+ this is func1
+ """
+ return a, b
+
+
+class Class1(object):
+ """
+ this is Class1
+ """
diff --git a/tests/roots/test-ext-viewcode/spam/mod2.py b/tests/roots/test-ext-viewcode/spam/mod2.py
new file mode 100644
index 00000000..79834b66
--- /dev/null
+++ b/tests/roots/test-ext-viewcode/spam/mod2.py
@@ -0,0 +1,15 @@
+"""
+mod2
+"""
+
+def func2(a, b):
+ """
+ this is func2
+ """
+ return a, b
+
+
+class Class2(object):
+ """
+ this is Class2
+ """
diff --git a/tests/roots/test-intl/admonitions.po b/tests/roots/test-intl/admonitions.po
index 0dd16376..bc722e58 100644
--- a/tests/roots/test-intl/admonitions.po
+++ b/tests/roots/test-intl/admonitions.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.2\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-07-03 12:00\n"
+"POT-Creation-Date: 2013-07-03 12:00+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/conf.py b/tests/roots/test-intl/conf.py
index 4c37f771..1b20244c 100644
--- a/tests/roots/test-intl/conf.py
+++ b/tests/roots/test-intl/conf.py
@@ -6,3 +6,4 @@ keep_warnings = True
templates_path = ['_templates']
html_additional_pages = {'index': 'index.html'}
release = version = '2013.120'
+gettext_enables = ['index']
diff --git a/tests/roots/test-intl/definition_terms.po b/tests/roots/test-intl/definition_terms.po
index 2c3a3bca..a147fe5e 100644
--- a/tests/roots/test-intl/definition_terms.po
+++ b/tests/roots/test-intl/definition_terms.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-01-01 05:00\n"
+"POT-Creation-Date: 2013-01-01 05:00+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/docfields.po b/tests/roots/test-intl/docfields.po
index f906ca19..8c3b8f97 100644
--- a/tests/roots/test-intl/docfields.po
+++ b/tests/roots/test-intl/docfields.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Sphinx <Tests> 0.6\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-12-16 14:11\n"
+"POT-Creation-Date: 2012-12-16 14:11+0000\n"
"PO-Revision-Date: 2012-12-18 06:14+0900\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/external_links.po b/tests/roots/test-intl/external_links.po
index e4e67643..8c53abbd 100644
--- a/tests/roots/test-intl/external_links.po
+++ b/tests/roots/test-intl/external_links.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-11-22 08:28\n"
+"POT-Creation-Date: 2012-11-22 08:28+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/figure_caption.po b/tests/roots/test-intl/figure_caption.po
index 2b85aea3..2fb1e5a5 100644
--- a/tests/roots/test-intl/figure_caption.po
+++ b/tests/roots/test-intl/figure_caption.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-01-04 7:00\n"
+"POT-Creation-Date: 2013-01-04 07:00+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/footnote.po b/tests/roots/test-intl/footnote.po
index b3876f51..3dfd3587 100644
--- a/tests/roots/test-intl/footnote.po
+++ b/tests/roots/test-intl/footnote.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-11-22 08:28\n"
+"POT-Creation-Date: 2012-11-22 08:28+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/glossary_terms.po b/tests/roots/test-intl/glossary_terms.po
index 1ffcaeb2..2746655e 100644
--- a/tests/roots/test-intl/glossary_terms.po
+++ b/tests/roots/test-intl/glossary_terms.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-01-29 14:10\n"
+"POT-Creation-Date: 2013-01-29 14:10+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/glossary_terms_inconsistency.po b/tests/roots/test-intl/glossary_terms_inconsistency.po
index 5e301657..ef2bf30f 100644
--- a/tests/roots/test-intl/glossary_terms_inconsistency.po
+++ b/tests/roots/test-intl/glossary_terms_inconsistency.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-01-29 14:10\n"
+"POT-Creation-Date: 2013-01-29 14:10+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/i18n.png b/tests/roots/test-intl/i18n.png
index 72c12d13..4c8f8992 100644
--- a/tests/roots/test-intl/i18n.png
+++ b/tests/roots/test-intl/i18n.png
Binary files differ
diff --git a/tests/roots/test-intl/index_entries.po b/tests/roots/test-intl/index_entries.po
index 6da9a813..83619b49 100644
--- a/tests/roots/test-intl/index_entries.po
+++ b/tests/roots/test-intl/index_entries.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: foo foo\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-01-05 18:10\n"
+"POT-Creation-Date: 2013-01-05 18:10+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/literalblock.po b/tests/roots/test-intl/literalblock.po
index 8ea83b3b..5b5f71e0 100644
--- a/tests/roots/test-intl/literalblock.po
+++ b/tests/roots/test-intl/literalblock.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-11-22 08:28\n"
+"POT-Creation-Date: 2012-11-22 08:28+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/refs_inconsistency.po b/tests/roots/test-intl/refs_inconsistency.po
index 9cab687f..cb2de9ad 100644
--- a/tests/roots/test-intl/refs_inconsistency.po
+++ b/tests/roots/test-intl/refs_inconsistency.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-12-05 08:28\n"
+"POT-Creation-Date: 2012-12-05 08:28+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/refs_python_domain.txt b/tests/roots/test-intl/refs_python_domain.txt
index 20a8bc50..2b021f2e 100644
--- a/tests/roots/test-intl/refs_python_domain.txt
+++ b/tests/roots/test-intl/refs_python_domain.txt
@@ -1,15 +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
-
+: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
index 8730c499..5b6d114c 100644
--- a/tests/roots/test-intl/role_xref.po
+++ b/tests/roots/test-intl/role_xref.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-02-04 14:00\n"
+"POT-Creation-Date: 2013-02-04 14:00+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/rubric.po b/tests/roots/test-intl/rubric.po
index 2c1214b7..91376236 100644
--- a/tests/roots/test-intl/rubric.po
+++ b/tests/roots/test-intl/rubric.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-11-12 7:00\n"
+"POT-Creation-Date: 2013-11-12 07:00+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/seealso.po b/tests/roots/test-intl/seealso.po
index d3b27e51..86a1c73c 100644
--- a/tests/roots/test-intl/seealso.po
+++ b/tests/roots/test-intl/seealso.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Sphinx <Tests> 0.6\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-12-16 06:06\n"
+"POT-Creation-Date: 2012-12-16 06:06+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/sphinx.po b/tests/roots/test-intl/sphinx.po
index cac5d4ad..a236f2f1 100644
--- a/tests/roots/test-intl/sphinx.po
+++ b/tests/roots/test-intl/sphinx.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-11-22 08:28\n"
+"POT-Creation-Date: 2012-11-22 08:28+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/subdir/contents.txt b/tests/roots/test-intl/subdir/contents.txt
index b6509baf..7578ce38 100644
--- a/tests/roots/test-intl/subdir/contents.txt
+++ b/tests/roots/test-intl/subdir/contents.txt
@@ -1,2 +1,2 @@
-subdir contents
-===============
+subdir contents
+===============
diff --git a/tests/roots/test-intl/versionchange.po b/tests/roots/test-intl/versionchange.po
index 911d3d9f..5a8df380 100644
--- a/tests/roots/test-intl/versionchange.po
+++ b/tests/roots/test-intl/versionchange.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sphinx 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-12-15 03:17\n"
+"POT-Creation-Date: 2012-12-15 03:17+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-intl/warnings.po b/tests/roots/test-intl/warnings.po
index bf82510e..7963a0a8 100644
--- a/tests/roots/test-intl/warnings.po
+++ b/tests/roots/test-intl/warnings.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Sphinx <Tests> 0.6\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-02-04 13:06\n"
+"POT-Creation-Date: 2013-02-04 13:06+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/tests/roots/test-numbered-circular/conf.py b/tests/roots/test-numbered-circular/conf.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/roots/test-numbered-circular/conf.py
diff --git a/tests/roots/test-numbered-circular/contents.rst b/tests/roots/test-numbered-circular/contents.rst
new file mode 100644
index 00000000..c3129cd4
--- /dev/null
+++ b/tests/roots/test-numbered-circular/contents.rst
@@ -0,0 +1,5 @@
+.. toctree::
+ :numbered:
+
+ sub
+
diff --git a/tests/roots/test-numbered-circular/sub.rst b/tests/roots/test-numbered-circular/sub.rst
new file mode 100644
index 00000000..070c3974
--- /dev/null
+++ b/tests/roots/test-numbered-circular/sub.rst
@@ -0,0 +1,3 @@
+.. toctree::
+
+ contents
diff --git a/tests/roots/test-numfig/bar.rst b/tests/roots/test-numfig/bar.rst
new file mode 100644
index 00000000..f86e7475
--- /dev/null
+++ b/tests/roots/test-numfig/bar.rst
@@ -0,0 +1,58 @@
+===
+Bar
+===
+
+Bar A
+=====
+
+.. figure:: rimg.png
+
+ should be Fig.2.1
+
+.. csv-table:: should be Table 2.1
+ :header-rows: 0
+
+ hello,world
+
+.. code-block:: python
+ :caption: should be List 2.1
+
+ print('hello world')
+
+.. toctree::
+
+ baz
+
+.. figure:: rimg.png
+
+ should be Fig.2.3
+
+.. csv-table:: should be Table 2.3
+ :header-rows: 0
+
+ hello,world
+
+.. code-block:: python
+ :caption: should be List 2.3
+
+ print('hello world')
+
+Bar B
+=====
+
+Bar B1
+------
+
+.. figure:: rimg.png
+
+ should be Fig.2.4
+
+.. csv-table:: should be Table 2.4
+ :header-rows: 0
+
+ hello,world
+
+.. code-block:: python
+ :caption: should be List 2.4
+
+ print('hello world')
diff --git a/tests/roots/test-numfig/baz.rst b/tests/roots/test-numfig/baz.rst
new file mode 100644
index 00000000..da9e0fe0
--- /dev/null
+++ b/tests/roots/test-numfig/baz.rst
@@ -0,0 +1,22 @@
+Baz A
+-----
+
+.. _fig22:
+
+.. figure:: rimg.png
+
+ should be Fig.2.2
+
+.. _table22:
+
+.. csv-table:: should be Table 2.2
+ :header-rows: 0
+
+ hello,world
+
+.. _code22:
+
+.. code-block:: python
+ :caption: should be List 2.2
+
+ print('hello world')
diff --git a/tests/roots/test-numfig/conf.py b/tests/roots/test-numfig/conf.py
new file mode 100644
index 00000000..f81c30bc
--- /dev/null
+++ b/tests/roots/test-numfig/conf.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'index'
diff --git a/tests/roots/test-numfig/foo.rst b/tests/roots/test-numfig/foo.rst
new file mode 100644
index 00000000..ef713574
--- /dev/null
+++ b/tests/roots/test-numfig/foo.rst
@@ -0,0 +1,71 @@
+===
+Foo
+===
+
+.. figure:: rimg.png
+
+ should be Fig.1.1
+
+.. csv-table:: should be Table 1.1
+ :header-rows: 0
+
+ hello,world
+
+.. code-block:: python
+ :caption: should be List 1.1
+
+ print('hello world')
+
+Foo A
+=====
+
+.. figure:: rimg.png
+
+ should be Fig.1.2
+
+.. figure:: rimg.png
+
+ should be Fig.1.3
+
+.. csv-table:: should be Table 1.2
+ :header-rows: 0
+
+ hello,world
+
+.. csv-table:: should be Table 1.3
+ :header-rows: 0
+
+ hello,world
+
+.. code-block:: python
+ :caption: should be List 1.2
+
+ print('hello world')
+
+.. code-block:: python
+ :caption: should be List 1.3
+
+ print('hello world')
+
+Foo A1
+------
+
+Foo B
+=====
+
+Foo B1
+------
+
+.. figure:: rimg.png
+
+ should be Fig.1.4
+
+.. csv-table:: should be Table 1.4
+ :header-rows: 0
+
+ hello,world
+
+.. code-block:: python
+ :caption: should be List 1.4
+
+ print('hello world')
diff --git a/tests/roots/test-numfig/index.rst b/tests/roots/test-numfig/index.rst
new file mode 100644
index 00000000..7bdf135c
--- /dev/null
+++ b/tests/roots/test-numfig/index.rst
@@ -0,0 +1,50 @@
+test-tocdepth
+=============
+
+.. toctree::
+ :numbered:
+
+ foo
+ bar
+
+.. _fig1:
+
+.. figure:: rimg.png
+
+ should be Fig.1
+
+.. figure:: rimg.png
+
+ should be Fig.2
+
+.. _table1:
+
+.. csv-table:: should be Table 1
+ :header-rows: 0
+
+ hello,world
+
+.. csv-table:: should be Table 2
+ :header-rows: 0
+
+ hello,world
+
+.. _code1:
+
+.. code-block:: python
+ :caption: should be List 1
+
+ print('hello world')
+
+.. code-block:: python
+ :caption: should be List 2
+
+ print('hello world')
+
+
+* Fig.1 is :numref:`fig1`
+* Fig.2.2 is :numref:`Figure# <fig22>`
+* Table.1 is :numref:`table1`
+* Table.2.2 is :numref:`Table:# <table22>`
+* List.1 is :numref:`code1`
+* List.2.2 is :numref:`Code-# <code22>`
diff --git a/tests/roots/test-numfig/rimg.png b/tests/roots/test-numfig/rimg.png
new file mode 100644
index 00000000..1081dc14
--- /dev/null
+++ b/tests/roots/test-numfig/rimg.png
Binary files differ
diff --git a/tests/roots/test-only-directive/conf.py b/tests/roots/test-only-directive/conf.py
deleted file mode 100644
index bcb4305d..00000000
--- a/tests/roots/test-only-directive/conf.py
+++ /dev/null
@@ -1,2 +0,0 @@
-
-project = 'test-only-directive'
diff --git a/tests/roots/test-setup/doc/contents.txt b/tests/roots/test-setup/doc/contents.txt
index cb52405f..56960f53 100644
--- a/tests/roots/test-setup/doc/contents.txt
+++ b/tests/roots/test-setup/doc/contents.txt
@@ -1,5 +1,5 @@
-contents
-=========
-
-spam egg ham
-
+contents
+=========
+
+spam egg ham
+
diff --git a/tests/roots/test-templating/autosummary_templating.txt b/tests/roots/test-templating/autosummary_templating.txt
index 05643a02..6b396a3f 100644
--- a/tests/roots/test-templating/autosummary_templating.txt
+++ b/tests/roots/test-templating/autosummary_templating.txt
@@ -4,10 +4,4 @@ Autosummary templating test
.. autosummary::
:toctree: generated
- sphinx.application.Sphinx
-
-.. currentmodule:: sphinx.application
-
-.. autoclass:: TemplateBridge
-
- .. automethod:: render
+ sphinx.application.TemplateBridge
diff --git a/tests/roots/test-tocdepth/bar.rst b/tests/roots/test-tocdepth/bar.rst
new file mode 100644
index 00000000..d70dec90
--- /dev/null
+++ b/tests/roots/test-tocdepth/bar.rst
@@ -0,0 +1,27 @@
+:tocdepth: 2
+
+===
+Bar
+===
+
+should be 2
+
+Bar A
+=====
+
+should be 2.1
+
+.. toctree::
+
+ baz
+
+Bar B
+=====
+
+should be 2.2
+
+Bar B1
+------
+
+should be 2.2.1
+
diff --git a/tests/roots/test-tocdepth/baz.rst b/tests/roots/test-tocdepth/baz.rst
new file mode 100644
index 00000000..b07fa050
--- /dev/null
+++ b/tests/roots/test-tocdepth/baz.rst
@@ -0,0 +1,5 @@
+Baz A
+-----
+
+should be 2.1.1
+
diff --git a/tests/roots/test-tocdepth/conf.py b/tests/roots/test-tocdepth/conf.py
new file mode 100644
index 00000000..f81c30bc
--- /dev/null
+++ b/tests/roots/test-tocdepth/conf.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'index'
diff --git a/tests/roots/test-tocdepth/foo.rst b/tests/roots/test-tocdepth/foo.rst
new file mode 100644
index 00000000..61fd539f
--- /dev/null
+++ b/tests/roots/test-tocdepth/foo.rst
@@ -0,0 +1,26 @@
+===
+Foo
+===
+
+should be 1
+
+Foo A
+=====
+
+should be 1.1
+
+Foo A1
+------
+
+should be 1.1.1
+
+Foo B
+=====
+
+should be 1.2
+
+Foo B1
+------
+
+should be 1.2.1
+
diff --git a/tests/roots/test-tocdepth/index.rst b/tests/roots/test-tocdepth/index.rst
new file mode 100644
index 00000000..0b651d48
--- /dev/null
+++ b/tests/roots/test-tocdepth/index.rst
@@ -0,0 +1,8 @@
+test-tocdepth
+=============
+
+.. toctree::
+ :numbered:
+
+ foo
+ bar
diff --git a/tests/root/versioning/added.txt b/tests/roots/test-versioning/added.txt
index 22a70739..22a70739 100644
--- a/tests/root/versioning/added.txt
+++ b/tests/roots/test-versioning/added.txt
diff --git a/tests/roots/test-versioning/conf.py b/tests/roots/test-versioning/conf.py
new file mode 100644
index 00000000..edcf9295
--- /dev/null
+++ b/tests/roots/test-versioning/conf.py
@@ -0,0 +1,3 @@
+project = 'versioning test root'
+master_doc = 'index'
+source_suffix = '.txt'
diff --git a/tests/root/versioning/deleted.txt b/tests/roots/test-versioning/deleted.txt
index a1a9c4c9..a1a9c4c9 100644
--- a/tests/root/versioning/deleted.txt
+++ b/tests/roots/test-versioning/deleted.txt
diff --git a/tests/root/versioning/deleted_end.txt b/tests/roots/test-versioning/deleted_end.txt
index f30e6300..f30e6300 100644
--- a/tests/root/versioning/deleted_end.txt
+++ b/tests/roots/test-versioning/deleted_end.txt
diff --git a/tests/root/versioning/index.txt b/tests/roots/test-versioning/index.txt
index 9d098f75..9d098f75 100644
--- a/tests/root/versioning/index.txt
+++ b/tests/roots/test-versioning/index.txt
diff --git a/tests/root/versioning/insert.txt b/tests/roots/test-versioning/insert.txt
index 1c157cc9..1c157cc9 100644
--- a/tests/root/versioning/insert.txt
+++ b/tests/roots/test-versioning/insert.txt
diff --git a/tests/root/versioning/insert_beginning.txt b/tests/roots/test-versioning/insert_beginning.txt
index 57102a76..57102a76 100644
--- a/tests/root/versioning/insert_beginning.txt
+++ b/tests/roots/test-versioning/insert_beginning.txt
diff --git a/tests/root/versioning/insert_similar.txt b/tests/roots/test-versioning/insert_similar.txt
index ee9b5305..ee9b5305 100644
--- a/tests/root/versioning/insert_similar.txt
+++ b/tests/roots/test-versioning/insert_similar.txt
diff --git a/tests/root/versioning/modified.txt b/tests/roots/test-versioning/modified.txt
index 49cdad93..49cdad93 100644
--- a/tests/root/versioning/modified.txt
+++ b/tests/roots/test-versioning/modified.txt
diff --git a/tests/root/versioning/original.txt b/tests/roots/test-versioning/original.txt
index b3fe0609..b3fe0609 100644
--- a/tests/root/versioning/original.txt
+++ b/tests/roots/test-versioning/original.txt
diff --git a/tests/run.py b/tests/run.py
index 37922f3b..e143ac15 100755
--- a/tests/run.py
+++ b/tests/run.py
@@ -9,53 +9,43 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
+import os
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)
+import traceback
+
+from path import path
+
+testroot = os.path.dirname(__file__) or '.'
+sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
+
+# check dependencies before testing
+print('Checking dependencies...')
+for modname in ('nose', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
+ 'snowballstemmer', 'babel'):
+ try:
+ __import__(modname)
+ except ImportError as err:
+ if modname == 'mock' and sys.version_info[0] == 3:
+ continue
+ traceback.print_exc()
+ print('The %r package is needed to run the Sphinx test suite.' % modname)
+ sys.exit(1)
+
+# find a temp dir for testing and clean it up now
+os.environ['SPHINX_TEST_TEMPDIR'] = \
+ os.path.abspath(os.path.join(testroot, 'build')) \
+ if 'SPHINX_TEST_TEMPDIR' not in os.environ \
+ else os.path.abspath(os.environ['SPHINX_TEST_TEMPDIR'])
+tempdir = path(os.environ['SPHINX_TEST_TEMPDIR'])
+print('Temporary files will be placed in %s.' % tempdir)
+if tempdir.exists():
+ tempdir.rmtree()
+tempdir.makedirs()
print('Running Sphinx test suite...')
+sys.stdout.flush()
+
+import nose
nose.main()
diff --git a/tests/test_api_translator.py b/tests/test_api_translator.py
new file mode 100644
index 00000000..e0ba5e0f
--- /dev/null
+++ b/tests/test_api_translator.py
@@ -0,0 +1,140 @@
+# -*- coding: utf-8 -*-
+"""
+ test_api_translator
+ ~~~~~~~~~~~~~~~~~~~
+
+ Test the Sphinx API for translator.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import sys
+
+from util import with_app, rootdir
+
+
+def setup_module():
+ sys.path.insert(0, rootdir / 'roots' / 'test-api-set-translator')
+
+
+def teardown_module():
+ sys.path.remove(rootdir / 'roots' / 'test-api-set-translator')
+
+
+@with_app('html')
+def test_html_translator(app, status, warning):
+ # no set_translator(), no html_translator_class
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'SmartyPantsHTMLTranslator'
+
+
+@with_app('html', confoverrides={
+ 'html_translator_class': 'translator.ExtHTMLTranslator'})
+def test_html_with_html_translator_class(app, status, warning):
+ # no set_translator(), but html_translator_class
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ExtHTMLTranslator'
+
+
+@with_app('html',
+ confoverrides={'html_use_smartypants': False})
+def test_html_with_smartypants(app, status, warning):
+ # no set_translator(), html_use_smartypants=False
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'HTMLTranslator'
+
+
+@with_app('html', testroot='api-set-translator')
+def test_html_with_set_translator_for_html_(app, status, warning):
+ # use set_translator(), no html_translator_class
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfHTMLTranslator'
+
+
+@with_app('html', testroot='api-set-translator',
+ confoverrides={'html_translator_class': 'ext.ExtHTMLTranslator'})
+def test_html_with_set_translator_for_html_and_html_translator_class(app, status, warning):
+ # use set_translator() and html_translator_class.
+ # set_translator() is given priority over html_translator_clas.
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfHTMLTranslator'
+
+
+## this test break test_websupport.test_comments test. why?
+# @with_app(
+# buildername='dirhtml',
+# srcdir=(test_roots / 'test-api-set-translator'),
+# )
+# def test_dirhtml_set_translator_for_dirhtml(app, status, warning):
+# translator_class = app.builder.translator_class
+# assert translator_class
+# assert translator_class.__name__ == 'ConfDirHTMLTranslator'
+
+
+@with_app('singlehtml', testroot='api-set-translator')
+def test_singlehtml_set_translator_for_singlehtml(app, status, warning):
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfSingleHTMLTranslator'
+
+
+@with_app('pickle', testroot='api-set-translator')
+def test_pickle_set_translator_for_pickle(app, status, warning):
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfPickleTranslator'
+
+
+@with_app('json', testroot='api-set-translator')
+def test_json_set_translator_for_json(app, status, warning):
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfJsonTranslator'
+
+
+@with_app('latex', testroot='api-set-translator')
+def test_html_with_set_translator_for_latex(app, status, warning):
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfLaTeXTranslator'
+
+
+@with_app('man', testroot='api-set-translator')
+def test_html_with_set_translator_for_man(app, status, warning):
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfManualPageTranslator'
+
+
+@with_app('texinfo', testroot='api-set-translator')
+def test_html_with_set_translator_for_texinfo(app, status, warning):
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfTexinfoTranslator'
+
+
+@with_app('text', testroot='api-set-translator')
+def test_html_with_set_translator_for_text(app, status, warning):
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfTextTranslator'
+
+
+@with_app('xml', testroot='api-set-translator')
+def test_html_with_set_translator_for_xml(app, status, warning):
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfXMLTranslator'
+
+
+@with_app('pseudoxml', testroot='api-set-translator')
+def test_html_with_set_translator_for_pseudoxml(app, status, warning):
+ translator_class = app.builder.translator_class
+ assert translator_class
+ assert translator_class.__name__ == 'ConfPseudoXMLTranslator'
diff --git a/tests/test_application.py b/tests/test_application.py
index 3d464eb5..1f188de1 100644
--- a/tests/test_application.py
+++ b/tests/test_application.py
@@ -9,22 +9,21 @@
: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
+from util import with_app, raises_msg
@with_app()
-def test_events(app):
- def empty(): pass
+def test_events(app, status, warning):
+ 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")
@@ -43,57 +42,49 @@ def test_events(app):
@with_app()
-def test_emit_with_nonascii_name_node(app):
+def test_emit_with_nonascii_name_node(app, status, warning):
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():
+@with_app()
+def test_output(app, status, warning):
+ 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 warning.getvalue() == "WARNING: Bad news!\n"
+ assert app._warncount == old_count + 1
+
+
+@with_app()
+def test_extensions(app, status, warning):
+ app.setup_extension('shutil')
+ assert warning.getvalue().startswith("WARNING: extension 'shutil'")
+
+
+@with_app()
+def test_domain_override(app, status, warning):
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()
+
+ # 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)
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index a7b2cee0..f4ae0c08 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -10,17 +10,15 @@
: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 six import StringIO
from docutils.statemachine import ViewList
from sphinx.ext.autodoc import AutoDirective, add_documenter, \
- ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL
+ ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL
app = None
@@ -125,24 +123,24 @@ def test_parse_name():
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'
+ directive.env.ref_context['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'
+ directive.env.ref_context['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.ref_context['py:module'] = 'util'
+ directive.env.ref_context['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.ref_context['py:module']
+ del directive.env.ref_context['py:class']
del directive.env.temp_data['autodoc:class']
@@ -424,6 +422,39 @@ def test_docstring_processing():
@with_setup(setup_test)
+def test_docstring_property_processing():
+ def genarate_docstring(objtype, name, **kw):
+ del processed_docstrings[:]
+ del processed_signatures[:]
+ inst = AutoDirective._registry[objtype](directive, name)
+ inst.generate(**kw)
+ results = list(directive.result)
+ docstrings = inst.get_doc()[0]
+ del directive.result[:]
+ return results, docstrings
+
+ directive.env.config.autodoc_docstring_signature = False
+ results, docstrings = genarate_docstring('attribute', 'test_autodoc.DocstringSig.prop1')
+ assert '.. py:attribute:: DocstringSig.prop1' in results
+ assert 'First line of docstring' in docstrings
+ assert 'DocstringSig.prop1(self)' in docstrings
+ results, docstrings = genarate_docstring('attribute', 'test_autodoc.DocstringSig.prop2')
+ assert '.. py:attribute:: DocstringSig.prop2' in results
+ assert 'First line of docstring' in docstrings
+ assert 'Second line of docstring' in docstrings
+
+ directive.env.config.autodoc_docstring_signature = True
+ results, docstrings = genarate_docstring('attribute', 'test_autodoc.DocstringSig.prop1')
+ assert '.. py:attribute:: DocstringSig.prop1' in results
+ assert 'First line of docstring' in docstrings
+ assert 'DocstringSig.prop1(self)' not in docstrings
+ results, docstrings = genarate_docstring('attribute', 'test_autodoc.DocstringSig.prop2')
+ assert '.. py:attribute:: DocstringSig.prop2' in results
+ assert 'First line of docstring' in docstrings
+ assert 'Second line of docstring' in docstrings
+
+
+@with_setup(setup_test)
def test_new_documenter():
class MyDocumenter(ModuleLevelDocumenter):
objtype = 'integer'
@@ -553,7 +584,7 @@ def test_generate():
'method', 'test_autodoc.Class.foobar', more_content=None)
# test auto and given content mixing
- directive.env.temp_data['py:module'] = 'test_autodoc'
+ directive.env.ref_context['py:module'] = 'test_autodoc'
assert_result_contains(' Function.', 'method', 'Class.meth')
add_content = ViewList()
add_content.append('Content.', '', 0)
@@ -651,12 +682,12 @@ def test_generate():
'attribute', 'test_autodoc.Class.descr')
# test generation for C modules (which have no source file)
- directive.env.temp_data['py:module'] = 'time'
+ directive.env.ref_context['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'
+ directive.env.ref_context['py:module'] = 'test_autodoc'
assert_order(['.. py:class:: Class(arg)',
' .. py:attribute:: Class.descr',
' .. py:method:: Class.meth()',
@@ -673,7 +704,7 @@ def test_generate():
' .. py:method:: Class.inheritedmeth()',
],
'class', 'Class', member_order='bysource', all_members=True)
- del directive.env.temp_data['py:module']
+ del directive.env.ref_context['py:module']
# test attribute initialized to class instance from other module
directive.env.temp_data['autodoc:class'] = 'test_autodoc.Class'
@@ -698,7 +729,7 @@ def test_generate():
'test_autodoc.Class.moore')
# test new attribute documenter behavior
- directive.env.temp_data['py:module'] = 'test_autodoc'
+ directive.env.ref_context['py:module'] = 'test_autodoc'
options.undoc_members = True
assert_processes([('class', 'test_autodoc.AttCls'),
('attribute', 'test_autodoc.AttCls.a1'),
@@ -712,7 +743,7 @@ def test_generate():
# 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'
+ directive.env.ref_context['py:module'] = 'test_autodoc'
options.inherited_members = False
options.undoc_members = False
options.members = ALL
@@ -734,7 +765,7 @@ def test_generate():
], 'class', 'InstAttCls')
del directive.env.temp_data['autodoc:class']
del directive.env.temp_data['autodoc:module']
- del directive.env.temp_data['py:module']
+ del directive.env.ref_context['py:module']
# test descriptor class documentation
options.members = ['CustomDataDescriptor']
@@ -776,12 +807,8 @@ def _funky_classmethod(name, b, c, d, docstring=None):
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)
+ from functools import partial
+ function = partial(template, b=b, c=c, d=d)
function.__name__ = name
function.__doc__ = docstring
return classmethod(function)
@@ -813,10 +840,9 @@ class Class(Base):
#: should be documented -- süß
attr = 'bar'
+ @property
def prop(self):
"""Property."""
- # stay 2.4 compatible (docstring!)
- prop = property(prop, doc="Property.")
docattr = 'baz'
"""should likewise be documented -- süß"""
@@ -886,6 +912,20 @@ First line of docstring
indented line
"""
+ @property
+ def prop1(self):
+ """DocstringSig.prop1(self)
+ First line of docstring
+ """
+ return 123
+
+ @property
+ def prop2(self):
+ """First line of docstring
+ Second line of docstring
+ """
+ return 456
+
class StrRepr(str):
def __repr__(self):
return self
diff --git a/tests/test_build.py b/tests/test_build.py
index c355b162..fe38cfaf 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -3,79 +3,86 @@
test_build
~~~~~~~~~~
- Test all builders that have no special checks.
+ Test all builders.
: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 six import BytesIO
+
from textwrap import dedent
+from util import with_app, rootdir, tempdir, SkipTest, TestApp
+
try:
from docutils.writers.manpage import Writer as ManWriter
except ImportError:
ManWriter = None
-def teardown_module():
- (test_root / '_build').rmtree(True)
-
+class MockOpener(object):
+ def open(self, req, **kwargs):
+ class result(BytesIO):
+ headers = None
+ url = req.url
+ return result()
-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()
+import sphinx.builders.linkcheck
+sphinx.builders.linkcheck.opener = MockOpener()
-@with_app(buildername='man')
-def test_man(app):
- if ManWriter is None:
+def verify_build(buildername, srcdir):
+ if buildername == 'man' and ManWriter is None:
raise SkipTest('man writer is not available')
- app.builder.build_all()
- assert (app.outdir / 'SphinxTests.1').exists()
+ app = TestApp(buildername=buildername, srcdir=srcdir)
+ try:
+ app.builder.build_all()
+ finally:
+ app.cleanup()
-def _test_nonascii_path(app):
- srcdir = path(app.srcdir)
- mb_name = u'\u65e5\u672c\u8a9e'
+def test_build_all():
+ # If supported, build in a non-ASCII source dir
+ test_name = u'\u65e5\u672c\u8a9e'
try:
- (srcdir / mb_name).makedirs()
+ srcdir = tempdir / test_name
+ (rootdir / 'root').copytree(tempdir / test_name)
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'))
+ srcdir = tempdir / 'all'
+ else:
+ # add a doc with a non-ASCII file name to the source dir
+ (srcdir / (test_name + '.txt')).write_text(dedent("""
+ nonascii file name page
+ =======================
+ """))
+
+ master_doc = srcdir / 'contents.txt'
+ master_doc.write_bytes((master_doc.text() + dedent("""
+ .. toctree::
+
+ %(test_name)s/%(test_name)s
+ """ % {'test_name': test_name})
+ ).encode('utf-8'))
+
+ # note: no 'html' - if it's ok with dirhtml it's ok with html
+ for buildername in ['dirhtml', 'singlehtml', 'latex', 'texinfo',
+ 'pickle', 'json', 'text', 'htmlhelp', 'qthelp', 'epub',
+ 'changes', 'xml', 'pseudoxml', 'man', 'linkcheck']:
+ yield verify_build, buildername, srcdir
+
+
+@with_app(buildername='text', testroot='circular')
+def test_circular_toctree(app, status, warning):
app.builder.build_all()
+ warnings = warning.getvalue()
+ assert 'circular toctree references detected, ignoring: sub <- contents <- sub' in warnings
+ assert 'circular toctree references detected, ignoring: contents <- sub <- contents' in warnings
-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()
+@with_app(buildername='text', testroot='numbered-circular')
+def test_numbered_circular_toctree(app, status, warning):
+ app.builder.build_all()
+ warnings = warning.getvalue()
+ assert 'circular toctree references detected, ignoring: sub <- contents <- sub' in warnings
+ assert 'circular toctree references detected, ignoring: contents <- sub <- contents' in warnings
diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py
index 9bde44b5..1de1306e 100644
--- a/tests/test_build_gettext.py
+++ b/tests/test_build_gettext.py
@@ -8,47 +8,32 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
-import gettext
import os
import re
+import gettext
from subprocess import Popen, PIPE
-from util import test_root, test_roots, with_app, SkipTest
-
+from nose.tools import assert_true, assert_equal
-def teardown_module():
- (test_root / '_build').rmtree(True)
- (test_roots / 'test-intl' / '_build').rmtree(True),
+from util import with_app, gen_with_app, SkipTest, assert_in
-@with_app(buildername='gettext')
-def test_all(app):
+@gen_with_app('gettext', srcdir='root-gettext')
+def test_all(app, status, warning):
# Generic build; should fail only when the builder is horribly broken.
app.builder.build_all()
-
-@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()
+ yield assert_true, (app.outdir / 'extapi.pot').isfile()
# directory items are grouped into sections
- assert (app.outdir / 'subdir.pot').isfile()
-
+ yield assert_true, (app.outdir / 'subdir.pot').isfile()
-@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
-
-
-@with_app(buildername='gettext')
-def test_gettext(app):
- app.builder.build(['markup'])
+ yield assert_in, 'msgid "something, something else, something more"', catalog
(app.outdir / 'en' / 'LC_MESSAGES').makedirs()
cwd = os.getcwd()
@@ -57,48 +42,47 @@ def test_gettext(app):
try:
p = Popen(['msginit', '--no-translator', '-i', 'markup.pot',
'--locale', 'en_US'],
- stdout=PIPE, stderr=PIPE)
+ 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
+ print(stdout)
+ print(stderr)
assert False, 'msginit exited with return code %s' % \
- p.returncode
- assert (app.outdir / 'en_US.po').isfile(), 'msginit failed'
+ p.returncode
+ yield assert_true, (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)
+ 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
+ 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'
+ p.returncode
+ yield assert_true, (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"
+ yield assert_equal, _("Testing various markup"), u"Testing various markup"
-@with_app(buildername='gettext',
- srcdir=(test_roots / 'test-intl'),
- doctreedir=(test_roots / 'test-intl' / '_build' / 'doctree'),
+@with_app('gettext', testroot='intl',
confoverrides={'gettext_compact': False})
-def test_gettext_index_entries(app):
+def test_gettext_index_entries(app, status, warning):
# 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:
@@ -106,7 +90,7 @@ def test_gettext_index_entries(app):
return None
pot = (app.outdir / 'index_entries.pot').text(encoding='utf-8')
- msgids = filter(None, map(msgid_getter, pot.splitlines()))
+ msgids = [_f for _f in map(msgid_getter, pot.splitlines()) if _f]
expected_msgids = [
"i18n with index entries",
@@ -129,6 +113,38 @@ def test_gettext_index_entries(app):
"Exception",
"Statement",
"Builtin",
+ ]
+ for expect in expected_msgids:
+ assert expect in msgids
+ msgids.remove(expect)
+
+ # unexpected msgid existent
+ assert msgids == []
+
+
+@with_app('gettext', testroot='intl',
+ confoverrides={'gettext_compact': False, 'gettext_enables': []})
+def test_gettext_disable_index_entries(app, status, warning):
+ # 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 = [_f for _f in map(msgid_getter, pot.splitlines()) if _f]
+
+ expected_msgids = [
+ "i18n with index entries",
+ "index target section",
+ "this is :index:`Newsletter` target paragraph.",
+ "various index entries",
+ "That's all.",
]
for expect in expected_msgids:
assert expect in msgids
@@ -138,10 +154,8 @@ def test_gettext_index_entries(app):
assert msgids == []
-@with_app(buildername='gettext',
- srcdir=(test_roots / 'test-intl'),
- doctreedir=(test_roots / 'test-intl' / '_build' / 'doctree'))
-def test_gettext_template(app):
+@with_app(buildername='gettext', testroot='intl')
+def test_gettext_template(app, status, warning):
app.builder.build_all()
assert (app.outdir / 'sphinx.pot').isfile()
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index 0c2efe42..baf3b6a6 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -11,43 +11,31 @@
import os
import re
-import sys
-import htmlentitydefs
-from StringIO import StringIO
-try:
- import pygments
-except ImportError:
- pygments = None
+from six import PY3, iteritems
+from six.moves import html_entities
from sphinx import __version__
-from util import test_root, remove_unicode_literals, gen_with_app, with_app
+from util import remove_unicode_literals, gen_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: \
+(%(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: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
-"""
+(%(root)s/markup.txt:\\d+: WARNING: Malformed :option: u'Python c option', does \
+not contain option marker - or -- or / or \\+
+%(root)s/undecodable.txt:3: WARNING: undecodable source characters, replacing \
+with "\\?": b?'here: >>>(\\\\|/)xbb<<<'
+)?"""
HTML_WARNINGS = ENV_WARNINGS + """\
%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
@@ -57,13 +45,14 @@ None:\\d+: WARNING: citation not found: missing
%(root)s/markup.txt:: WARNING: invalid pair index entry u'keyword; '
"""
-if sys.version_info >= (3, 0):
+if PY3:
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):
@@ -87,6 +76,8 @@ HTML_XPATH = {
(".//a[@href='../_downloads/img.png']", ''),
(".//img[@src='../_images/img.png']", ''),
(".//p", 'This is an include file.'),
+ (".//pre/span", 'line 1'),
+ (".//pre/span", 'line 2'),
],
'includes.html': [
(".//pre", u'Max Strauß'),
@@ -94,6 +85,23 @@ HTML_XPATH = {
(".//a[@href='_downloads/img1.png']", ''),
(".//pre", u'"quotes"'),
(".//pre", u"'included'"),
+ (".//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",
+ u'^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'-| |-'),
],
'autodoc.html': [
(".//dt[@id='test_autodoc.Class']", ''),
@@ -125,25 +133,29 @@ HTML_XPATH = {
(".//li/strong", r'^command\\n$'),
(".//li/strong", r'^program\\n$'),
(".//li/em", r'^dfn\\n$'),
- (".//li/tt/span[@class='pre']", r'^kbd\\n$'),
+ (".//li/code/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$'),
+ (".//li/code/span[@class='pre']", '^a/$'),
+ (".//li/code/em/span[@class='pre']", '^varpart$'),
+ (".//li/code/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://www.python.org/dev/peps/pep-0008']"
+ "[@class='pep reference external']/strong", 'Python Enhancement Proposal #8'),
(".//a[@href='http://tools.ietf.org/html/rfc1.html']"
"[@class='rfc reference external']/strong", 'RFC 1'),
+ (".//a[@href='http://tools.ietf.org/html/rfc1.html']"
+ "[@class='rfc reference external']/strong", 'Request for Comments #1'),
(".//a[@href='objects.html#envvar-HOME']"
- "[@class='reference internal']/tt/span[@class='pre']", 'HOME'),
+ "[@class='reference internal']/code/span[@class='pre']", 'HOME'),
(".//a[@href='#with']"
- "[@class='reference internal']/tt/span[@class='pre']", '^with$'),
+ "[@class='reference internal']/code/span[@class='pre']", '^with$'),
(".//a[@href='#grammar-token-try_stmt']"
- "[@class='reference internal']/tt/span", '^statement$'),
+ "[@class='reference internal']/code/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'),
+ "[@class='reference internal']/code/span[@class='pre']", '-c'),
# abbreviations
(".//abbr[@title='abbreviation']", '^abbr$'),
# version stuff
@@ -168,18 +180,21 @@ HTML_XPATH = {
(".//dl/dt[@id='term-boson']", 'boson'),
# a production list
(".//pre/strong", 'try_stmt'),
- (".//pre/a[@href='#grammar-token-try1_stmt']/tt/span", 'try1_stmt'),
+ (".//pre/a[@href='#grammar-token-try1_stmt']/code/span", 'try1_stmt'),
# tests for ``only`` directive
(".//p", 'A global substitution.'),
(".//p", 'In HTML.'),
(".//p", 'In both.'),
(".//p", 'Always present'),
+ # tests for ``any`` role
+ (".//a[@href='#with']/em", 'headings'),
+ (".//a[@href='objects.html#func_without_body']/code/span", 'objects'),
],
'objects.html': [
(".//dt[@id='mod.Cls.meth1']", ''),
(".//dt[@id='errmod.Error']", ''),
- (".//dt/tt", r'long\(parameter,\s* list\)'),
- (".//dt/tt", 'another one'),
+ (".//dt/code", r'long\(parameter,\s* list\)'),
+ (".//dt/code", 'another one'),
(".//a[@href='#mod.Cls'][@class='reference internal']", ''),
(".//dl[@class='userdesc']", ''),
(".//dt[@id='userdesc-myobj']", ''),
@@ -191,8 +206,6 @@ HTML_XPATH = {
(".//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'),
@@ -213,12 +226,10 @@ HTML_XPATH = {
(".//h4", 'Custom sidebar'),
# docfields
(".//td[@class='field-body']/strong", '^moo$'),
- (".//td[@class='field-body']/strong",
- tail_check(r'\(Moo\) .* 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')),
+ (".//td[@class='field-body']/ul/li/em", tail_check(r'.* Some parameter')),
],
'contents.html': [
(".//meta[@name='hc'][@content='hcval']", ''),
@@ -239,6 +250,11 @@ HTML_XPATH = {
(".//h4", 'Contents sidebar'),
# custom JavaScript
(".//script[@src='file://moo.js']", ''),
+ # URL in contents
+ (".//a[@class='reference external'][@href='http://sphinx-doc.org/']",
+ 'http://sphinx-doc.org/'),
+ (".//a[@class='reference external'][@href='http://sphinx-doc.org/latest/']",
+ 'Latest reference'),
],
'bom.html': [
(".//title", " File with UTF-8 BOM"),
@@ -258,33 +274,19 @@ HTML_XPATH = {
(".//a/strong", "Other"),
(".//a", "entry"),
(".//dt/a", "double"),
- ]
+ ],
+ 'footnote.html': [
+ (".//a[@class='footnote-reference'][@href='#id5'][@id='id1']", r"\[1\]"),
+ (".//a[@class='footnote-reference'][@href='#id6'][@id='id2']", r"\[2\]"),
+ (".//a[@class='footnote-reference'][@href='#foo'][@id='id3']", r"\[3\]"),
+ (".//a[@class='reference internal'][@href='#bar'][@id='id4']", r"\[bar\]"),
+ (".//a[@class='fn-backref'][@href='#id1']", r"\[1\]"),
+ (".//a[@class='fn-backref'][@href='#id2']", r"\[2\]"),
+ (".//a[@class='fn-backref'][@href='#id3']", r"\[3\]"),
+ (".//a[@class='fn-backref'][@href='#id4']", r"\[bar\]"),
+ ],
}
-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."""
@@ -301,10 +303,15 @@ class NslessParser(ET.XMLParser):
return name
-def check_xpath(etree, fname, path, check):
+def check_xpath(etree, fname, path, check, be_found=True):
nodes = list(etree.findall(path))
- assert nodes != [], ('did not find any node matching xpath '
- '%r in file %s' % (path, fname))
+ if check is None:
+ assert nodes == [], ('found any nodes matching xpath '
+ '%r in file %s' % (path, fname))
+ return
+ else:
+ assert nodes != [], ('did not find any node matching xpath '
+ '%r in file %s' % (path, fname))
if hasattr(check, '__call__'):
check(nodes)
elif not check:
@@ -313,12 +320,13 @@ def check_xpath(etree, fname, path, check):
else:
rex = re.compile(check)
for node in nodes:
- if node.text and rex.search(node.text):
+ if node.text and (bool(rex.search(node.text)) ^ (not be_found)):
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]))
+ [node.text for node in nodes]))
+
def check_static_entries(outdir):
staticdir = outdir / '_static'
@@ -333,25 +341,27 @@ def check_static_entries(outdir):
# a file from _static, but matches exclude_patterns
assert not (staticdir / 'excluded.css').exists()
+
def check_extra_entries(outdir):
assert (outdir / 'robots.txt').isfile()
-@gen_with_app(buildername='html', warning=html_warnfile, cleanenv=True,
+
+@gen_with_app(buildername='html',
confoverrides={'html_context.hckey_co': 'hcval_co'},
tags=['testtag'])
-def test_html(app):
+def test_html_output(app, status, warning):
app.builder.build_all()
- html_warnings = html_warnfile.getvalue().replace(os.sep, '/')
+ html_warnings = warning.getvalue().replace(os.sep, '/')
html_warnings_exp = HTML_WARNINGS % {
- 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
+ '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
+ 'Warnings don\'t match:\n' + \
+ '--- Expected (regex):\n' + html_warnings_exp + \
+ '--- Got:\n' + html_warnings
- for fname, paths in HTML_XPATH.iteritems():
+ for fname, paths in iteritems(HTML_XPATH):
parser = NslessParser()
- parser.entity.update(htmlentitydefs.entitydefs)
+ parser.entity.update(html_entities.entitydefs)
fp = open(os.path.join(app.outdir, fname), 'rb')
try:
etree = ET.parse(fp, parser)
@@ -363,16 +373,531 @@ def test_html(app):
check_static_entries(app.builder.outdir)
check_extra_entries(app.builder.outdir)
-@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')
+
+@gen_with_app(buildername='html', testroot='tocdepth')
+def test_tocdepth(app, status, warning):
+ # issue #1251
+ app.builder.build_all()
+
+ expects = {
+ 'index.html': [
+ (".//li[@class='toctree-l3']/a", '1.1.1. Foo A1', True),
+ (".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
+ (".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
+ (".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
+ ],
+ 'foo.html': [
+ (".//h1", '1. Foo', True),
+ (".//h2", '1.1. Foo A', True),
+ (".//h3", '1.1.1. Foo A1', True),
+ (".//h2", '1.2. Foo B', True),
+ (".//h3", '1.2.1. Foo B1', True),
+ ],
+ 'bar.html': [
+ (".//h1", '2. Bar', True),
+ (".//h2", '2.1. Bar A', True),
+ (".//h2", '2.2. Bar B', True),
+ (".//h3", '2.2.1. Bar B1', True),
+ ],
+ 'baz.html': [
+ (".//h1", '2.1.1. Baz A', True),
+ ],
+ }
+
+ for fname, paths in iteritems(expects):
+ parser = NslessParser()
+ parser.entity.update(html_entities.entitydefs)
+ fp = open(os.path.join(app.outdir, fname), 'rb')
+ try:
+ etree = ET.parse(fp, parser)
+ finally:
+ fp.close()
+
+ for xpath, check, be_found in paths:
+ yield check_xpath, etree, fname, xpath, check, be_found
+
+
+@gen_with_app(buildername='singlehtml', testroot='tocdepth')
+def test_tocdepth_singlehtml(app, status, warning):
app.builder.build_all()
+
+ expects = {
+ 'index.html': [
+ (".//li[@class='toctree-l3']/a", '1.1.1. Foo A1', True),
+ (".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
+ (".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
+ (".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
+
+ # index.rst
+ (".//h1", 'test-tocdepth', True),
+
+ # foo.rst
+ (".//h2", '1. Foo', True),
+ (".//h3", '1.1. Foo A', True),
+ (".//h4", '1.1.1. Foo A1', True),
+ (".//h3", '1.2. Foo B', True),
+ (".//h4", '1.2.1. Foo B1', True),
+
+ # bar.rst
+ (".//h2", '2. Bar', True),
+ (".//h3", '2.1. Bar A', True),
+ (".//h3", '2.2. Bar B', True),
+ (".//h4", '2.2.1. Bar B1', True),
+
+ # baz.rst
+ (".//h4", '2.1.1. Baz A', True),
+ ],
+ }
+
+ for fname, paths in iteritems(expects):
+ parser = NslessParser()
+ parser.entity.update(html_entities.entitydefs)
+ fp = open(os.path.join(app.outdir, fname), 'rb')
+ try:
+ etree = ET.parse(fp, parser)
+ finally:
+ fp.close()
+
+ for xpath, check, be_found in paths:
+ yield check_xpath, etree, fname, xpath, check, be_found
+
+
+@gen_with_app(buildername='html', testroot='numfig')
+def test_numfig_disabled(app, status, warning):
+ app.builder.build_all()
+
+ expects = {
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//table/caption/span[@class='caption-number']", None, True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//li/code/span", '^fig1$', True),
+ (".//li/code/span", '^Figure#$', True),
+ (".//li/code/span", '^table1$', True),
+ (".//li/code/span", '^Table:#$', True),
+ (".//li/code/span", '^code1$', True),
+ (".//li/code/span", '^Code-#$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//table/caption/span[@class='caption-number']", None, True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", None, True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//table/caption/span[@class='caption-number']", None, True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", None, True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", None, True),
+ (".//table/caption/span[@class='caption-number']", None, True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", None, True),
+ ],
+ }
+
+ for fname, paths in iteritems(expects):
+ parser = NslessParser()
+ parser.entity.update(html_entities.entitydefs)
+ fp = open(os.path.join(app.outdir, fname), 'rb')
+ try:
+ etree = ET.parse(fp, parser)
+ finally:
+ fp.close()
+
+ for xpath, check, be_found in paths:
+ yield check_xpath, etree, fname, xpath, check, be_found
+
+
+@gen_with_app(buildername='html', testroot='numfig',
+ confoverrides={'numfig': True})
+def test_numfig_without_numbered_toctree(app, status, warning):
+ # remove :numbered: option
+ index = (app.srcdir / 'index.rst').text()
+ index = re.sub(':numbered:.*', '', index, re.MULTILINE)
+ (app.srcdir / 'index.rst').write_text(index, encoding='utf-8')
+ app.builder.build_all()
+
+ expects = {
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 9 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 10 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 9 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 10 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 9 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 10 $', True),
+ (".//li/a/em", '^Fig. 9$', True),
+ (".//li/a/em", '^Figure6$', True),
+ (".//li/a/em", '^Table 9$', True),
+ (".//li/a/em", '^Table:6$', True),
+ (".//li/a/em", '^Listing 9$', True),
+ (".//li/a/em", '^Code-6$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 4 $', True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 5 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 7 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 8 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 5 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 7 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 8 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 5 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 7 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 8 $', True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 6 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 6 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 6 $', True),
+ ],
+ }
+
+ for fname, paths in iteritems(expects):
+ parser = NslessParser()
+ parser.entity.update(html_entities.entitydefs)
+ fp = open(os.path.join(app.outdir, fname), 'rb')
+ try:
+ etree = ET.parse(fp, parser)
+ finally:
+ fp.close()
+
+ for xpath, check, be_found in paths:
+ yield check_xpath, etree, fname, xpath, check, be_found
+
+
+@gen_with_app(buildername='html', testroot='numfig',
+ confoverrides={'numfig': True})
+def test_numfig_with_numbered_toctree(app, status, warning):
+ app.builder.build_all()
+
+ expects = {
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2 $', True),
+ (".//li/a/em", '^Fig. 1$', True),
+ (".//li/a/em", '^Figure2.2$', True),
+ (".//li/a/em", '^Table 1$', True),
+ (".//li/a/em", '^Table:2.2$', True),
+ (".//li/a/em", '^Listing 1$', True),
+ (".//li/a/em", '^Code-2.2$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.2 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.4 $', True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.4 $', True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.2 $', True),
+ ],
+ }
+
+ for fname, paths in iteritems(expects):
+ parser = NslessParser()
+ parser.entity.update(html_entities.entitydefs)
+ fp = open(os.path.join(app.outdir, fname), 'rb')
+ try:
+ etree = ET.parse(fp, parser)
+ finally:
+ fp.close()
+
+ for xpath, check, be_found in paths:
+ yield check_xpath, etree, fname, xpath, check, be_found
+
+
+@gen_with_app(buildername='html', testroot='numfig',
+ confoverrides={'numfig': True,
+ 'numfig_prefix': {'figure': 'Figure:%s',
+ 'table': 'Tab_%s',
+ 'code-block': 'Code-%s'}})
+def test_numfig_with_prefix(app, status, warning):
+ app.builder.build_all()
+
+ expects = {
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2 $', True),
+ (".//li/a/em", '^Figure:1$', True),
+ (".//li/a/em", '^Figure2.2$', True),
+ (".//li/a/em", '^Tab_1$', True),
+ (".//li/a/em", '^Table:2.2$', True),
+ (".//li/a/em", '^Code-1$', True),
+ (".//li/a/em", '^Code-2.2$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1.2 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:1.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_1.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-1.4 $', True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2.4 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2.4 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2.4 $', True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Figure:2.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Tab_2.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Code-2.2 $', True),
+ ],
+ }
+
+ for fname, paths in iteritems(expects):
+ parser = NslessParser()
+ parser.entity.update(html_entities.entitydefs)
+ fp = open(os.path.join(app.outdir, fname), 'rb')
+ try:
+ etree = ET.parse(fp, parser)
+ finally:
+ fp.close()
+
+ for xpath, check, be_found in paths:
+ yield check_xpath, etree, fname, xpath, check, be_found
+
+
+@gen_with_app(buildername='html', testroot='numfig',
+ confoverrides={'numfig': True, 'numfig_secnum_depth': 2})
+def test_numfig_with_secnum_depth(app, status, warning):
+ app.builder.build_all()
+
+ expects = {
+ 'index.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2 $', True),
+ (".//li/a/em", '^Fig. 1$', True),
+ (".//li/a/em", '^Figure2.1.2$', True),
+ (".//li/a/em", '^Table 1$', True),
+ (".//li/a/em", '^Table:2.1.2$', True),
+ (".//li/a/em", '^Listing 1$', True),
+ (".//li/a/em", '^Code-2.1.2$', True),
+ ],
+ 'foo.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.1.2 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 1.2.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.1.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 1.2.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.1.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 1.2.1 $', True),
+ ],
+ 'bar.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.1.1 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.1.3 $', True),
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.2.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.1.1 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.1.3 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.2.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.1.1 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.1.3 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.2.1 $', True),
+ ],
+ 'baz.html': [
+ (".//div[@class='figure']/p[@class='caption']/"
+ "span[@class='caption-number']", '^Fig. 2.1.2 $', True),
+ (".//table/caption/span[@class='caption-number']",
+ '^Table 2.1.2 $', True),
+ (".//div[@class='code-block-caption']/"
+ "span[@class='caption-number']", '^Listing 2.1.2 $', True),
+ ],
+ }
+
+ for fname, paths in iteritems(expects):
+ parser = NslessParser()
+ parser.entity.update(html_entities.entitydefs)
+ fp = open(os.path.join(app.outdir, fname), 'rb')
+ try:
+ etree = ET.parse(fp, parser)
+ finally:
+ fp.close()
+
+ for xpath, check, be_found in paths:
+ yield check_xpath, etree, fname, xpath, check, be_found
diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py
index 78aa71cc..3b6dd3e2 100644
--- a/tests/test_build_latex.py
+++ b/tests/test_build_latex.py
@@ -8,25 +8,20 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
import os
import re
-import sys
-from StringIO import StringIO
from subprocess import Popen, PIPE
+from six import PY3
+
from sphinx.writers.latex import LaTeXTranslator
-from util import test_root, SkipTest, remove_unicode_literals, with_app
+from util import 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.\\*'
@@ -34,21 +29,21 @@ WARNING: invalid pair index entry u''
WARNING: invalid pair index entry u'keyword; '
"""
-if sys.version_info >= (3, 0):
+if PY3:
LATEX_WARNINGS = remove_unicode_literals(LATEX_WARNINGS)
-@with_app(buildername='latex', warning=latex_warnfile, cleanenv=True)
-def test_latex(app):
+@with_app(buildername='latex')
+def test_latex(app, status, warning):
LaTeXTranslator.ignore_missing_images = True
app.builder.build_all()
- latex_warnings = latex_warnfile.getvalue().replace(os.sep, '/')
+ latex_warnings = warning.getvalue().replace(os.sep, '/')
latex_warnings_exp = LATEX_WARNINGS % {
- 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
+ '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
+ '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()
@@ -90,9 +85,35 @@ def test_latex(app):
else:
stdout, stderr = p.communicate()
if p.returncode != 0:
- print stdout
- print stderr
+ print(stdout)
+ print(stderr)
del app.cleanup_trees[:]
assert False, 'latex exited with return code %s' % p.returncode
finally:
os.chdir(cwd)
+
+
+@with_app(buildername='latex', testroot='numfig',
+ confoverrides={'numfig': True})
+def test_numref(app, status, warning):
+ app.builder.build_all()
+ result = (app.outdir / 'Python.tex').text(encoding='utf8')
+ print(result)
+ print(status.getvalue())
+ print(warning.getvalue())
+ assert '\\ref{index:fig1}' in result
+ assert '\\ref{baz:fig22}' in result
+ assert '\\ref{index:table1}' in result
+ assert '\\ref{baz:table22}' in result
+ assert '\\ref{index:code1}' in result
+ assert '\\ref{baz:code22}' in result
+
+
+@with_app(buildername='latex')
+def test_latex_add_latex_package(app, status, warning):
+ app.add_latex_package('foo')
+ app.add_latex_package('bar', 'baz')
+ app.builder.build_all()
+ result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
+ assert '\\usepackage{foo}' in result
+ assert '\\usepackage[baz]{bar}' in result
diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py
index 2f519435..bb10f8fa 100644
--- a/tests/test_build_texinfo.py
+++ b/tests/test_build_texinfo.py
@@ -8,46 +8,41 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
import os
import re
-import sys
-from StringIO import StringIO
from subprocess import Popen, PIPE
+from six import PY3
+
from sphinx.writers.texinfo import TexinfoTranslator
-from util import test_root, SkipTest, remove_unicode_literals, with_app
+from util import 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):
+if PY3:
TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS)
-@with_app(buildername='texinfo', warning=texinfo_warnfile, cleanenv=True)
-def test_texinfo(app):
+@with_app('texinfo')
+def test_texinfo(app, status, warning):
TexinfoTranslator.ignore_missing_images = True
app.builder.build_all()
- texinfo_warnings = texinfo_warnfile.getvalue().replace(os.sep, '/')
+ texinfo_warnings = warning.getvalue().replace(os.sep, '/')
texinfo_warnings_exp = TEXINFO_WARNINGS % {
- 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
+ '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
+ '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)
@@ -61,8 +56,8 @@ def test_texinfo(app):
stdout, stderr = p.communicate()
retcode = p.returncode
if retcode != 0:
- print stdout
- print stderr
+ print(stdout)
+ print(stderr)
del app.cleanup_trees[:]
assert False, 'makeinfo exited with return code %s' % retcode
finally:
diff --git a/tests/test_build_text.py b/tests/test_build_text.py
index e6e4d5be..d486bed2 100644
--- a/tests/test_build_text.py
+++ b/tests/test_build_text.py
@@ -18,29 +18,16 @@ from util import with_app
def with_text_app(*args, **kw):
default_kw = {
'buildername': 'text',
- 'srcdir': '(empty)',
- 'confoverrides': {
- 'project': 'text',
- 'master_doc': 'contents',
- },
+ 'testroot': 'build-text',
}
default_kw.update(kw)
return with_app(*args, **default_kw)
@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')
+def test_maxwitdh_with_prefix(app, status, warning):
+ app.builder.build_update()
+ result = (app.outdir / 'maxwidth.txt').text(encoding='utf-8')
lines = result.splitlines()
line_widths = [column_width(line) for line in lines]
@@ -58,105 +45,52 @@ def test_maxwitdh_with_prefix(app):
@with_text_app()
-def test_lineblock(app):
+def test_lineblock(app, status, warning):
# 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')
-
+ app.builder.build_update()
+ result = (app.outdir / 'lineblock.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"
- )
-
+ u"* one\n"
+ u"\n"
+ u" line-block 1\n"
+ u" line-block 2\n"
+ u"\n"
+ u"followed paragraph.\n"
+ )
assert result == expect
@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('=', '*')
+def test_nonascii_title_line(app, status, warning):
+ app.builder.build_update()
+ result = (app.outdir / 'nonascii_title.txt').text(encoding='utf-8')
+ expect_underline = '******'
result_underline = result.splitlines()[2].strip()
assert expect_underline == result_underline
@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')
-
+def test_nonascii_table(app, status, warning):
+ app.builder.build_update()
+ result = (app.outdir / 'nonascii_table.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
@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')
-
+def test_nonascii_maxwidth(app, status, warning):
+ app.builder.build_update()
+ result = (app.outdir / 'nonascii_maxwidth.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
@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')
-
+def test_table_with_empty_cell(app, status, warning):
+ app.builder.build_update()
+ result = (app.outdir / 'table.txt').text(encoding='utf-8')
lines = [line.strip() for line in result.splitlines() if line.strip()]
assert lines[0] == "+-------+-------+"
assert lines[1] == "| XXX | XXX |"
diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py
new file mode 100644
index 00000000..c4f5c08f
--- /dev/null
+++ b/tests/test_catalogs.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+"""
+ test_build_base
+ ~~~~~~~~~~~~~~~
+
+ Test the base build process.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import shutil
+
+from nose.tools import with_setup
+
+from util import with_app, find_files, rootdir, tempdir
+
+root = tempdir / 'test-intl'
+build_dir = root / '_build'
+locale_dir = build_dir / 'locale'
+
+
+def setup_test():
+ # delete remnants left over after failed build
+ root.rmtree(True)
+ (rootdir / 'roots' / 'test-intl').copytree(root)
+ # copy all catalogs into locale layout directory
+ for po in find_files(root, '.po'):
+ copy_po = (locale_dir / 'en' / 'LC_MESSAGES' / po)
+ if not copy_po.parent.exists():
+ copy_po.parent.makedirs()
+ shutil.copy(root / po, copy_po)
+
+
+def teardown_test():
+ build_dir.rmtree(True)
+
+
+@with_setup(setup_test, teardown_test)
+@with_app(buildername='html', testroot='intl',
+ confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
+def test_compile_all_catalogs(app, status, warning):
+ app.builder.compile_all_catalogs()
+
+ catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
+ expect = set([
+ x.replace('.po', '.mo')
+ for x in find_files(catalog_dir, '.po')
+ ])
+ actual = set(find_files(catalog_dir, '.mo'))
+ assert actual # not empty
+ assert actual == expect
+
+
+@with_setup(setup_test, teardown_test)
+@with_app(buildername='html', testroot='intl',
+ confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
+def test_compile_specific_catalogs(app, status, warning):
+ app.builder.compile_specific_catalogs(['admonitions'])
+
+ catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
+ actual = set(find_files(catalog_dir, '.mo'))
+ assert actual == set(['admonitions.mo'])
+
+
+@with_setup(setup_test, teardown_test)
+@with_app(buildername='html', testroot='intl',
+ confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
+def test_compile_update_catalogs(app, status, warning):
+ app.builder.compile_update_catalogs()
+
+ catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
+ expect = set([
+ x.replace('.po', '.mo')
+ for x in find_files(catalog_dir, '.po')
+ ])
+ actual = set(find_files(catalog_dir, '.mo'))
+ assert actual # not empty
+ assert actual == expect
diff --git a/tests/test_config.py b/tests/test_config.py
index 1e00091d..0dcf3fa3 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -9,18 +9,18 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-import sys
+from six import PY3
-from util import TestApp, with_app, with_tempdir, raises, raises_msg, write_file
+from util import TestApp, with_app, with_tempdir, raises, raises_msg
from sphinx.config import Config
from sphinx.errors import ExtensionError, ConfigError, VersionRequirementError
-from sphinx.util.pycompat import b
@with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True',
- 'latex_elements.docclass': 'scrartcl'})
-def test_core_config(app):
+ 'latex_elements.docclass': 'scrartcl',
+ 'modindex_common_prefix': 'path1,path2'})
+def test_core_config(app, status, warning):
cfg = app.config
# simple values
@@ -31,11 +31,12 @@ def test_core_config(app):
# overrides
assert cfg.master_doc == 'master'
assert cfg.latex_elements['docclass'] == 'scrartcl'
+ assert cfg.modindex_common_prefix == ['path1', 'path2']
# simple default values
assert 'locale_dirs' not in cfg.__dict__
assert cfg.locale_dirs == []
- assert cfg.trim_footnote_reference_space == False
+ assert cfg.trim_footnote_reference_space is False
# complex default values
assert 'html_title' not in cfg.__dict__
@@ -67,7 +68,7 @@ def test_core_config(app):
@with_app()
-def test_extension_values(app):
+def test_extension_values(app, status, warning):
cfg = app.config
# default value
@@ -85,23 +86,24 @@ def test_extension_values(app):
@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')
+ (dir / 'conf.py').write_text(u'project = \n', encoding='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')
+ (dir / 'conf.py').write_text(
+ u'# -*- coding: utf-8\n\nproject = u"Jägermeister"\n',
+ encoding='utf-8')
cfg = Config(dir, 'conf.py', {}, None)
- cfg.init_values()
+ cfg.init_values(lambda warning: 1/0)
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):
+ if PY3:
return
- write_file(dir / 'conf.py', u'# -*- coding: latin-1\nproject = "fooä"\n',
- 'latin-1')
+ (dir / 'conf.py').write_text(
+ u'# -*- coding: latin-1\nproject = "fooä"\n', encoding='latin-1')
cfg = Config(dir, 'conf.py', {}, None)
warned = [False]
def warn(msg):
@@ -126,8 +128,8 @@ def test_needs_sphinx():
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))
+ for eol in (b'\n', b'\r\n'):
+ configfile.write_bytes(b'project = "spam"' + eol)
cfg = Config(tmpdir, 'conf.py', {}, None)
- cfg.init_values()
+ cfg.init_values(lambda warning: 1/0)
assert cfg.project == u'spam'
diff --git a/tests/test_cpp_domain.py b/tests/test_cpp_domain.py
deleted file mode 100644
index 8e1cb22b..00000000
--- a/tests/test_cpp_domain.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# -*- 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_directive_code.py b/tests/test_directive_code.py
new file mode 100644
index 00000000..651527c7
--- /dev/null
+++ b/tests/test_directive_code.py
@@ -0,0 +1,191 @@
+# -*- coding: utf-8 -*-
+"""
+ test_directive_code
+ ~~~~~~~~~~~~~~~~~~~
+
+ Test the code-block directive.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from xml.etree import ElementTree
+
+from util import with_app
+
+
+@with_app('xml', testroot='directive-code')
+def test_code_block(app, status, warning):
+ app.builder.build('index')
+ et = ElementTree.parse(app.outdir / 'index.xml')
+ secs = et.findall('./section/section')
+ code_block = secs[0].findall('literal_block')
+ assert len(code_block) > 0
+ actual = code_block[0].text
+ expect = (
+ " def ruby?\n" +
+ " false\n" +
+ " end"
+ )
+ assert actual == expect
+
+
+@with_app('xml', testroot='directive-code')
+def test_code_block_dedent(app, status, warning):
+ app.builder.build(['dedent_code'])
+ et = ElementTree.parse(app.outdir / 'dedent_code.xml')
+ blocks = et.findall('./section/section/literal_block')
+
+ for i in range(5): # 0-4
+ actual = blocks[i].text
+ indent = " " * (4 - i)
+ expect = (
+ indent + "def ruby?\n" +
+ indent + " false\n" +
+ indent + "end"
+ )
+ assert (i, actual) == (i, expect)
+
+ assert blocks[5].text == '\n\n' # dedent: 1000
+
+
+@with_app('html', testroot='directive-code')
+def test_code_block_caption_html(app, status, warning):
+ app.builder.build(['caption'])
+ html = (app.outdir / 'caption.html').text(encoding='utf-8')
+ caption = (u'<div class="code-block-caption">'
+ u'<span class="caption-text">caption <em>test</em> rb'
+ u'</span><a class="headerlink" href="#id1" '
+ u'title="Permalink to this code">\xb6</a></div>')
+ assert caption in html
+
+
+@with_app('latex', testroot='directive-code')
+def test_code_block_caption_latex(app, status, warning):
+ app.builder.build_all()
+ latex = (app.outdir / 'Python.tex').text()
+ caption = '\\caption{caption \\emph{test} rb}'
+ assert caption in latex
+
+
+@with_app('xml', testroot='directive-code')
+def test_literal_include(app, status, warning):
+ app.builder.build(['index'])
+ et = ElementTree.parse(app.outdir / 'index.xml')
+ secs = et.findall('./section/section')
+ literal_include = secs[1].findall('literal_block')
+ literal_src = (app.srcdir / 'literal.inc').text(encoding='utf-8')
+ assert len(literal_include) > 0
+ actual = literal_include[0].text
+ assert actual == literal_src
+
+
+@with_app('xml', testroot='directive-code')
+def test_literal_include_dedent(app, status, warning):
+ literal_src = (app.srcdir / 'literal.inc').text(encoding='utf-8')
+ literal_lines = [l[4:] for l in literal_src.split('\n')[9:11]]
+
+ app.builder.build(['dedent'])
+ et = ElementTree.parse(app.outdir / 'dedent.xml')
+ blocks = et.findall('./section/section/literal_block')
+
+ for i in range(5): # 0-4
+ actual = blocks[i].text
+ indent = ' ' * (4 - i)
+ expect = '\n'.join(indent + l for l in literal_lines) + '\n'
+ assert (i, actual) == (i, expect)
+
+ assert blocks[5].text == '\n\n' # dedent: 1000
+
+
+@with_app('html', testroot='directive-code')
+def test_literal_include_linenos(app, status, warning):
+ app.builder.build(['linenos'])
+ html = (app.outdir / 'linenos.html').text()
+ linenos = (
+ '<td class="linenos"><div class="linenodiv"><pre>'
+ ' 1\n'
+ ' 2\n'
+ ' 3\n'
+ ' 4\n'
+ ' 5\n'
+ ' 6\n'
+ ' 7\n'
+ ' 8\n'
+ ' 9\n'
+ '10\n'
+ '11\n'
+ '12\n'
+ '13</pre></div></td>')
+ assert linenos in html
+
+
+@with_app('html', testroot='directive-code')
+def test_literal_include_lineno_start(app, status, warning):
+ app.builder.build(['lineno_start'])
+ html = (app.outdir / 'lineno_start.html').text()
+ linenos = (
+ '<td class="linenos"><div class="linenodiv"><pre>'
+ '200\n'
+ '201\n'
+ '202\n'
+ '203\n'
+ '204\n'
+ '205\n'
+ '206\n'
+ '207\n'
+ '208\n'
+ '209\n'
+ '210\n'
+ '211\n'
+ '212</pre></div></td>')
+ assert linenos in html
+
+
+@with_app('html', testroot='directive-code')
+def test_literal_include_lineno_match(app, status, warning):
+ app.builder.build(['lineno_match'])
+ html = (app.outdir / 'lineno_match.html').text()
+ pyobject = (
+ '<td class="linenos"><div class="linenodiv"><pre>'
+ ' 9\n'
+ '10\n'
+ '11</pre></div></td>')
+
+ assert pyobject in html
+
+ lines = (
+ '<td class="linenos"><div class="linenodiv"><pre>'
+ '6\n'
+ '7\n'
+ '8\n'
+ '9</pre></div></td>')
+ assert lines in html
+
+ start_after = (
+ '<td class="linenos"><div class="linenodiv"><pre>'
+ ' 9\n'
+ '10\n'
+ '11\n'
+ '12\n'
+ '13</pre></div></td>')
+ assert start_after in html
+
+
+@with_app('html', testroot='directive-code')
+def test_literalinclude_caption_html(app, status, warning):
+ app.builder.build('index')
+ html = (app.outdir / 'caption.html').text(encoding='utf-8')
+ caption = (u'<div class="code-block-caption">'
+ u'<span class="caption-text">caption <strong>test</strong> py'
+ u'</span><a class="headerlink" href="#id2" '
+ u'title="Permalink to this code">\xb6</a></div>')
+ assert caption in html
+
+
+@with_app('latex', testroot='directive-code')
+def test_literalinclude_caption_latex(app, status, warning):
+ app.builder.build('index')
+ latex = (app.outdir / 'Python.tex').text()
+ caption = '\\caption{caption \\textbf{test} py}'
+ assert caption in latex
diff --git a/tests/test_only_directive.py b/tests/test_directive_only.py
index 4717ff9f..0cf44663 100644
--- a/tests/test_only_directive.py
+++ b/tests/test_directive_only.py
@@ -13,15 +13,11 @@ import re
from docutils import nodes
-from util import with_app, test_roots
+from util import with_app
-def teardown_module():
- (test_roots / 'test-only-directive' / '_build').rmtree(True)
-
-
-@with_app(buildername='text', srcdir=(test_roots / 'test-only-directive'))
-def test_sectioning(app):
+@with_app('text', testroot='directive-only')
+def test_sectioning(app, status, warning):
def getsects(section):
if not isinstance(section, nodes.section):
@@ -53,8 +49,7 @@ def test_sectioning(app):
app.env.process_only_nodes(doctree, app.builder)
parts = [getsects(n)
- for n in filter(lambda n: isinstance(n, nodes.section),
- doctree.children)]
+ for n in [_n for _n in doctree.children if isinstance(_n, nodes.section)]]
for i, s in enumerate(parts):
testsects(str(i+1) + '.', s, 4)
assert len(parts) == 4, 'Expected 4 document level headings, got:\n%s' % \
diff --git a/tests/test_docutilsconf.py b/tests/test_docutilsconf.py
index 4aeaa56a..90fa5db3 100644
--- a/tests/test_docutilsconf.py
+++ b/tests/test_docutilsconf.py
@@ -9,49 +9,17 @@
: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
+
+from util import with_app, path, SkipTest
def regex_count(expr, result):
return len(re.findall(expr, result))
-@with_conf_app(buildername='html')
-def test_html_with_default_docutilsconf(app):
+@with_app('html', testroot='docutilsconf', freshenv=True, docutilsconf='')
+def test_html_with_default_docutilsconf(app, status, warning):
app.builder.build(['contents'])
result = (app.outdir / 'contents.html').text(encoding='utf-8')
@@ -61,13 +29,13 @@ def test_html_with_default_docutilsconf(app):
assert regex_count(r'<td class="option-group" colspan="2">', result) == 1
-@with_conf_app(buildername='html', docutilsconf=(
+@with_app('html', testroot='docutilsconf', freshenv=True, docutilsconf=(
'\n[html4css1 writer]'
'\noption-limit:1'
'\nfield-name-limit:1'
'\n')
)
-def test_html_with_docutilsconf(app):
+def test_html_with_docutilsconf(app, status, warning):
app.builder.build(['contents'])
result = (app.outdir / 'contents.html').text(encoding='utf-8')
@@ -77,41 +45,32 @@ def test_html_with_docutilsconf(app):
assert regex_count(r'<td class="option-group" colspan="2">', result) == 2
-@with_conf_app(buildername='html', warning=html_warnfile)
-def test_html(app):
+@with_app('html', testroot='docutilsconf')
+def test_html(app, status, warning):
app.builder.build(['contents'])
- assert html_warnfile.getvalue() == ''
+ assert warning.getvalue() == ''
-@with_conf_app(buildername='latex', warning=html_warnfile)
-def test_latex(app):
+@with_app('latex', testroot='docutilsconf')
+def test_latex(app, status, warning):
app.builder.build(['contents'])
- assert html_warnfile.getvalue() == ''
+ assert warning.getvalue() == ''
-@with_conf_app(buildername='man', warning=html_warnfile)
-def test_man(app):
+@with_app('man', testroot='docutilsconf')
+def test_man(app, status, warning):
app.builder.build(['contents'])
- assert html_warnfile.getvalue() == ''
+ assert warning.getvalue() == ''
-@with_conf_app(buildername='texinfo', warning=html_warnfile)
-def test_texinfo(app):
+@with_app('texinfo', testroot='docutilsconf')
+def test_texinfo(app, status, warning):
app.builder.build(['contents'])
-@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()
-
-
-@with_conf_app(buildername='html', srcdir='(empty)',
- docutilsconf='[general]\nsource_link=true\n')
-def test_docutils_source_link_with_nonascii_file(app):
+@with_app('html', testroot='docutilsconf',
+ docutilsconf='[general]\nsource_link=true\n')
+def test_docutils_source_link_with_nonascii_file(app, status, warning):
srcdir = path(app.srcdir)
mb_name = u'\u65e5\u672c\u8a9e'
try:
@@ -122,7 +81,4 @@ def test_docutils_source_link_with_nonascii_file(app):
'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_domain_cpp.py b/tests/test_domain_cpp.py
new file mode 100644
index 00000000..0b4219a5
--- /dev/null
+++ b/tests/test_domain_cpp.py
@@ -0,0 +1,127 @@
+# -*- coding: utf-8 -*-
+"""
+ test_domain_cpp
+ ~~~~~~~~~~~~~~~
+
+ Tests the C++ Domain
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from six import text_type
+
+from util import raises
+
+from sphinx.domains.cpp import DefinitionParser, DefinitionError
+
+def parse(name, string):
+ parser = DefinitionParser(string)
+ res = getattr(parser, "parse_" + name + "_object")()
+ if not parser.eof:
+ print("Parsing stopped at", parser.pos)
+ print(string)
+ print('-'*parser.pos + '^')
+ raise DefinitionError("")
+ return res
+
+def check(name, input, output=None):
+ # first a simple check of the AST
+ if output == None: output = input
+ ast = parse(name, input)
+ res = text_type(ast)
+ if res != output:
+ print("Input: ", text_type(input))
+ print("Result: ", res)
+ print("Expected: ", output)
+ raise DefinitionError("")
+ ast.describe_signature([], 'lastIsName', None)
+ ast.prefixedName = ast.name # otherwise the get_id fails, it would be set in handle_signarue
+ ast.get_id()
+ #print ".. %s:: %s" % (name, input)
+
+def test_type_definitions():
+ check("type", "public bool b", "bool b")
+ check("type", "bool A::b")
+ check("type", "bool *b")
+ check("type", "bool *const b")
+ check("type", "bool *volatile const b")
+ check("type", "bool *volatile const b")
+ check("type", "bool *volatile const *b")
+ check("type", "bool &b")
+ check("type", "bool b[]")
+ check("type", "std::pair<int, int> coord")
+ check("type", "long long int foo")
+ check("type", 'std::vector<std::pair<std::string, long long>> module::blah')
+ check("type", "std::function<void()> F")
+ check("type", "std::function<R(A1, A2, A3)> F")
+ check("type", "std::function<R(A1, A2, A3, As...)> F")
+ check("type", "MyContainer::const_iterator")
+ check("type", "public MyContainer::const_iterator", "MyContainer::const_iterator")
+
+ check('member', ' const std::string & name = 42', 'const std::string &name = 42')
+ check('member', ' const std::string & name', 'const std::string &name')
+ check('member', ' const std::string & name [ n ]', 'const std::string &name[n]')
+ check('member', 'const std::vector< unsigned int, long> &name', 'const std::vector<unsigned int, long> &name')
+ check('member', 'module::myclass foo[n]')
+
+ check('function', 'operator bool() const')
+ check('function', 'bool namespaced::theclass::method(arg1, arg2)')
+ x = 'std::vector<std::pair<std::string, int>> &module::test(register ' \
+ 'foo, bar, std::string baz = "foobar, blah, bleh") const = 0'
+ check('function', x)
+ check('function', 'explicit module::myclass::foo::foo()')
+ check('function', 'module::myclass::foo::~foo()')
+ check('function', 'int printf(const char *fmt, ...)')
+ check('function', 'int foo(const unsigned int j)')
+ check('function', 'int foo(const int *const ptr)')
+ check('function', 'module::myclass::operator std::vector<std::string>()')
+ check('function', 'void operator()(const boost::array<VertexID, 2> &v) const')
+ check('function', 'void operator()(const boost::array<VertexID, 2, "foo, bar"> &v) const')
+ check('function', 'MyClass::MyClass(MyClass::MyClass&&)')
+ check('function', 'constexpr int get_value()')
+ check('function', 'static constexpr int get_value()')
+ check('function', 'int get_value() const noexcept')
+ check('function', 'int get_value() const noexcept = delete')
+ check('function', 'MyClass::MyClass(MyClass::MyClass&&) = default')
+ check('function', 'virtual MyClass::a_virtual_function() const override')
+ check('function', 'A B() override')
+ check('function', 'A B() final')
+ check('function', 'A B() final override')
+ check('function', 'A B() override final', 'A B() final override')
+ check('function', 'MyClass::a_member_function() volatile')
+ check('function', 'MyClass::a_member_function() volatile const')
+ check('function', 'MyClass::a_member_function() &&')
+ check('function', 'MyClass::a_member_function() &')
+ check('function', 'MyClass::a_member_function() const &')
+ check('function', 'int main(int argc, char *argv[])')
+ check('function', 'MyClass &MyClass::operator++()')
+ check('function', 'MyClass::pointer MyClass::operator->()')
+
+ x = 'std::vector<std::pair<std::string, int>> &module::test(register ' \
+ 'foo, bar[n], std::string baz = "foobar, blah, bleh") const = 0'
+ check('function', x)
+ check('function', 'int foo(Foo f = Foo(double(), std::make_pair(int(2), double(3.4))))')
+ check('function', 'int foo(A a = x(a))')
+ raises(DefinitionError, parse, 'function', 'int foo(B b=x(a)')
+ raises(DefinitionError, parse, 'function', 'int foo)C c=x(a))')
+ raises(DefinitionError, parse, 'function', 'int foo(D d=x(a')
+ check('function', 'int foo(const A&... a)')
+ check('function', 'virtual void f()')
+
+def test_bases():
+ check('class', 'A')
+ check('class', 'A::B::C')
+ check('class', 'A : B')
+ check('class', 'A : private B', 'A : B')
+ check('class', 'A : public B')
+ check('class', 'A : B, C')
+ check('class', 'A : B, protected C, D')
+
+
+def test_operators():
+ check('function', 'void operator new [ ] ()', 'void operator new[]()')
+ check('function', 'void operator delete ()', 'void operator delete()')
+ check('function', 'void operator bool() const', 'void operator bool() const')
+ for op in '*-+=/%!':
+ check('function', 'void operator %s ()' % op, 'void operator%s()' % op)
diff --git a/tests/test_py_domain.py b/tests/test_domain_py.py
index 68634d83..1d0fcc5f 100644
--- a/tests/test_py_domain.py
+++ b/tests/test_domain_py.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
- test_py_domain
+ test_domain_py
~~~~~~~~~~~~~~
Tests the Python Domain
@@ -9,6 +9,8 @@
:license: BSD, see LICENSE for details.
"""
+from six import text_type
+
from sphinx import addnodes
from sphinx.domains.python import py_sig_re, _pseudo_parse_arglist
@@ -26,19 +28,19 @@ def parse(sig):
def test_function_signatures():
rv = parse('func(a=1) -> int object')
- assert unicode(rv) == u'a=1'
+ assert text_type(rv) == u'a=1'
rv = parse('func(a=1, [b=None])')
- assert unicode(rv) == u'a=1, [b=None]'
+ assert text_type(rv) == u'a=1, [b=None]'
rv = parse('func(a=1[, b=None])')
- assert unicode(rv) == u'a=1, [b=None]'
+ assert text_type(rv) == u'a=1, [b=None]'
rv = parse("compile(source : string, filename, symbol='file')")
- assert unicode(rv) == u"source : string, filename, symbol='file'"
+ assert text_type(rv) == u"source : string, filename, symbol='file'"
rv = parse('func(a=[], [b=None])')
- assert unicode(rv) == u'a=[], [b=None]'
+ assert text_type(rv) == u'a=[], [b=None]'
rv = parse('func(a=[][, b=None])')
- assert unicode(rv) == u'a=[], [b=None]'
+ assert text_type(rv) == u'a=[], [b=None]'
diff --git a/tests/test_rst_domain.py b/tests/test_domain_rst.py
index 9f70f5b1..9f70f5b1 100644
--- a/tests/test_rst_domain.py
+++ b/tests/test_domain_rst.py
diff --git a/tests/test_domain_std.py b/tests/test_domain_std.py
new file mode 100644
index 00000000..a1e5bdc1
--- /dev/null
+++ b/tests/test_domain_std.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+"""
+ test_domain_std
+ ~~~~~~~~~~~~~~~
+
+ Tests the std domain
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from docutils import nodes
+
+from sphinx.domains.std import StandardDomain
+from util import mock
+
+
+def test_process_doc_handle_figure_caption():
+ env = mock.Mock(domaindata={})
+ figure_node = nodes.figure(
+ '',
+ nodes.caption('caption text', 'caption text'),
+ )
+ document = mock.Mock(
+ nametypes={'testname': True},
+ nameids={'testname': 'testid'},
+ ids={'testid': figure_node},
+ )
+
+ domain = StandardDomain(env)
+ if 'testname' in domain.data['labels']:
+ del domain.data['labels']['testname']
+ domain.process_doc(env, 'testdoc', document)
+ assert 'testname' in domain.data['labels']
+ assert domain.data['labels']['testname'] == (
+ 'testdoc', 'testid', 'caption text')
+
+
+def test_process_doc_handle_image_parent_figure_caption():
+ env = mock.Mock(domaindata={})
+ img_node = nodes.image('', alt='image alt')
+ figure_node = nodes.figure(
+ '',
+ nodes.caption('caption text', 'caption text'),
+ img_node,
+ )
+ document = mock.Mock(
+ nametypes={'testname': True},
+ nameids={'testname': 'testid'},
+ ids={'testid': img_node},
+ )
+
+ domain = StandardDomain(env)
+ if 'testname' in domain.data['labels']:
+ del domain.data['labels']['testname']
+ domain.process_doc(env, 'testdoc', document)
+ assert 'testname' in domain.data['labels']
+ assert domain.data['labels']['testname'] == (
+ 'testdoc', 'testid', 'caption text')
+
+
+def test_process_doc_handle_table_title():
+ env = mock.Mock(domaindata={})
+ table_node = nodes.table(
+ '',
+ nodes.title('title text', 'title text'),
+ )
+ document = mock.Mock(
+ nametypes={'testname': True},
+ nameids={'testname': 'testid'},
+ ids={'testid': table_node},
+ )
+
+ domain = StandardDomain(env)
+ if 'testname' in domain.data['labels']:
+ del domain.data['labels']['testname']
+ domain.process_doc(env, 'testdoc', document)
+ assert 'testname' in domain.data['labels']
+ assert domain.data['labels']['testname'] == (
+ 'testdoc', 'testid', 'title text')
diff --git a/tests/test_env.py b/tests/test_environment.py
index c5a091cd..b5da325f 100644
--- a/tests/test_env.py
+++ b/tests/test_environment.py
@@ -8,11 +8,10 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-import os
-import sys
-import tempfile
-from util import TestApp, test_root, remove_unicode_literals, path
+from six import PY3
+
+from util import TestApp, remove_unicode_literals, path
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.builders.latex import LaTeXBuilder
@@ -20,34 +19,35 @@ from sphinx.builders.latex import LaTeXBuilder
app = env = None
warnings = []
+
def setup_module():
global app, env
- app = TestApp(srcdir='(temp)', freshenv=True)
+ app = TestApp(srcdir='root-envtest')
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)
+ updated = env.update(app.config, app.srcdir, app.doctreedir, app)
+ assert set(updated) == 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: '
@@ -59,7 +59,7 @@ def test_images():
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):
+ if PY3:
image_uri_message = remove_unicode_literals(image_uri_message)
assert image_uri_message in app._warning.content[-1]
assert set(htmlbuilder.images.keys()) == \
@@ -77,6 +77,7 @@ def test_images():
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
@@ -85,39 +86,33 @@ def test_second_update():
# 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)
+ updated = env.update(app.config, app.srcdir, app.doctreedir, app)
# "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 set(updated) == set(['contents', 'new', 'includes', 'images'])
assert 'autodoc' not in env.all_docs
assert 'autodoc' not in env.found_docs
-def test_record_dependency_on_multibyte_directory():
- app = None
- olddir = os.getcwd()
- try:
- tmproot = path(os.path.abspath(tempfile.mkdtemp()))
- tmpdir = tmproot / u'テスト'
- test_root.copytree(tmpdir)
- os.chdir(tmpdir)
- tmpdir = path(os.getcwd()) # for MacOSX; tmpdir is based on symlinks
-
- app = TestApp(srcdir=tmpdir, freshenv=True)
- (app.srcdir / 'test.txt').write_text('.. include:: test.inc')
- (app.srcdir / 'test.inc').write_text('hello sphinx')
- _, _, it = app.env.update(app.config, app.srcdir, app.doctreedir, app)
- list(it) # take all from iterator
- finally:
- tmproot.rmtree(ignore_errors=True)
- os.chdir(olddir)
- if app:
- app.cleanup()
+def test_env_read_docs():
+ """By default, docnames are read in alphanumeric order"""
+ def on_env_read_docs_1(app, env, docnames):
+ pass
+
+ app.connect('env-before-read-docs', on_env_read_docs_1)
+
+ read_docnames = env.update(app.config, app.srcdir, app.doctreedir, app)
+ assert len(read_docnames) > 2 and read_docnames == sorted(read_docnames)
+
+ def on_env_read_docs_2(app, env, docnames):
+ docnames.reverse()
+
+ app.connect('env-before-read-docs', on_env_read_docs_2)
+
+ read_docnames = env.update(app.config, app.srcdir, app.doctreedir, app)
+ reversed_read_docnames = sorted(read_docnames, reverse=True)
+ assert len(read_docnames) > 2 and read_docnames == reversed_read_docnames
def test_object_inventory():
diff --git a/tests/test_autosummary.py b/tests/test_ext_autosummary.py
index de26a054..363c11e9 100644
--- a/tests/test_autosummary.py
+++ b/tests/test_ext_autosummary.py
@@ -8,48 +8,24 @@
: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 six import iteritems, StringIO
from sphinx.ext.autosummary import mangle_signature
-from util import test_roots, TestApp
+from util import with_app
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 = {
+ 'testroot': '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():
@@ -71,17 +47,15 @@ def test_mangle_signature():
(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")
+ TEST = [[y.strip() for y in 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))
-@with_autosummary_app(buildername='html', warning=html_warnfile)
-def test_get_items_summary(app):
- app.builddir.rmtree(True)
-
+@with_app(buildername='html', **default_kw)
+def test_get_items_summary(app, status, warning):
# monkey-patch Autosummary.get_items so we can easily get access to it's
# results..
import sphinx.ext.autosummary
@@ -95,13 +69,17 @@ def test_get_items_summary(app):
autosummary_items[name] = result
return results
+ def handler(app, what, name, obj, options, lines):
+ assert isinstance(lines, list)
+ app.connect('autodoc-process-docstring', handler)
+
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()
+ html_warnings = warning.getvalue()
assert html_warnings == ''
expected_values = {
@@ -114,16 +92,6 @@ def test_get_items_summary(app):
'C.prop_attr2': 'This is a attribute docstring',
'C.C2': 'This is a nested inner class docstring',
}
- for key, expected in expected_values.iteritems():
+ for key, expected in iteritems(expected_values):
assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\
' expected %r' % (key, autosummary_items[key], expected)
-
-
-@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_coverage.py b/tests/test_ext_coverage.py
index e6747b0c..e59d42bc 100644
--- a/tests/test_coverage.py
+++ b/tests/test_ext_coverage.py
@@ -15,7 +15,7 @@ from util import with_app
@with_app(buildername='coverage')
-def test_build(app):
+def test_build(app, status, warning):
app.builder.build_all()
py_undoc = (app.outdir / 'python.txt').text()
@@ -38,7 +38,7 @@ def test_build(app):
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 list(undoc_c.values())[0] == set([('function', 'Py_SphinxTest')])
assert 'test_autodoc' in undoc_py
assert 'funcs' in undoc_py['test_autodoc']
diff --git a/tests/test_doctest.py b/tests/test_ext_doctest.py
index 2aab541b..002afff6 100644
--- a/tests/test_doctest.py
+++ b/tests/test_ext_doctest.py
@@ -9,27 +9,23 @@
:license: BSD, see LICENSE for details.
"""
-import sys
-import StringIO
-
from util import with_app
-
-status = StringIO.StringIO()
cleanup_called = 0
-@with_app(buildername='doctest', status=status)
-def test_build(app):
+
+@with_app(buildername='doctest', testroot='doctest')
+def test_build(app, status, warning):
global cleanup_called
cleanup_called = 0
app.builder.build_all()
if app.statuscode != 0:
- print >>sys.stderr, status.getvalue()
- assert False, 'failures in doctests'
+ assert False, 'failures in doctests:' + status.getvalue()
# 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_intersphinx.py b/tests/test_ext_intersphinx.py
index 8f0263b9..fb540668 100644
--- a/tests/test_intersphinx.py
+++ b/tests/test_ext_intersphinx.py
@@ -11,18 +11,15 @@
import zlib
import posixpath
-try:
- from io import BytesIO
-except ImportError:
- from cStringIO import StringIO as BytesIO
+from six import BytesIO
from docutils import nodes
from sphinx import addnodes
from sphinx.ext.intersphinx import read_inventory_v1, read_inventory_v2, \
- load_mappings, missing_reference
+ load_mappings, missing_reference
-from util import with_app, with_tempdir, write_file
+from util import with_app, with_tempdir
inventory_v1 = '''\
@@ -52,9 +49,9 @@ def test_read_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', '-')
+ ('foo', '1.0', '/util/foo.html#module-module', '-')
assert invdata['py:class']['module.cls'] == \
- ('foo', '1.0', '/util/foo.html#module.cls', '-')
+ ('foo', '1.0', '/util/foo.html#module.cls', '-')
def test_read_inventory_v2():
@@ -71,21 +68,21 @@ def test_read_inventory_v2():
assert len(invdata1['py:module']) == 2
assert invdata1['py:module']['module1'] == \
- ('foo', '2.0', '/util/foo.html#module-module1', 'Long Module desc')
+ ('foo', '2.0', '/util/foo.html#module-module1', 'Long Module desc')
assert invdata1['py:module']['module2'] == \
- ('foo', '2.0', '/util/foo.html#module-module2', '-')
+ ('foo', '2.0', '/util/foo.html#module-module2', '-')
assert invdata1['py:function']['module1.func'][2] == \
- '/util/sub/foo.html#module1.func'
+ '/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'
+ '/util/glossary.html#term-a-term'
-@with_app(confoverrides={'extensions': 'sphinx.ext.intersphinx'})
+@with_app()
@with_tempdir
-def test_missing_reference(tempdir, app):
+def test_missing_reference(tempdir, app, status, warning):
inv_file = tempdir / 'inventory'
- write_file(inv_file, inventory_v2)
+ inv_file.write_bytes(inventory_v2)
app.config.intersphinx_mapping = {
'http://docs.python.org/': inv_file,
'py3k': ('http://docs.python.org/py3k/', inv_file),
@@ -97,7 +94,7 @@ def test_missing_reference(tempdir, app):
inv = app.env.intersphinx_inventory
assert inv['py:module']['module2'] == \
- ('foo', '2.0', 'http://docs.python.org/foo.html#module-module2', '-')
+ ('foo', '2.0', 'http://docs.python.org/foo.html#module-module2', '-')
# create fake nodes and check referencing
@@ -157,15 +154,15 @@ def test_missing_reference(tempdir, app):
assert contnode[0].astext() == 'py3k:unknown'
-@with_app(confoverrides={'extensions': 'sphinx.ext.intersphinx'})
+@with_app()
@with_tempdir
-def test_load_mappings_warnings(tempdir, app):
+def test_load_mappings_warnings(tempdir, app, status, warning):
"""
load_mappings issues a warning if new-style mapping
identifiers are not alphanumeric
"""
inv_file = tempdir / 'inventory'
- write_file(inv_file, inventory_v2)
+ inv_file.write_bytes(inventory_v2)
app.config.intersphinx_mapping = {
'http://docs.python.org/': inv_file,
'py3k': ('http://docs.python.org/py3k/', inv_file),
@@ -177,4 +174,4 @@ def test_load_mappings_warnings(tempdir, app):
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
+ assert warning.getvalue().count('\n') == 2
diff --git a/tests/test_ext_napoleon.py b/tests/test_ext_napoleon.py
new file mode 100644
index 00000000..e2790d38
--- /dev/null
+++ b/tests/test_ext_napoleon.py
@@ -0,0 +1,199 @@
+# -*- coding: utf-8 -*-
+"""
+ test_napoleon
+ ~~~~~~~~~~~~~
+
+ Tests for :mod:`sphinx.ext.napoleon.__init__` module.
+
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from collections import namedtuple
+from unittest import TestCase
+
+from sphinx.application import Sphinx
+from sphinx.ext.napoleon import (_process_docstring, _skip_member, Config,
+ setup)
+from util import mock
+
+
+def _private_doc():
+ """module._private_doc.DOCSTRING"""
+ pass
+
+
+def _private_undoc():
+ pass
+
+
+def __special_doc__():
+ """module.__special_doc__.DOCSTRING"""
+ pass
+
+
+def __special_undoc__():
+ pass
+
+
+class SampleClass(object):
+ def _private_doc(self):
+ """SampleClass._private_doc.DOCSTRING"""
+ pass
+
+ def _private_undoc(self):
+ pass
+
+ def __special_doc__(self):
+ """SampleClass.__special_doc__.DOCSTRING"""
+ pass
+
+ def __special_undoc__(self):
+ pass
+
+
+class SampleError(Exception):
+ def _private_doc(self):
+ """SampleError._private_doc.DOCSTRING"""
+ pass
+
+ def _private_undoc(self):
+ pass
+
+ def __special_doc__(self):
+ """SampleError.__special_doc__.DOCSTRING"""
+ pass
+
+ def __special_undoc__(self):
+ pass
+
+SampleNamedTuple = namedtuple('SampleNamedTuple', 'user_id block_type def_id')
+
+
+class ProcessDocstringTest(TestCase):
+ def test_modify_in_place(self):
+ lines = ['Summary line.',
+ '',
+ 'Args:',
+ ' arg1: arg1 description']
+ app = mock.Mock()
+ app.config = Config()
+ _process_docstring(app, 'class', 'SampleClass', SampleClass,
+ mock.Mock(), lines)
+
+ expected = ['Summary line.',
+ '',
+ ':param arg1: arg1 description',
+ '']
+ self.assertEqual(expected, lines)
+
+
+class SetupTest(TestCase):
+ def test_unknown_app_type(self):
+ setup(object())
+
+ def test_add_config_values(self):
+ app = mock.Mock(Sphinx)
+ setup(app)
+ for name, (default, rebuild) in Config._config_values.items():
+ has_config = False
+ for method_name, args, kwargs in app.method_calls:
+ if(method_name == 'add_config_value' and
+ args[0] == name):
+ has_config = True
+ if not has_config:
+ self.fail('Config value was not added to app %s' % name)
+
+ has_process_docstring = False
+ has_skip_member = False
+ for method_name, args, kwargs in app.method_calls:
+ if method_name == 'connect':
+ if(args[0] == 'autodoc-process-docstring' and
+ args[1] == _process_docstring):
+ has_process_docstring = True
+ elif(args[0] == 'autodoc-skip-member' and
+ args[1] == _skip_member):
+ has_skip_member = True
+ if not has_process_docstring:
+ self.fail('autodoc-process-docstring never connected')
+ if not has_skip_member:
+ self.fail('autodoc-skip-member never connected')
+
+
+class SkipMemberTest(TestCase):
+ def assertSkip(self, what, member, obj, expect_skip, config_name):
+ skip = 'default skip'
+ app = mock.Mock()
+ app.config = Config()
+ setattr(app.config, config_name, True)
+ if expect_skip:
+ self.assertEqual(skip, _skip_member(app, what, member, obj, skip,
+ mock.Mock()))
+ else:
+ self.assertFalse(_skip_member(app, what, member, obj, skip,
+ mock.Mock()))
+ setattr(app.config, config_name, False)
+ self.assertEqual(skip, _skip_member(app, what, member, obj, skip,
+ mock.Mock()))
+
+ def test_namedtuple(self):
+ self.assertSkip('class', '_asdict',
+ SampleNamedTuple._asdict, False,
+ 'napoleon_include_private_with_doc')
+
+ def test_class_private_doc(self):
+ self.assertSkip('class', '_private_doc',
+ SampleClass._private_doc, False,
+ 'napoleon_include_private_with_doc')
+
+ def test_class_private_undoc(self):
+ self.assertSkip('class', '_private_undoc',
+ SampleClass._private_undoc, True,
+ 'napoleon_include_private_with_doc')
+
+ def test_class_special_doc(self):
+ self.assertSkip('class', '__special_doc__',
+ SampleClass.__special_doc__, False,
+ 'napoleon_include_special_with_doc')
+
+ def test_class_special_undoc(self):
+ self.assertSkip('class', '__special_undoc__',
+ SampleClass.__special_undoc__, True,
+ 'napoleon_include_special_with_doc')
+
+ def test_exception_private_doc(self):
+ self.assertSkip('exception', '_private_doc',
+ SampleError._private_doc, False,
+ 'napoleon_include_private_with_doc')
+
+ def test_exception_private_undoc(self):
+ self.assertSkip('exception', '_private_undoc',
+ SampleError._private_undoc, True,
+ 'napoleon_include_private_with_doc')
+
+ def test_exception_special_doc(self):
+ self.assertSkip('exception', '__special_doc__',
+ SampleError.__special_doc__, False,
+ 'napoleon_include_special_with_doc')
+
+ def test_exception_special_undoc(self):
+ self.assertSkip('exception', '__special_undoc__',
+ SampleError.__special_undoc__, True,
+ 'napoleon_include_special_with_doc')
+
+ def test_module_private_doc(self):
+ self.assertSkip('module', '_private_doc', _private_doc, False,
+ 'napoleon_include_private_with_doc')
+
+ def test_module_private_undoc(self):
+ self.assertSkip('module', '_private_undoc', _private_undoc, True,
+ 'napoleon_include_private_with_doc')
+
+ def test_module_special_doc(self):
+ self.assertSkip('module', '__special_doc__', __special_doc__, False,
+ 'napoleon_include_special_with_doc')
+
+ def test_module_special_undoc(self):
+ self.assertSkip('module', '__special_undoc__', __special_undoc__, True,
+ 'napoleon_include_special_with_doc')
diff --git a/tests/test_ext_napoleon_docstring.py b/tests/test_ext_napoleon_docstring.py
new file mode 100644
index 00000000..3b5c4fc7
--- /dev/null
+++ b/tests/test_ext_napoleon_docstring.py
@@ -0,0 +1,442 @@
+# -*- coding: utf-8 -*-
+"""
+ test_napoleon_docstring
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests for :mod:`sphinx.ext.napoleon.docstring` module.
+
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import textwrap
+from unittest import TestCase
+
+from sphinx.ext.napoleon import Config
+from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring
+from util import mock
+
+
+class BaseDocstringTest(TestCase):
+ pass
+
+
+class GoogleDocstringTest(BaseDocstringTest):
+ docstrings = [(
+ """Single line summary""",
+ """Single line summary"""
+ ), (
+ """
+ Single line summary
+
+ Extended description
+
+ """,
+ """
+ Single line summary
+
+ Extended description
+ """
+ ), (
+ """
+ Single line summary
+
+ Args:
+ arg1(str):Extended
+ description of arg1
+ """,
+ """
+ Single line summary
+
+ :Parameters: **arg1** (*str*) --
+ Extended
+ description of arg1"""
+ ), (
+ """
+ Single line summary
+
+ Args:
+ arg1(str):Extended
+ description of arg1
+ arg2 ( int ) : Extended
+ description of arg2
+
+ Keyword Args:
+ kwarg1(str):Extended
+ description of kwarg1
+ kwarg2 ( int ) : Extended
+ description of kwarg2""",
+ """
+ Single line summary
+
+ :Parameters: * **arg1** (*str*) --
+ Extended
+ description of arg1
+ * **arg2** (*int*) --
+ Extended
+ description of arg2
+
+ :Keyword Arguments: * **kwarg1** (*str*) --
+ Extended
+ description of kwarg1
+ * **kwarg2** (*int*) --
+ Extended
+ description of kwarg2"""
+ ), (
+ """
+ Single line summary
+
+ Arguments:
+ arg1(str):Extended
+ description of arg1
+ arg2 ( int ) : Extended
+ description of arg2
+
+ Keyword Arguments:
+ kwarg1(str):Extended
+ description of kwarg1
+ kwarg2 ( int ) : Extended
+ description of kwarg2""",
+ """
+ Single line summary
+
+ :Parameters: * **arg1** (*str*) --
+ Extended
+ description of arg1
+ * **arg2** (*int*) --
+ Extended
+ description of arg2
+
+ :Keyword Arguments: * **kwarg1** (*str*) --
+ Extended
+ description of kwarg1
+ * **kwarg2** (*int*) --
+ Extended
+ description of kwarg2"""
+ ), (
+ """
+ Single line summary
+
+ Return:
+ str:Extended
+ description of return value
+ """,
+ """
+ Single line summary
+
+ :returns: *str* --
+ Extended
+ description of return value"""
+ ), (
+ """
+ Single line summary
+
+ Returns:
+ str:Extended
+ description of return value
+ """,
+ """
+ Single line summary
+
+ :returns: *str* --
+ Extended
+ description of return value"""
+ ), (
+ """
+ Single line summary
+
+ Returns:
+ Extended
+ description of return value
+ """,
+ """
+ Single line summary
+
+ :returns: Extended
+ description of return value"""
+ )]
+
+ def test_docstrings(self):
+ config = Config(napoleon_use_param=False, napoleon_use_rtype=False)
+ for docstring, expected in self.docstrings:
+ actual = str(GoogleDocstring(textwrap.dedent(docstring), config))
+ expected = textwrap.dedent(expected)
+ self.assertEqual(expected, actual)
+
+ def test_parameters_with_class_reference(self):
+ docstring = """\
+Construct a new XBlock.
+
+This class should only be used by runtimes.
+
+Arguments:
+ runtime (:class:`Runtime`): Use it to access the environment.
+ It is available in XBlock code as ``self.runtime``.
+
+ field_data (:class:`FieldData`): Interface used by the XBlock
+ fields to access their data from wherever it is persisted.
+
+ scope_ids (:class:`ScopeIds`): Identifiers needed to resolve scopes.
+
+"""
+
+ actual = str(GoogleDocstring(docstring))
+ expected = """\
+Construct a new XBlock.
+
+This class should only be used by runtimes.
+
+:param runtime: Use it to access the environment.
+ It is available in XBlock code as ``self.runtime``.
+
+:type runtime: :class:`Runtime`
+:param field_data: Interface used by the XBlock
+ fields to access their data from wherever it is persisted.
+
+:type field_data: :class:`FieldData`
+:param scope_ids: Identifiers needed to resolve scopes.
+
+:type scope_ids: :class:`ScopeIds`
+"""
+ self.assertEqual(expected, actual)
+
+ def test_attributes_with_class_reference(self):
+ docstring = """\
+Attributes:
+ in_attr(:class:`numpy.ndarray`): super-dooper attribute
+"""
+
+ actual = str(GoogleDocstring(docstring))
+ expected = """\
+.. attribute:: in_attr
+
+ :class:`numpy.ndarray`
+
+ super-dooper attribute
+"""
+ self.assertEqual(expected, actual)
+
+ docstring = """\
+Attributes:
+ in_attr(numpy.ndarray): super-dooper attribute
+"""
+
+ actual = str(GoogleDocstring(docstring))
+ expected = """\
+.. attribute:: in_attr
+
+ *numpy.ndarray*
+
+ super-dooper attribute
+"""
+ self.assertEqual(expected, actual)
+
+
+class NumpyDocstringTest(BaseDocstringTest):
+ docstrings = [(
+ """Single line summary""",
+ """Single line summary"""
+ ), (
+ """
+ Single line summary
+
+ Extended description
+
+ """,
+ """
+ Single line summary
+
+ Extended description
+ """
+ ), (
+ """
+ Single line summary
+
+ Parameters
+ ----------
+ arg1:str
+ Extended
+ description of arg1
+ """,
+ """
+ Single line summary
+
+ :Parameters: **arg1** (*str*) --
+ Extended
+ description of arg1"""
+ ), (
+ """
+ Single line summary
+
+ Parameters
+ ----------
+ arg1:str
+ Extended
+ description of arg1
+ arg2 : int
+ Extended
+ description of arg2
+
+ Keyword Arguments
+ -----------------
+ kwarg1:str
+ Extended
+ description of kwarg1
+ kwarg2 : int
+ Extended
+ description of kwarg2
+ """,
+ """
+ Single line summary
+
+ :Parameters: * **arg1** (*str*) --
+ Extended
+ description of arg1
+ * **arg2** (*int*) --
+ Extended
+ description of arg2
+
+ :Keyword Arguments: * **kwarg1** (*str*) --
+ Extended
+ description of kwarg1
+ * **kwarg2** (*int*) --
+ Extended
+ description of kwarg2"""
+ ), (
+ """
+ Single line summary
+
+ Return
+ ------
+ str
+ Extended
+ description of return value
+ """,
+ """
+ Single line summary
+
+ :returns: *str* --
+ Extended
+ description of return value"""
+ ), (
+ """
+ Single line summary
+
+ Returns
+ -------
+ str
+ Extended
+ description of return value
+ """,
+ """
+ Single line summary
+
+ :returns: *str* --
+ Extended
+ description of return value"""
+ )]
+
+ def test_docstrings(self):
+ config = Config(napoleon_use_param=False, napoleon_use_rtype=False)
+ for docstring, expected in self.docstrings:
+ actual = str(NumpyDocstring(textwrap.dedent(docstring), config))
+ expected = textwrap.dedent(expected)
+ self.assertEqual(expected, actual)
+
+ def test_parameters_with_class_reference(self):
+ docstring = """\
+Parameters
+----------
+param1 : :class:`MyClass <name.space.MyClass>` instance
+
+"""
+
+ config = Config(napoleon_use_param=False)
+ actual = str(NumpyDocstring(docstring, config))
+ expected = """\
+:Parameters: **param1** (:class:`MyClass <name.space.MyClass>` instance)
+"""
+ self.assertEqual(expected, actual)
+
+ config = Config(napoleon_use_param=True)
+ actual = str(NumpyDocstring(docstring, config))
+ expected = """\
+
+:type param1: :class:`MyClass <name.space.MyClass>` instance
+"""
+ self.assertEqual(expected, actual)
+
+ def test_parameters_without_class_reference(self):
+ docstring = """\
+Parameters
+----------
+param1 : MyClass instance
+
+"""
+
+ config = Config(napoleon_use_param=False)
+ actual = str(NumpyDocstring(docstring, config))
+ expected = """\
+:Parameters: **param1** (*MyClass instance*)
+"""
+ self.assertEqual(expected, actual)
+
+ config = Config(napoleon_use_param=True)
+ actual = str(NumpyDocstring(textwrap.dedent(docstring), config))
+ expected = """\
+
+:type param1: MyClass instance
+"""
+ self.assertEqual(expected, actual)
+
+ def test_see_also_refs(self):
+ docstring = """\
+numpy.multivariate_normal(mean, cov, shape=None, spam=None)
+
+See Also
+--------
+some, other, funcs
+otherfunc : relationship
+
+"""
+
+ actual = str(NumpyDocstring(docstring))
+
+ expected = """\
+numpy.multivariate_normal(mean, cov, shape=None, spam=None)
+
+.. seealso::
+
+ :obj:`some`, :obj:`other`, :obj:`funcs`
+ \n\
+ :obj:`otherfunc`
+ relationship
+"""
+ self.assertEqual(expected, actual)
+
+ docstring = """\
+numpy.multivariate_normal(mean, cov, shape=None, spam=None)
+
+See Also
+--------
+some, other, funcs
+otherfunc : relationship
+
+"""
+
+ config = Config()
+ app = mock.Mock()
+ actual = str(NumpyDocstring(docstring, config, app, "method"))
+
+ expected = """\
+numpy.multivariate_normal(mean, cov, shape=None, spam=None)
+
+.. seealso::
+
+ :meth:`some`, :meth:`other`, :meth:`funcs`
+ \n\
+ :meth:`otherfunc`
+ relationship
+"""
+ self.assertEqual(expected, actual)
diff --git a/tests/test_ext_napoleon_iterators.py b/tests/test_ext_napoleon_iterators.py
new file mode 100644
index 00000000..320047e5
--- /dev/null
+++ b/tests/test_ext_napoleon_iterators.py
@@ -0,0 +1,346 @@
+# -*- coding: utf-8 -*-
+"""
+ test_napoleon_iterators
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests for :mod:`sphinx.ext.napoleon.iterators` module.
+
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from sphinx.ext.napoleon.iterators import peek_iter, modify_iter
+from unittest import TestCase
+
+
+class BaseIteratorsTest(TestCase):
+ def assertEqualTwice(self, expected, func, *args):
+ self.assertEqual(expected, func(*args))
+ self.assertEqual(expected, func(*args))
+
+ def assertFalseTwice(self, func, *args):
+ self.assertFalse(func(*args))
+ self.assertFalse(func(*args))
+
+ def assertNext(self, it, expected, is_last):
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(expected, it.peek)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(expected, it.peek)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqual(expected, next(it))
+ if is_last:
+ self.assertFalseTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next)
+ else:
+ self.assertTrueTwice(it.has_next)
+
+ def assertRaisesTwice(self, exc, func, *args):
+ self.assertRaises(exc, func, *args)
+ self.assertRaises(exc, func, *args)
+
+ def assertTrueTwice(self, func, *args):
+ self.assertTrue(func(*args))
+ self.assertTrue(func(*args))
+
+
+class PeekIterTest(BaseIteratorsTest):
+ def test_init_with_sentinel(self):
+ a = iter(['1', '2', 'DONE'])
+ sentinel = 'DONE'
+ self.assertRaises(TypeError, peek_iter, a, sentinel)
+
+ def get_next():
+ return next(a)
+ it = peek_iter(get_next, sentinel)
+ self.assertEqual(it.sentinel, sentinel)
+ self.assertNext(it, '1', is_last=False)
+ self.assertNext(it, '2', is_last=True)
+
+ def test_iter(self):
+ a = ['1', '2', '3']
+ it = peek_iter(a)
+ self.assertTrue(it is it.__iter__())
+
+ a = []
+ b = [i for i in peek_iter(a)]
+ self.assertEqual([], b)
+
+ a = ['1']
+ b = [i for i in peek_iter(a)]
+ self.assertEqual(['1'], b)
+
+ a = ['1', '2']
+ b = [i for i in peek_iter(a)]
+ self.assertEqual(['1', '2'], b)
+
+ a = ['1', '2', '3']
+ b = [i for i in peek_iter(a)]
+ self.assertEqual(['1', '2', '3'], b)
+
+ def test_next_with_multi(self):
+ a = []
+ it = peek_iter(a)
+ self.assertFalseTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next, 2)
+
+ a = ['1']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next, 2)
+ self.assertTrueTwice(it.has_next)
+
+ a = ['1', '2']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqual(['1', '2'], it.next(2))
+ self.assertFalseTwice(it.has_next)
+
+ a = ['1', '2', '3']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqual(['1', '2'], it.next(2))
+ self.assertTrueTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next, 2)
+ self.assertTrueTwice(it.has_next)
+
+ a = ['1', '2', '3', '4']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqual(['1', '2'], it.next(2))
+ self.assertTrueTwice(it.has_next)
+ self.assertEqual(['3', '4'], it.next(2))
+ self.assertFalseTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next, 2)
+ self.assertFalseTwice(it.has_next)
+
+ def test_next_with_none(self):
+ a = []
+ it = peek_iter(a)
+ self.assertFalseTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next)
+ self.assertFalseTwice(it.has_next)
+
+ a = ['1']
+ it = peek_iter(a)
+ self.assertEqual('1', it.__next__())
+
+ a = ['1']
+ it = peek_iter(a)
+ self.assertNext(it, '1', is_last=True)
+
+ a = ['1', '2']
+ it = peek_iter(a)
+ self.assertNext(it, '1', is_last=False)
+ self.assertNext(it, '2', is_last=True)
+
+ a = ['1', '2', '3']
+ it = peek_iter(a)
+ self.assertNext(it, '1', is_last=False)
+ self.assertNext(it, '2', is_last=False)
+ self.assertNext(it, '3', is_last=True)
+
+ def test_next_with_one(self):
+ a = []
+ it = peek_iter(a)
+ self.assertFalseTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next, 1)
+
+ a = ['1']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqual(['1'], it.next(1))
+ self.assertFalseTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next, 1)
+
+ a = ['1', '2']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqual(['1'], it.next(1))
+ self.assertTrueTwice(it.has_next)
+ self.assertEqual(['2'], it.next(1))
+ self.assertFalseTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next, 1)
+
+ def test_next_with_zero(self):
+ a = []
+ it = peek_iter(a)
+ self.assertFalseTwice(it.has_next)
+ self.assertRaisesTwice(StopIteration, it.next, 0)
+
+ a = ['1']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice([], it.next, 0)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice([], it.next, 0)
+
+ a = ['1', '2']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice([], it.next, 0)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice([], it.next, 0)
+
+ def test_peek_with_multi(self):
+ a = []
+ it = peek_iter(a)
+ self.assertFalseTwice(it.has_next)
+ self.assertEqualTwice([it.sentinel, it.sentinel], it.peek, 2)
+ self.assertFalseTwice(it.has_next)
+
+ a = ['1']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1', it.sentinel], it.peek, 2)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1', it.sentinel, it.sentinel], it.peek, 3)
+ self.assertTrueTwice(it.has_next)
+
+ a = ['1', '2']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1', '2'], it.peek, 2)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1', '2', it.sentinel], it.peek, 3)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1', '2', it.sentinel, it.sentinel], it.peek, 4)
+ self.assertTrueTwice(it.has_next)
+
+ a = ['1', '2', '3']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1', '2'], it.peek, 2)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1', '2', '3'], it.peek, 3)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1', '2', '3', it.sentinel], it.peek, 4)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqual('1', next(it))
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['2', '3'], it.peek, 2)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['2', '3', it.sentinel], it.peek, 3)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['2', '3', it.sentinel, it.sentinel], it.peek, 4)
+ self.assertTrueTwice(it.has_next)
+
+ def test_peek_with_none(self):
+ a = []
+ it = peek_iter(a)
+ self.assertFalseTwice(it.has_next)
+ self.assertEqualTwice(it.sentinel, it.peek)
+ self.assertFalseTwice(it.has_next)
+
+ a = ['1']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice('1', it.peek)
+ self.assertEqual('1', next(it))
+ self.assertFalseTwice(it.has_next)
+ self.assertEqualTwice(it.sentinel, it.peek)
+ self.assertFalseTwice(it.has_next)
+
+ a = ['1', '2']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice('1', it.peek)
+ self.assertEqual('1', next(it))
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice('2', it.peek)
+ self.assertEqual('2', next(it))
+ self.assertFalseTwice(it.has_next)
+ self.assertEqualTwice(it.sentinel, it.peek)
+ self.assertFalseTwice(it.has_next)
+
+ def test_peek_with_one(self):
+ a = []
+ it = peek_iter(a)
+ self.assertFalseTwice(it.has_next)
+ self.assertEqualTwice([it.sentinel], it.peek, 1)
+ self.assertFalseTwice(it.has_next)
+
+ a = ['1']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1'], it.peek, 1)
+ self.assertEqual('1', next(it))
+ self.assertFalseTwice(it.has_next)
+ self.assertEqualTwice([it.sentinel], it.peek, 1)
+ self.assertFalseTwice(it.has_next)
+
+ a = ['1', '2']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['1'], it.peek, 1)
+ self.assertEqual('1', next(it))
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice(['2'], it.peek, 1)
+ self.assertEqual('2', next(it))
+ self.assertFalseTwice(it.has_next)
+ self.assertEqualTwice([it.sentinel], it.peek, 1)
+ self.assertFalseTwice(it.has_next)
+
+ def test_peek_with_zero(self):
+ a = []
+ it = peek_iter(a)
+ self.assertFalseTwice(it.has_next)
+ self.assertEqualTwice([], it.peek, 0)
+
+ a = ['1']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice([], it.peek, 0)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice([], it.peek, 0)
+
+ a = ['1', '2']
+ it = peek_iter(a)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice([], it.peek, 0)
+ self.assertTrueTwice(it.has_next)
+ self.assertEqualTwice([], it.peek, 0)
+
+
+class ModifyIterTest(BaseIteratorsTest):
+ def test_init_with_sentinel_args(self):
+ a = iter(['1', '2', '3', 'DONE'])
+ sentinel = 'DONE'
+
+ def get_next():
+ return next(a)
+ it = modify_iter(get_next, sentinel, int)
+ expected = [1, 2, 3]
+ self.assertEqual(expected, [i for i in it])
+
+ def test_init_with_sentinel_kwargs(self):
+ a = iter([1, 2, 3, 4])
+ sentinel = 4
+
+ def get_next():
+ return next(a)
+ it = modify_iter(get_next, sentinel, modifier=str)
+ expected = ['1', '2', '3']
+ self.assertEqual(expected, [i for i in it])
+
+ def test_modifier_default(self):
+ a = ['', ' ', ' a ', 'b ', ' c', ' ', '']
+ it = modify_iter(a)
+ expected = ['', ' ', ' a ', 'b ', ' c', ' ', '']
+ self.assertEqual(expected, [i for i in it])
+
+ def test_modifier_not_callable(self):
+ self.assertRaises(TypeError, modify_iter, [1], modifier='not_callable')
+
+ def test_modifier_rstrip(self):
+ a = ['', ' ', ' a ', 'b ', ' c', ' ', '']
+ it = modify_iter(a, modifier=lambda s: s.rstrip())
+ expected = ['', '', ' a', 'b', ' c', '', '']
+ self.assertEqual(expected, [i for i in it])
+
+ def test_modifier_rstrip_unicode(self):
+ a = [u'', u' ', u' a ', u'b ', u' c', u' ', u'']
+ it = modify_iter(a, modifier=lambda s: s.rstrip())
+ expected = [u'', u'', u' a', u'b', u' c', u'', u'']
+ self.assertEqual(expected, [i for i in it])
diff --git a/tests/test_ext_viewcode.py b/tests/test_ext_viewcode.py
new file mode 100644
index 00000000..fb24f765
--- /dev/null
+++ b/tests/test_ext_viewcode.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+"""
+ test_ext_viewcode
+ ~~~~~~~~~~~~~~~~~
+
+ Test sphinx.ext.viewcode extension.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from util import with_app
+
+
+@with_app(testroot='ext-viewcode')
+def test_viewcode(app, status, warning):
+ app.builder.build_all()
+
+ warnings = re.sub(r'\\+', '/', warning.getvalue())
+ assert re.findall(
+ r"index.rst:\d+: WARNING: Object named 'func1' not found in include " +
+ r"file .*/spam/__init__.py'",
+ warnings
+ )
+
+ result = (app.outdir / 'index.html').text(encoding='utf-8')
+ assert result.count('href="_modules/spam/mod1.html#func1"') == 2
+ assert result.count('href="_modules/spam/mod2.html#func2"') == 2
+ assert result.count('href="_modules/spam/mod1.html#Class1"') == 2
+ assert result.count('href="_modules/spam/mod2.html#Class2"') == 2
+
+
+@with_app(testroot='ext-viewcode', tags=['test_linkcode'])
+def test_linkcode(app, status, warning):
+ app.builder.build(['objects'])
+
+ 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_footnote.py b/tests/test_footnote.py
deleted file mode 100644
index 964bb3e7..00000000
--- a/tests/test_footnote.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# -*- 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)
-
-
-@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
index b4e5149f..5044ab0e 100644
--- a/tests/test_highlighting.py
+++ b/tests/test_highlighting.py
@@ -15,12 +15,7 @@ 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')
+from util import with_app
class MyLexer(RegexLexer):
@@ -46,13 +41,14 @@ class ComplainOnUnhighlighted(PygmentsBridge):
@with_app()
-def test_add_lexer(app):
+def test_add_lexer(app, status, warning):
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 = [
@@ -60,11 +56,12 @@ def test_detect_interactive():
>>> 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:
@@ -74,6 +71,7 @@ def test_set_formatter():
finally:
PygmentsBridge.html_formatter = HtmlFormatter
+
def test_trim_doctest_flags():
PygmentsBridge.html_formatter = MyFormatter
try:
diff --git a/tests/test_i18n.py b/tests/test_i18n.py
index 06f6b28b..8144663c 100644
--- a/tests/test_i18n.py
+++ b/tests/test_i18n.py
@@ -13,5 +13,5 @@ from util import with_app
@with_app(confoverrides={'language': 'de'})
-def test_i18n(app):
+def test_i18n(app, status, warning):
app.builder.build_all()
diff --git a/tests/test_intl.py b/tests/test_intl.py
index ca0273c8..69437c1a 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -9,75 +9,70 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
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 nose.tools import assert_equal
+from six import string_types
-from util import test_roots, path, with_app, SkipTest
+from util import tempdir, rootdir, path, gen_with_app, SkipTest, \
+ assert_re_search, assert_not_re_search, assert_in, assert_not_in, \
+ assert_startswith
-warnfile = StringIO()
-root = test_roots / 'test-intl'
-doctreedir = root / '_build' / 'doctree'
+root = tempdir / 'test-intl'
-def with_intl_app(*args, **kw):
+def gen_with_intl_app(*args, **kw):
default_kw = {
- 'srcdir': root,
- 'doctreedir': doctreedir,
+ 'testroot': 'intl',
'confoverrides': {
'language': 'xx', 'locale_dirs': ['.'],
'gettext_compact': False,
},
}
default_kw.update(kw)
- return with_app(*args, **default_kw)
+ return gen_with_app(*args, **default_kw)
def setup_module():
+ if not root.exists():
+ (rootdir / 'roots' / 'test-intl').copytree(root)
# 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')
+ os.path.relpath(po[:-3], root) + '.mo')
if not mo.parent.exists():
mo.parent.makedirs()
try:
p = Popen(['msgfmt', po, '-o', mo],
- stdout=PIPE, stderr=PIPE)
+ 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
+ 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
+ # for compatibility to Python-2.6
tag = self.tag
- if not isinstance(tag, basestring) and tag is not None:
+ if not isinstance(tag, string_types) and tag is not None:
return
if self.text:
yield self.text
@@ -86,7 +81,7 @@ def elem_gettexts(elem):
yield s
if e.tail:
yield e.tail
- return filter(None, [s.strip() for s in itertext(elem)])
+ return [_f for _f in [s.strip() for s in itertext(elem)] if _f]
def elem_getref(elem):
@@ -98,132 +93,45 @@ def assert_elem(elem, texts=None, refs=None, names=None):
_texts = elem_gettexts(elem)
assert _texts == texts
if refs is not None:
- _refs = map(elem_getref, elem.findall('reference'))
+ _refs = [elem_getref(x) for x in elem.findall('reference')]
assert _refs == refs
if names is not None:
_names = elem.attrib.get('names').split()
assert _names == names
-@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
-
+@gen_with_intl_app('text', freshenv=True)
+def test_text_builder(app, status, warning):
+ app.builder.build_all()
-@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")
+ # --- warnings in translation
+ warnings = warning.getvalue().replace(os.sep, '/')
+ warning_expr = u'.*/warnings.txt:4: ' \
+ u'WARNING: Inline literal start-string without end-string.\n'
+ yield assert_re_search, warning_expr, warnings
-@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")
+ yield assert_equal, result, expect
- 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)
-
-
-@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
-
-
-@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)
-
-
-@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
+ # --- simple translation; check title underlines
+ 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")
+ yield assert_equal, result, expect
-@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')
+ # --- check translation in subdirs
- # regression test for fix #1363
- para0 = secs[0].findall('paragraph')
- assert_elem(
- para0[0],
- texts=['SEE THIS DECORATOR:', 'sensitive_variables()', '.'],
- refs=['sensitive.sensitive_variables'])
+ result = (app.outdir / 'subdir' / 'contents.txt').text(encoding='utf-8')
+ yield assert_startswith, result, u"\nsubdir contents\n***************\n"
+ # --- check warnings for inconsistency in number of references
-@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"
@@ -233,98 +141,19 @@ def test_i18n_warn_for_number_of_references_inconsistency(app):
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
+ yield assert_equal, result, expect
- warnings = warnfile.getvalue().replace(os.sep, '/')
+ warnings = warning.getvalue().replace(os.sep, '/')
warning_fmt = u'.*/refs_inconsistency.txt:\\d+: ' \
- u'WARNING: inconsistent %s in translated message\n'
+ 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)
-
-
-@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
-
-
-@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'])
+ yield assert_re_search, expected_warning_expr, warnings
- # 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'])
+ # --- check warning for literal block
- # 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'])
-
-
-@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"
@@ -333,18 +162,15 @@ def test_i18n_literalblock_warning(app):
u"\n literal block\n"
u"\nMISSING LITERAL BLOCK:\n"
u"\n<SYSTEM MESSAGE:")
- assert result.startswith(expect)
+ yield assert_startswith, result, expect
- warnings = warnfile.getvalue().replace(os.sep, '/')
+ warnings = warning.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)
+ u'WARNING: Literal block expected; none found.'
+ yield assert_re_search, expected_warning_expr, warnings
+ # --- definition terms: regression test for #975
-@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"
@@ -352,15 +178,10 @@ def test_i18n_definition_terms(app):
u"\n THE CORRESPONDING DEFINITION\n"
u"\nSOME OTHER TERM"
u"\n THE CORRESPONDING DEFINITION #2\n")
+ yield assert_equal, result, expect
- assert result == expect
-
+ # --- glossary terms: regression test for #1090
-@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"
@@ -369,146 +190,26 @@ def test_i18n_glossary_terms(app):
u"\nSOME OTHER NEW TERM"
u"\n THE CORRESPONDING GLOSSARY #2\n"
u"\nLINK TO *SOME NEW TERM*.\n")
- assert result == expect
+ yield assert_equal, result, expect
+ warnings = warning.getvalue().replace(os.sep, '/')
+ yield assert_not_in, 'term not in glossary', warnings
- warnings = warnfile.getvalue().replace(os.sep, '/')
- assert 'term not in glossary' not in warnings
-
-
-@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
-
-
-@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'])
+ # --- glossary term inconsistencies: regression test for #1090
- 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'])
-
-
-@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')
+ 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
+ yield assert_equal, result, expect
- warnings = warnfile.getvalue().replace(os.sep, '/')
+ warnings = warning.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)
+ u'.*/glossary_terms_inconsistency.txt:\\d+: '
+ u'WARNING: inconsistent term references in translated message\n')
+ yield assert_re_search, expected_warning_expr, warnings
+ # --- seealso
-@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"
@@ -516,13 +217,10 @@ def test_seealso(app):
u"\nSee also: LONG TEXT 1\n"
u"\nSee also: SHORT TEXT 2\n"
u"\n LONG TEXT 2\n")
- assert result == expect
+ yield assert_equal, result, expect
+ # --- figure captions: regression test for #940
-@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"
@@ -536,14 +234,10 @@ def test_i18n_figure_caption(app):
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")
+ yield assert_equal, result, expect
- assert result == expect
-
+ # --- rubric: regression test for pull request #190
-@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"
@@ -553,14 +247,73 @@ def test_i18n_rubric(app):
u"\n===================\n"
u"\nBLOCK\n"
u"\n -[ RUBRIC TITLE ]-\n")
+ yield assert_equal, result, expect
+
+ # --- 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')
+ yield assert_equal, result, expect
+
+ # --- admonitions
+ # #1206: gettext did not translate admonition directive's title
+ # seealso: http://docutils.sourceforge.net/docs/ref/rst/directives.html#admonitions
- assert result == expect
+ result = (app.outdir / 'admonitions.txt').text(encoding='utf-8')
+ directives = (
+ "attention", "caution", "danger", "error", "hint",
+ "important", "note", "tip", "warning", "admonition")
+ for d in directives:
+ yield assert_in, d.upper() + " TITLE", result
+ yield assert_in, d.upper() + " BODY", result
+
+
+@gen_with_intl_app('html', freshenv=True)
+def test_html_builder(app, status, warning):
+ app.builder.build_all()
+
+ # --- test for #955 cant-build-html-with-footnotes-when-using
+
+ # expect no error by build
+ (app.outdir / 'footnote.html').text(encoding='utf-8')
+
+ # --- links to undefined reference
+
+ result = (app.outdir / 'refs_inconsistency.html').text(encoding='utf-8')
+
+ expected_expr = ('<a class="reference external" '
+ 'href="http://www.example.com">reference</a>')
+ yield assert_equal, len(re.findall(expected_expr, result)), 2
+
+ expected_expr = ('<a class="reference internal" '
+ 'href="#reference">reference</a>')
+ yield assert_equal, len(re.findall(expected_expr, result)), 0
+
+ expected_expr = ('<a class="reference internal" '
+ 'href="#i18n-with-refs-inconsistency">I18N WITH '
+ 'REFS INCONSISTENCY</a>')
+ yield assert_equal, len(re.findall(expected_expr, result)), 1
+ # --- index entries: regression test for #976
-@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):
@@ -586,12 +339,10 @@ def test_i18n_index_entries(app):
wrap('a', 'BUILTIN'),
]
for expr in expected_exprs:
- assert re.search(expr, result, re.M)
+ yield assert_re_search, expr, result, re.M
+ # --- versionchanges
-@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):
@@ -607,83 +358,266 @@ def test_versionchange(app):
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
+ yield assert_equal, 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
+ yield assert_equal, 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
+ yield assert_equal, expect3, matched_content
+ # --- docfields
-@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
+ # expect no error by build
+ (app.outdir / 'docfields.html').text(encoding='utf-8')
+ # --- gettext template
-@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
+ result = (app.outdir / 'index.html').text(encoding='utf-8')
+ yield assert_in, "WELCOME", result
+ yield assert_in, "SPHINX 2013.120", result
+ # --- rebuild by .mo mtime
-@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
+ app.builder.build_update()
+ updated = app.env.update(app.config, app.srcdir, app.doctreedir, app)
+ yield assert_equal, len(updated), 0
+
+ (app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').utime(None)
+ updated = app.env.update(app.config, app.srcdir, app.doctreedir, app)
+ yield assert_equal, len(updated), 1
-@with_intl_app(buildername='html')
-def test_gettext_template(app):
+@gen_with_intl_app('xml', freshenv=True)
+def test_xml_builder(app, status, warning):
app.builder.build_all()
- result = (app.outdir / 'index.html').text(encoding='utf-8')
- assert "WELCOME" in result
- assert "SPHINX 2013.120" in result
+ # --- footnotes: regression test for fix #955, #1176
-@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
+ et = ElementTree.parse(app.outdir / 'footnote.xml')
+ secs = et.findall('section')
+
+ para0 = secs[0].findall('paragraph')
+ yield (assert_elem,
+ para0[0],
+ ['I18N WITH FOOTNOTE', 'INCLUDE THIS CONTENTS',
+ '2', '[ref]', '1', '100', '.'],
+ ['i18n-with-footnote', 'ref'])
+
+ footnote0 = secs[0].findall('footnote')
+ yield (assert_elem,
+ footnote0[0],
+ ['1', 'THIS IS A AUTO NUMBERED FOOTNOTE.'],
+ None,
+ ['1'])
+ yield (assert_elem,
+ footnote0[1],
+ ['100', 'THIS IS A NUMBERED FOOTNOTE.'],
+ None,
+ ['100'])
+ yield (assert_elem,
+ footnote0[2],
+ ['2', 'THIS IS A AUTO NUMBERED NAMED FOOTNOTE.'],
+ None,
+ ['named'])
+
+ citation0 = secs[0].findall('citation')
+ yield (assert_elem,
+ citation0[0],
+ ['ref', 'THIS IS A NAMED FOOTNOTE.'],
+ None,
+ ['ref'])
+
+ warnings = warning.getvalue().replace(os.sep, '/')
+ warning_expr = u'.*/footnote.xml:\\d*: SEVERE: Duplicate ID: ".*".\n'
+ yield assert_not_re_search, warning_expr, warnings
+
+ # --- footnote backlinks: i18n test for #1058
+
+ 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')
+ yield assert_equal, refid2id[ids], backrefs
+
+ # --- refs in the Python domain
- 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
+ et = ElementTree.parse(app.outdir / 'refs_python_domain.xml')
+ secs = et.findall('section')
+
+ # regression test for fix #1363
+ para0 = secs[0].findall('paragraph')
+ yield (assert_elem,
+ para0[0],
+ ['SEE THIS DECORATOR:', 'sensitive_variables()', '.'],
+ ['sensitive.sensitive_variables'])
+
+ # --- keep external links: regression test for #1044
+
+ et = ElementTree.parse(app.outdir / 'external_links.xml')
+ secs = et.findall('section')
+
+ para0 = secs[0].findall('paragraph')
+ # external link check
+ yield (assert_elem,
+ para0[0],
+ ['EXTERNAL LINK TO', 'Python', '.'],
+ ['http://python.org/index.html'])
+
+ # internal link check
+ yield (assert_elem,
+ para0[1],
+ ['EXTERNAL LINKS', 'IS INTERNAL LINK.'],
+ ['i18n-with-external-links'])
+
+ # inline link check
+ yield (assert_elem,
+ para0[2],
+ ['INLINE LINK BY', 'THE SPHINX SITE', '.'],
+ ['http://sphinx-doc.org'])
+
+ # unnamed link check
+ yield (assert_elem,
+ para0[3],
+ ['UNNAMED', 'LINK', '.'],
+ ['http://google.com'])
+
+ # link target swapped translation
+ para1 = secs[1].findall('paragraph')
+ yield (assert_elem,
+ para1[0],
+ ['LINK TO', 'external2', 'AND', 'external1', '.'],
+ ['http://example.com/external2',
+ 'http://example.com/external1'])
+ yield (assert_elem,
+ para1[1],
+ ['LINK TO', 'THE PYTHON SITE', 'AND', 'THE SPHINX SITE', '.'],
+ ['http://python.org', 'http://sphinx-doc.org'])
+
+ # multiple references in the same line
+ para2 = secs[2].findall('paragraph')
+ yield (assert_elem,
+ para2[0],
+ ['LINK TO', 'EXTERNAL LINKS', ',', 'Python', ',',
+ 'THE SPHINX SITE', ',', 'UNNAMED', 'AND',
+ 'THE PYTHON SITE', '.'],
+ ['i18n-with-external-links', 'http://python.org/index.html',
+ 'http://sphinx-doc.org', 'http://google.com',
+ 'http://python.org'])
+
+ # --- role xref: regression test for #1090, #1193
+
+ et = ElementTree.parse(app.outdir / 'role_xref.xml')
+ sec1, sec2 = et.findall('section')
+
+ para1, = sec1.findall('paragraph')
+ yield (assert_elem,
+ para1,
+ ['LINK TO', "I18N ROCK'N ROLE XREF", ',', 'CONTENTS', ',',
+ 'SOME NEW TERM', '.'],
+ ['i18n-role-xref', 'contents',
+ 'glossary_terms#term-some-term'])
+
+ para2 = sec2.findall('paragraph')
+ yield (assert_elem,
+ para2[0],
+ ['LINK TO', 'SOME OTHER NEW TERM', 'AND', 'SOME NEW TERM', '.'],
+ ['glossary_terms#term-some-other-term',
+ 'glossary_terms#term-some-term'])
+ yield(assert_elem,
+ para2[1],
+ ['LINK TO', 'SAME TYPE LINKS', 'AND',
+ "I18N ROCK'N ROLE XREF", '.'],
+ ['same-type-links', 'i18n-role-xref'])
+ yield (assert_elem,
+ para2[2],
+ ['LINK TO', 'I18N WITH GLOSSARY TERMS', 'AND', 'CONTENTS', '.'],
+ ['glossary_terms', 'contents'])
+ yield (assert_elem,
+ para2[3],
+ ['LINK TO', '--module', 'AND', '-m', '.'],
+ ['cmdoption--module', 'cmdoption-m'])
+ yield (assert_elem,
+ para2[4],
+ ['LINK TO', 'env2', 'AND', 'env1', '.'],
+ ['envvar-env2', 'envvar-env1'])
+ yield (assert_elem,
+ para2[5],
+ ['LINK TO', 'token2', 'AND', 'token1', '.'],
+ []) # TODO: how do I link token role to productionlist?
+ yield (assert_elem,
+ para2[6],
+ ['LINK TO', 'same-type-links', 'AND', "i18n-role-xref", '.'],
+ ['same-type-links', 'i18n-role-xref'])
+
+ # warnings
+ warnings = warning.getvalue().replace(os.sep, '/')
+ yield assert_not_in, 'term not in glossary', warnings
+ yield assert_not_in, 'undefined label', warnings
+ yield assert_not_in, 'unknown document', warnings
+
+ # --- label targets: regression test for #1193, #1265
+
+ et = ElementTree.parse(app.outdir / 'label_target.xml')
+ secs = et.findall('section')
+
+ para0 = secs[0].findall('paragraph')
+ yield (assert_elem,
+ para0[0],
+ ['X SECTION AND LABEL', 'POINT TO', 'implicit-target', 'AND',
+ 'X SECTION AND LABEL', 'POINT TO', 'section-and-label', '.'],
+ ['implicit-target', 'section-and-label'])
+
+ para1 = secs[1].findall('paragraph')
+ yield (assert_elem,
+ para1[0],
+ ['X EXPLICIT-TARGET', 'POINT TO', 'explicit-target', 'AND',
+ 'X EXPLICIT-TARGET', 'POINT TO DUPLICATED ID LIKE', 'id1',
+ '.'],
+ ['explicit-target', 'id1'])
+
+ para2 = secs[2].findall('paragraph')
+ yield (assert_elem,
+ para2[0],
+ ['X IMPLICIT SECTION NAME', 'POINT TO',
+ 'implicit-section-name', '.'],
+ ['implicit-section-name'])
+
+ sec2 = secs[2].findall('section')
+
+ para2_0 = sec2[0].findall('paragraph')
+ yield (assert_elem,
+ para2_0[0],
+ ['`X DUPLICATED SUB SECTION`_', 'IS BROKEN LINK.'],
+ [])
+
+ para3 = secs[3].findall('paragraph')
+ yield (assert_elem,
+ para3[0],
+ ['X', 'bridge label',
+ 'IS NOT TRANSLATABLE BUT LINKED TO TRANSLATED ' +
+ 'SECTION TITLE.'],
+ ['label-bridged-target-section'])
+ yield (assert_elem,
+ para3[1],
+ ['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.'],
+ ['label-bridged-target-section',
+ 'section-and-label',
+ 'section-and-label'])
diff --git a/tests/test_linkcode.py b/tests/test_linkcode.py
deleted file mode 100644
index 83b72098..00000000
--- a/tests/test_linkcode.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- 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
-
-
-@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
index 4f0b0de8..8bac6324 100644
--- a/tests/test_markup.py
+++ b/tests/test_markup.py
@@ -15,7 +15,6 @@ 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
@@ -24,10 +23,11 @@ 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)
+ app = TestApp()
optparser = frontend.OptionParser(
components=(rst.Parser, HTMLWriter, LaTeXWriter))
settings = optparser.get_default_values()
@@ -36,6 +36,7 @@ def setup_module():
settings.env.temp_data['docname'] = 'dummy'
parser = rst.Parser()
+
def teardown_module():
app.cleanup()
@@ -43,18 +44,21 @@ def teardown_module():
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 = utils.new_document(b'test data', settings)
document['file'] = 'dummy'
parser.parse(rst, document)
for msg in document.traverse(nodes.system_message):
@@ -84,16 +88,16 @@ def verify(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>&nbsp;&nbsp; <span class="pre">sample</span></tt></p>')
+ _html = ('<p><code class="(samp )?docutils literal"><span class="pre">'
+ 'code</span>&nbsp;&nbsp; <span class="pre">sample</span></code></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>'
+ '<p><code class="samp docutils literal"><span class="pre">a</span>'
'<em><span class="pre">b</span></em>'
- '<span class="pre">c</span></tt></p>',
+ '<span class="pre">c</span></code></p>',
'\\code{a\\emph{b}c}')
# interpolation of arrows in menuselection
@@ -109,15 +113,16 @@ def test_inline():
# 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}}$')
+ '<p><code( class="xref std std-option docutils literal")?>'
+ '<span class="pre">--with-option</span></code></p>$',
+ r'\\code{-{-}with-option}$')
# verify smarty-pants quotes
yield verify, '"John"', '<p>&#8220;John&#8221;</p>', "``John''"
# ... but not in literal text
yield (verify, '``"John"``',
- '<p><tt class="docutils literal"><span class="pre">'
- '&quot;John&quot;</span></tt></p>',
+ '<p><code class="docutils literal"><span class="pre">'
+ '&quot;John&quot;</span></code></p>',
'\\code{"John"}')
# verify classes for inline roles
@@ -128,12 +133,12 @@ def test_inline():
def test_latex_escaping():
# correct escaping in normal mode
yield (verify, u'Γ\\\\∞$', None,
- ur'\(\Gamma\)\textbackslash{}\(\infty\)\$')
+ r'\(\Gamma\)\textbackslash{}\(\infty\)\$')
# in verbatim code fragments
yield (verify, u'::\n\n @Γ\\∞${}', None,
- u'\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n'
+ u'\\begin{Verbatim}[frame=single,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}.*')
+ r'\\href{http://example.com/~me/}{test}.*')
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
index a0d44457..944aa157 100644
--- a/tests/test_metadata.py
+++ b/tests/test_metadata.py
@@ -12,27 +12,13 @@
# adapted from an example of bibliographic metadata at
# http://docutils.sourceforge.net/docs/user/rst/demo.txt
-from util import TestApp
+from util import with_app
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():
+@with_app('pseudoxml')
+def test_docinfo(app, status, warning):
"""
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
@@ -40,6 +26,8 @@ def test_docinfo():
'dedication' blocks, or the 'meta' role. Doing otherwise is probably more
messing with the internals of sphinx than this rare use case merits.
"""
+ app.builder.build(['metadata'])
+ env = app.env
exampledocinfo = env.metadata['metadata']
expecteddocinfo = {
'author': u'David Goodger',
@@ -61,6 +49,9 @@ def test_docinfo():
'date': u'2006-05-21',
'organization': u'humankind',
'revision': u'4564',
+ 'tocdepth': 1,
+ 'orphan': u'',
+ 'nocomments': u'',
}
# I like this way of comparing dicts - easier to see the error.
for key in exampledocinfo:
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index 8f630700..1d3bcd9e 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -11,10 +11,11 @@
import sys
import time
-from StringIO import StringIO
-import tempfile
-from util import raises, with_tempdir, with_app, SkipTest
+from six import PY2, text_type, StringIO
+from six.moves import input
+
+from util import raises, with_tempdir, SkipTest
from sphinx import application
from sphinx import quickstart as qs
@@ -28,18 +29,20 @@ warnfile = StringIO()
def setup_module():
nocolor()
-def mock_raw_input(answers, needanswer=False):
+
+def mock_input(answers, needanswer=False):
called = set()
- def raw_input(prompt):
+
+ def 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):
+ if PY2:
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
+ prompt = text_type(prompt) # Python3.x input emulation
# `input` decode prompt by default encoding before print.
for question in answers:
if prompt.startswith(qs.PROMPT_PREFIX + question):
@@ -47,15 +50,14 @@ def mock_raw_input(answers, needanswer=False):
if needanswer:
raise AssertionError('answer for %r missing' % prompt)
return ''
- return raw_input
+ return input_
+
+
+real_input = input
-try:
- real_raw_input = raw_input
-except NameError:
- real_raw_input = input
def teardown_module():
- qs.term_input = real_raw_input
+ qs.term_input = real_input
qs.TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
coloron()
@@ -63,12 +65,12 @@ def teardown_module():
def test_quickstart_inputstrip():
d = {}
answers = {
- 'Q1': 'Y\r', # input() return with '\r' on Python-3.2.0 for Windows
- 'Q2': ' Yes \r',
+ 'Q1': 'Y',
+ 'Q2': ' Yes ',
'Q3': 'N',
'Q4': 'N ',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
qs.do_prompt(d, 'k1', 'Q1')
assert d['k1'] == 'Y'
qs.do_prompt(d, 'k2', 'Q2')
@@ -88,7 +90,7 @@ def test_do_prompt():
'Q5': 'no',
'Q6': 'foo',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
try:
qs.do_prompt(d, 'k1', 'Q1')
except AssertionError:
@@ -113,7 +115,7 @@ def test_do_prompt_with_nonascii():
answers = {
'Q1': u'\u30c9\u30a4\u30c4',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
try:
qs.do_prompt(d, 'k1', 'Q1', default=u'\u65e5\u672c')
except UnicodeEncodeError:
@@ -131,7 +133,7 @@ def test_quickstart_defaults(tempdir):
'Author name': 'Georg Brandl',
'Project version': '0.1',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
d = {}
qs.ask_user(d)
qs.generate(d)
@@ -170,6 +172,7 @@ def test_quickstart_all_answers(tempdir):
'Author name': u'Wolfgang Schäuble & G\'Beckstein'.encode('utf-8'),
'Project version': '2.0',
'Project release': '2.0.1',
+ 'Project language': 'de',
'Source file suffix': '.txt',
'Name of your master document': 'contents',
'autodoc': 'y',
@@ -185,7 +188,7 @@ def test_quickstart_all_answers(tempdir):
'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_input = mock_input(answers, needanswer=True)
qs.TERM_ENCODING = 'utf-8'
d = {}
qs.ask_user(d)
@@ -201,7 +204,7 @@ def test_quickstart_all_answers(tempdir):
assert ns['master_doc'] == 'contents'
assert ns['project'] == u'STASIâ„¢'
assert ns['copyright'] == u'%s, Wolfgang Schäuble & G\'Beckstein' % \
- time.strftime('%Y')
+ time.strftime('%Y')
assert ns['version'] == '2.0'
assert ns['release'] == '2.0.1'
assert ns['html_static_path'] == ['.static']
@@ -215,7 +218,7 @@ def test_quickstart_all_answers(tempdir):
assert ns['texinfo_documents'] == [
('contents', 'STASI', u'STASIâ„¢ Documentation',
u'Wolfgang Schäuble & G\'Beckstein', 'STASI',
- 'One line description of project.', 'Miscellaneous'),]
+ 'One line description of project.', 'Miscellaneous')]
assert (tempdir / 'build').isdir()
assert (tempdir / 'source' / '.static').isdir()
@@ -231,14 +234,14 @@ def test_generated_files_eol(tempdir):
'Author name': 'Georg Brandl',
'Project version': '0.1',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_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 all([l[-len(eol):] == eol for l in content.splitlines(True)])
assert_eol(tempdir / 'make.bat', '\r\n')
assert_eol(tempdir / 'Makefile', '\n')
@@ -252,19 +255,19 @@ def test_quickstart_and_build(tempdir):
'Author name': 'Georg Brandl',
'Project version': '0.1',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_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)
+ 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
@@ -274,11 +277,11 @@ def test_quickstart_and_build(tempdir):
def test_default_filename(tempdir):
answers = {
'Root path': tempdir,
- 'Project name': u'\u30c9\u30a4\u30c4', #Fullwidth characters only
+ 'Project name': u'\u30c9\u30a4\u30c4', # Fullwidth characters only
'Author name': 'Georg Brandl',
'Project version': '0.1',
}
- qs.term_input = mock_raw_input(answers)
+ qs.term_input = mock_input(answers)
d = {}
qs.ask_user(d)
qs.generate(d)
diff --git a/tests/test_search.py b/tests/test_search.py
index 2efd753c..a7e99e04 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -13,7 +13,6 @@ from docutils import frontend, utils
from docutils.parsers import rst
from sphinx.search import IndexBuilder
-from sphinx.util.pycompat import b
settings = parser = None
@@ -32,7 +31,7 @@ test that non-comments are indexed: fermion
'''
def test_wordcollector():
- doc = utils.new_document(b('test data'), settings)
+ doc = utils.new_document(b'test data', settings)
doc['file'] = 'dummy'
parser.parse(FILE_CONTENTS, doc)
diff --git a/tests/test_searchadapters.py b/tests/test_searchadapters.py
index 81d7c178..4a91f96d 100644
--- a/tests/test_searchadapters.py
+++ b/tests/test_searchadapters.py
@@ -9,32 +9,24 @@
:license: BSD, see LICENSE for details.
"""
-import os
-from StringIO import StringIO
+from six 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)
+from util import rootdir, tempdir, skip_if, skip_unless_importable
def teardown_module():
- (test_root / 'generated').rmtree(True)
- clear_builddir()
+ (tempdir / 'websupport').rmtree(True)
def search_adapter_helper(adapter):
- clear_builddir()
-
- settings = {'builddir': os.path.join(test_root, 'websupport'),
+ settings = {'srcdir': rootdir / 'root',
+ 'builddir': tempdir / 'websupport',
'status': StringIO(),
- 'warning': StringIO()}
- settings.update({'srcdir': test_root,
- 'search': adapter})
+ 'warning': StringIO(),
+ 'search': adapter}
support = WebSupport(**settings)
support.build()
@@ -62,7 +54,7 @@ def search_adapter_helper(adapter):
'%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')
+ support.get_search_results(u'SomeLongRandomWord')
@skip_unless_importable('xapian', 'needs xapian bindings installed')
diff --git a/tests/test_setup_command.py b/tests/test_setup_command.py
index c165b2d3..70826721 100644
--- a/tests/test_setup_command.py
+++ b/tests/test_setup_command.py
@@ -16,11 +16,16 @@ from functools import wraps
import tempfile
import sphinx
-from util import with_tempdir, test_roots, SkipTest
+from util import rootdir, tempdir, SkipTest
from path import path
from textwrap import dedent
-root = test_roots / 'test-setup'
+root = tempdir / 'test-setup'
+
+
+def setup_module():
+ if not root.exists():
+ (rootdir / 'roots' / 'test-setup').copytree(root)
def with_setup_command(root, *args, **kwds):
diff --git a/tests/test_templating.py b/tests/test_templating.py
index e8fafca2..5f8fcaeb 100644
--- a/tests/test_templating.py
+++ b/tests/test_templating.py
@@ -9,28 +9,23 @@
:license: BSD, see LICENSE for details.
"""
-from util import test_roots, with_app
+from util import with_app
-def teardown_module():
- (test_roots / 'test-templating' / '_build').rmtree(True),
-
-
-@with_app(buildername='html', srcdir=(test_roots / 'test-templating'))
-def test_layout_overloading(app):
- app.builder.build_all()
+@with_app('html', testroot='templating')
+def test_layout_overloading(app, status, warning):
+ app.builder.build_update()
result = (app.outdir / 'contents.html').text(encoding='utf-8')
assert '<!-- layout overloading -->' in result
-@with_app(buildername='html', srcdir=(test_roots / 'test-templating'))
-def test_autosummary_class_template_overloading(app):
- app.builder.build_all()
+@with_app('html', testroot='templating')
+def test_autosummary_class_template_overloading(app, status, warning):
+ app.builder.build_update()
- result = (app.outdir / 'generated' / 'sphinx.application.Sphinx.html').text(
- encoding='utf-8')
+ result = (app.outdir / 'generated' / 'sphinx.application.TemplateBridge.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
index 7f91a32a..85138b97 100644
--- a/tests/test_theming.py
+++ b/tests/test_theming.py
@@ -19,14 +19,14 @@ from util import with_app, raises
@with_app(confoverrides={'html_theme': 'ziptheme',
'html_theme_options.testopt': 'foo'})
-def test_theme_api(app):
+def test_theme_api(app, status, warning):
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'])
+ set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku',
+ 'traditional', 'testtheme', 'ziptheme', 'epub', 'nature',
+ 'pyramid', 'bizstyle'])
assert Theme.themes['testtheme'][1] is None
assert isinstance(Theme.themes['ziptheme'][1], zipfile.ZipFile)
@@ -55,3 +55,27 @@ def test_theme_api(app):
# cleanup temp directories
theme.cleanup()
assert not os.path.exists(themedir)
+
+
+@with_app(testroot='tocdepth') # a minimal root
+def test_js_source(app, status, warning):
+ # Now sphinx provides non-minified JS files for jquery.js and underscore.js
+ # to clarify the source of the minified files. see also #1434.
+ # If you update the version of the JS file, please update the source of the
+ # JS file and version number in this test.
+
+ app.builder.build(['contents'])
+
+ v = '1.11.1'
+ msg = 'jquery.js version does not match to {v}'.format(v=v)
+ jquery_min = (app.outdir / '_static' / 'jquery.js').text()
+ assert 'jQuery v{v}'.format(v=v) in jquery_min, msg
+ jquery_src = (app.outdir / '_static' / 'jquery-{v}.js'.format(v=v)).text()
+ assert 'jQuery JavaScript Library v{v}'.format(v=v) in jquery_src, msg
+
+ v = '1.3.1'
+ msg = 'underscore.js version does not match to {v}'.format(v=v)
+ underscore_min = (app.outdir / '_static' / 'underscore.js').text()
+ assert 'Underscore.js {v}'.format(v=v) in underscore_min, msg
+ underscore_src = (app.outdir / '_static' / 'underscore-{v}.js'.format(v=v)).text()
+ assert 'Underscore.js {v}'.format(v=v) in underscore_src, msg
diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py
new file mode 100644
index 00000000..d69c2acd
--- /dev/null
+++ b/tests/test_util_i18n.py
@@ -0,0 +1,163 @@
+# -*- coding: utf-8 -*-
+"""
+ test_util_i18n
+ ~~~~~~~~~~~~~~
+
+ Test i18n util.
+
+ :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from __future__ import print_function
+
+import os
+from os import path
+
+from babel.messages.mofile import read_mo
+from sphinx.util import i18n
+
+from util import with_tempdir
+
+
+def test_catalog_info_for_file_and_path():
+ cat = i18n.CatalogInfo('path', 'domain')
+ assert cat.po_file == 'domain.po'
+ assert cat.mo_file == 'domain.mo'
+ assert cat.po_path == path.join('path', 'domain.po')
+ assert cat.mo_path == path.join('path', 'domain.mo')
+
+
+def test_catalog_info_for_sub_domain_file_and_path():
+ cat = i18n.CatalogInfo('path', 'sub/domain')
+ assert cat.po_file == 'sub/domain.po'
+ assert cat.mo_file == 'sub/domain.mo'
+ assert cat.po_path == path.join('path', 'sub/domain.po')
+ assert cat.mo_path == path.join('path', 'sub/domain.mo')
+
+
+@with_tempdir
+def test_catalog_outdated(dir):
+ (dir / 'test.po').write_text('#')
+ cat = i18n.CatalogInfo(dir, 'test')
+ assert cat.is_outdated() # if mo is not exist
+
+ mo_file = (dir / 'test.mo')
+ mo_file.write_text('#')
+ assert not cat.is_outdated() # if mo is exist and newer than po
+
+ os.utime(mo_file, (os.stat(mo_file).st_mtime - 10,) * 2) # to be outdate
+ assert cat.is_outdated() # if mo is exist and older than po
+
+
+@with_tempdir
+def test_catalog_write_mo(dir):
+ (dir / 'test.po').write_text('#')
+ cat = i18n.CatalogInfo(dir, 'test')
+ cat.write_mo('en')
+ assert path.exists(cat.mo_path)
+ assert read_mo(open(cat.mo_path, 'rb')) is not None
+
+
+@with_tempdir
+def test_get_catalogs_for_xx(dir):
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
+ (dir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
+ (dir / 'loc1' / 'en' / 'LC_MESSAGES' / 'test6.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_ALL').makedirs()
+ (dir / 'loc1' / 'xx' / 'LC_ALL' / 'test7.po').write_text('#')
+
+ catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=False)
+ domains = set(c.domain for c in catalogs)
+ assert domains == set([
+ 'test1',
+ 'test2',
+ path.normpath('sub/test4'),
+ path.normpath('sub/test5'),
+ ])
+
+
+@with_tempdir
+def test_get_catalogs_for_en(dir):
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'xx_dom.po').write_text('#')
+ (dir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
+ (dir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#')
+
+ catalogs = i18n.get_catalogs([dir / 'loc1'], 'en', force_all=False)
+ domains = set(c.domain for c in catalogs)
+ assert domains == set(['en_dom'])
+
+
+@with_tempdir
+def test_get_catalogs_with_non_existent_locale(dir):
+ catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx')
+ assert not catalogs
+
+ catalogs = i18n.get_catalogs([dir / 'loc1'], None)
+ assert not catalogs
+
+
+def test_get_catalogs_with_non_existent_locale_dirs():
+ catalogs = i18n.get_catalogs(['dummy'], 'xx')
+ assert not catalogs
+
+
+@with_tempdir
+def test_get_catalogs_for_xx_without_outdated(dir):
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.mo').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.mo').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.mo').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.mo').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.mo').write_text('#')
+
+ catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=False)
+ assert not catalogs
+
+ catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=True)
+ domains = set(c.domain for c in catalogs)
+ assert domains == set([
+ 'test1',
+ 'test2',
+ path.normpath('sub/test4'),
+ path.normpath('sub/test5'),
+ ])
+
+
+@with_tempdir
+def test_get_catalogs_from_multiple_locale_dirs(dir):
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (dir / 'loc2' / 'xx' / 'LC_MESSAGES').makedirs()
+ (dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
+
+ catalogs = i18n.get_catalogs([dir / 'loc1', dir / 'loc2'], 'xx')
+ domains = sorted(c.domain for c in catalogs)
+ assert domains == ['test1', 'test1', 'test2']
+
+
+@with_tempdir
+def test_get_catalogs_with_compact(dir):
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#')
+ (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
+
+ catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', gettext_compact=True)
+ domains = set(c.domain for c in catalogs)
+ assert domains == set(['test1', 'test2', 'sub'])
diff --git a/tests/test_util_nodes.py b/tests/test_util_nodes.py
index 9ddc049d..a385245d 100644
--- a/tests/test_util_nodes.py
+++ b/tests/test_util_nodes.py
@@ -1,121 +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,
- )
+# -*- 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
index bf2f65ee..bd8c697c 100644
--- a/tests/test_versioning.py
+++ b/tests/test_versioning.py
@@ -15,41 +15,47 @@ 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
+from util import TestApp
app = original = original_uids = None
+
def setup_module():
global app, original, original_uids
- app = TestApp()
+ app = TestApp(testroot='versioning')
app.builder.env.app = app
app.connect('doctree-resolved', on_doctree_resolved)
app.build()
- original = doctrees['versioning/original']
+ original = doctrees['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()
@@ -63,44 +69,50 @@ def test_picklablility():
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']
+ modified = doctrees['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']
+ added = doctrees['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']
+ deleted = doctrees['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']
+ deleted_end = doctrees['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']
+ insert = doctrees['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']
+ insert_beginning = doctrees['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
@@ -108,8 +120,9 @@ def test_insert_beginning():
assert original_uids == uids[1:]
assert original_uids[0] != uids[0]
+
def test_insert_similar():
- insert_similar = doctrees['versioning/insert_similar']
+ insert_similar = doctrees['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
diff --git a/tests/test_websupport.py b/tests/test_websupport.py
index 9376a2a2..9e88a60f 100644
--- a/tests/test_websupport.py
+++ b/tests/test_websupport.py
@@ -9,38 +9,33 @@
:license: BSD, see LICENSE for details.
"""
-import os
-from StringIO import StringIO
+from functools import wraps
-try:
- from functools import wraps
-except ImportError:
- # functools is new in 2.5
- wraps = lambda f: (lambda w: w)
+from six import StringIO
from sphinx.websupport import WebSupport
from sphinx.websupport.errors import DocumentNotFoundError, \
- CommentNotAllowedError, UserNotAuthorizedError
+ 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
+ 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
+from util import rootdir, tempdir, raises, skip_if
-default_settings = {'builddir': os.path.join(test_root, 'websupport'),
+default_settings = {'builddir': tempdir / 'websupport',
'status': StringIO(),
'warning': StringIO()}
+
def teardown_module():
- (test_root / 'generated').rmtree(True)
- (test_root / 'websupport').rmtree(True)
+ (tempdir / 'websupport').rmtree(True)
def with_support(*args, **kwargs):
@@ -63,12 +58,12 @@ class NullStorage(StorageBackend):
@with_support(storage=NullStorage())
def test_no_srcdir(support):
- """Make sure the correct exception is raised if srcdir is not given."""
+ # make sure the correct exception is raised if srcdir is not given.
raises(RuntimeError, support.build)
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
-@with_support(srcdir=test_root)
+@with_support(srcdir=rootdir / 'root')
def test_build(support):
support.build()
@@ -177,9 +172,9 @@ def test_proposals(support):
source = data['source']
proposal = source[:5] + source[10:15] + 'asdf' + source[15:]
- comment = support.add_comment('Proposal comment',
- node_id=node.id,
- proposal=proposal)
+ support.add_comment('Proposal comment',
+ node_id=node.id,
+ proposal=proposal)
@skip_if(sqlalchemy_missing, 'needs sqlalchemy')
@@ -238,6 +233,8 @@ def test_update_username(support):
called = False
+
+
def moderation_callback(comment):
global called
called = True
@@ -255,7 +252,7 @@ def test_moderation(support):
deleted = support.add_comment('Comment to delete', node_id=node.id,
displayed=False)
# Make sure the moderation_callback is called.
- assert called == True
+ assert called
# Make sure the user must be a moderator.
raises(UserNotAuthorizedError, support.accept_comment, accepted['id'])
raises(UserNotAuthorizedError, support.delete_comment, deleted['id'])
diff --git a/tests/util.py b/tests/util.py
index 61c9bd0d..bf35d279 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -7,39 +7,42 @@
:license: BSD, see LICENSE for details.
"""
+import os
+import re
import sys
-import StringIO
import tempfile
-import shutil
-import re
-from codecs import open
+from functools import wraps
-try:
- from functools import wraps
-except ImportError:
- # functools is new in 2.4
- wraps = lambda f: (lambda w: w)
+from six import StringIO
+
+from nose import tools, SkipTest
from sphinx import application
from sphinx.theming import Theme
from sphinx.ext.autodoc import AutoDirective
+from sphinx.pycode import ModuleAnalyzer
from path import path
-from nose import tools, SkipTest
+try:
+ # Python >=3.3
+ from unittest import mock
+except ImportError:
+ import mock
__all__ = [
- 'test_root', 'test_roots', 'raises', 'raises_msg',
+ 'rootdir', 'tempdir', 'raises', 'raises_msg',
'skip_if', 'skip_unless', 'skip_unless_importable', 'Struct',
'ListOutput', 'TestApp', 'with_app', 'gen_with_app',
- 'path', 'with_tempdir', 'write_file',
+ 'path', 'with_tempdir',
'sprint', 'remove_unicode_literals',
+ 'mock',
]
-test_root = path(__file__).parent.joinpath('root').abspath()
-test_roots = path(__file__).parent.joinpath('roots').abspath()
+rootdir = path(os.path.dirname(__file__) or '.').abspath()
+tempdir = path(os.environ['SPHINX_TEST_TEMPDIR']).abspath()
def _excstr(exc):
@@ -47,11 +50,9 @@ def _excstr(exc):
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*.
- """
+ """Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*."""
try:
func(*args, **kwds)
except exc:
@@ -60,19 +61,45 @@ def raises(exc, func, *args, **kwds):
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*.
+ """Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*,
+ and check if the message contains *msg*.
"""
try:
func(*args, **kwds)
- except exc, err:
+ except exc as 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 assert_re_search(regex, text, flags=0):
+ if not re.search(regex, text, flags):
+ assert False, '%r did not match %r' % (regex, text)
+
+
+def assert_not_re_search(regex, text, flags=0):
+ if re.search(regex, text, flags):
+ assert False, '%r did match %r' % (regex, text)
+
+
+def assert_startswith(thing, prefix):
+ if not thing.startswith(prefix):
+ assert False, '%r does not start with %r' % (thing, prefix)
+
+
+def assert_in(x, thing):
+ if x not in thing:
+ assert False, '%r is not in %r' % (x, thing)
+
+
+def assert_not_in(x, thing):
+ if x in thing:
+ assert False, '%r is in %r' % (x, thing)
+
+
def skip_if(condition, msg=None):
"""Decorator to skip test if condition is true."""
def deco(test):
@@ -84,10 +111,12 @@ def skip_if(condition, msg=None):
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:
@@ -124,57 +153,47 @@ class TestApp(application.Sphinx):
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']
-
+ def __init__(self, buildername='html', testroot=None, srcdir=None,
+ freshenv=False, confoverrides=None, status=None, warning=None,
+ tags=None, docutilsconf=None):
+ if testroot is None:
+ defaultsrcdir = 'root'
+ testroot = rootdir / 'root'
+ else:
+ defaultsrcdir = 'test-' + testroot
+ testroot = rootdir / 'roots' / ('test-' + testroot)
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
+ srcdir = tempdir / defaultsrcdir
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)
+ srcdir = tempdir / srcdir
+
+ if not srcdir.exists():
+ testroot.copytree(srcdir)
+
+ if docutilsconf is not None:
+ (srcdir / 'docutils.conf').write_text(docutilsconf)
+
+ builddir = srcdir / '_build'
+# if confdir is None:
+ confdir = srcdir
+# if outdir is None:
+ outdir = builddir.joinpath(buildername)
+ if not outdir.isdir():
+ outdir.makedirs()
+# if doctreedir is None:
+ doctreedir = builddir.joinpath('doctrees')
+ if not doctreedir.isdir():
+ doctreedir.makedirs()
if confoverrides is None:
confoverrides = {}
if status is None:
- status = StringIO.StringIO()
+ status = StringIO()
if warning is None:
warning = ListOutput('stderr')
- if freshenv is None:
- freshenv = False
- if warningiserror is None:
- warningiserror = False
+# if warningiserror is None:
+ warningiserror = False
+
+ self._saved_path = sys.path[:]
application.Sphinx.__init__(self, srcdir, confdir, outdir, doctreedir,
buildername, confoverrides, status, warning,
@@ -183,8 +202,9 @@ class TestApp(application.Sphinx):
def cleanup(self, doctrees=False):
Theme.themes.clear()
AutoDirective._registry.clear()
- for tree in self.cleanup_trees:
- shutil.rmtree(tree, True)
+ ModuleAnalyzer.cache.clear()
+ sys.path[:] = self._saved_path
+ sys.modules.pop('autodoc_fodder', None)
def __repr__(self):
return '<%s buildername=%r>' % (self.__class__.__name__, self.builder.name)
@@ -198,10 +218,14 @@ def with_app(*args, **kwargs):
def generator(func):
@wraps(func)
def deco(*args2, **kwargs2):
+ status, warning = StringIO(), StringIO()
+ kwargs['status'] = status
+ kwargs['warning'] = warning
app = TestApp(*args, **kwargs)
- func(app, *args2, **kwargs2)
- # don't execute cleanup if test failed
- app.cleanup()
+ try:
+ func(app, status, warning, *args2, **kwargs2)
+ finally:
+ app.cleanup()
return deco
return generator
@@ -214,39 +238,42 @@ def gen_with_app(*args, **kwargs):
def generator(func):
@wraps(func)
def deco(*args2, **kwargs2):
+ status, warning = StringIO(), StringIO()
+ kwargs['status'] = status
+ kwargs['warning'] = warning
app = TestApp(*args, **kwargs)
- for item in func(app, *args2, **kwargs2):
- yield item
- # don't execute cleanup if test failed
- app.cleanup()
+ try:
+ for item in func(app, status, warning, *args2, **kwargs2):
+ yield item
+ finally:
+ 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_tempdir = path(tempfile.mkdtemp(dir=tempdir))
+ func(new_tempdir, *args, **kwds)
+ new_tempdir.rmtree() # not when test fails...
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)
+
+
+def find_files(root, suffix=None):
+ for dirpath, dirs, files in os.walk(root, followlinks=True):
+ dirpath = path(dirpath)
+ for f in [f for f in files if not suffix or f.endswith(suffix)]:
+ fpath = dirpath / f
+ yield os.path.relpath(fpath, root)
diff --git a/tox.ini b/tox.ini
index f1675e90..f308880e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist=py25,py26,py27,py31,py32,py33,pypy,du11,du10,du09,du08,du07
+envlist=py26,py27,py33,py34,pypy,du12,du11,du10
[testenv]
deps=
@@ -7,50 +7,41 @@ deps=
sqlalchemy
whoosh
setenv =
- BUILD_TEST_PATH = {envdir}/tests
+ SPHINX_TEST_TEMPDIR = {envdir}/testbuild
commands=
{envpython} tests/run.py {posargs}
- sphinx-build -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html
+ sphinx-build -q -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html
-[testenv:py25]
+[testenv:py26]
deps=
- simplejson==2.5.0
+ mock
{[testenv]deps}
-setenv=
- PIP_INSECURE = 1
- {[testenv]setenv}
-[testenv:py33]
+[testenv:py27]
deps=
- docutils>=0.10.0
+ mock
{[testenv]deps}
[testenv:pypy]
deps=
+ mock
simplejson
{[testenv]deps}
-[testenv:du07]
-deps=
- docutils==0.7
- {[testenv]deps}
-
-[testenv:du08]
-deps=
- docutils==0.8.1
- {[testenv]deps}
-
-[testenv:du09]
-deps=
- docutils==0.9.1
- {[testenv]deps}
-
[testenv:du10]
deps=
+ mock
docutils==0.10
{[testenv]deps}
[testenv:du11]
deps=
+ mock
docutils==0.11
{[testenv]deps}
+
+[testenv:du12]
+deps=
+ mock
+ docutils==0.12
+ {[testenv]deps}
diff --git a/utils/check_sources.py b/utils/check_sources.py
index 7bbd0a79..1b78ab62 100755
--- a/utils/check_sources.py
+++ b/utils/check_sources.py
@@ -10,18 +10,13 @@
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
+from __future__ import print_function
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 = {}
@@ -36,25 +31,25 @@ def checker(*suffixes, **kwds):
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
+copyright_re = re.compile(br'^ :copyright: Copyright 200\d(-20\d\d)? '
+ br'by %s(, %s)*[,.]$' %
+ (name_mail_re, name_mail_re))
+license_re = re.compile(br" :license: (.*?).\n")
+copyright_2_re = re.compile(br'^ %s(, %s)*[,.]$' %
+ (name_mail_re, name_mail_re))
+coding_re = re.compile(br'coding[:=]\s*([-\w.]+)')
+not_ix_re = re.compile(br'\bnot\s+\S+?\s+i[sn]\s\S+')
+is_const_re = re.compile(br'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:
+ compile(b''.join(lines), fn, "exec")
+ except SyntaxError as err:
yield 0, "not compilable: %s" % err
@@ -68,7 +63,7 @@ def check_style_and_encoding(fn, lines):
co = coding_re.search(line)
if co:
encoding = co.group(1).decode('ascii')
- if line.strip().startswith(b('#')):
+ if line.strip().startswith(b'#'):
continue
#m = not_ix_re.search(line)
#if m:
@@ -77,9 +72,9 @@ def check_style_and_encoding(fn, lines):
yield lno+1, 'using == None/True/False'
try:
line.decode(encoding)
- except UnicodeDecodeError, err:
+ except UnicodeDecodeError as err:
yield lno+1, "not decodable: %s\n Line: %r" % (err, line)
- except LookupError, err:
+ except LookupError as err:
yield 0, "unknown encoding: %s" % encoding
encoding = 'latin1'
@@ -88,7 +83,7 @@ def check_style_and_encoding(fn, lines):
def check_fileheader(fn, lines):
# line number correction
c = 1
- if lines[0:1] == [b('#!/usr/bin/env python\n')]:
+ if lines[0:1] == [b'#!/usr/bin/env python\n']:
lines = lines[1:]
c = 2
@@ -97,38 +92,38 @@ def check_fileheader(fn, lines):
for lno, l in enumerate(lines):
llist.append(l)
if lno == 0:
- if l == b('# -*- coding: rot13 -*-\n'):
+ if l == b'# -*- coding: rot13 -*-\n':
# special-case pony package
return
- elif l != b('# -*- coding: utf-8 -*-\n'):
+ elif l != b'# -*- coding: utf-8 -*-\n':
yield 1, "missing coding declaration"
elif lno == 1:
- if l != b('"""\n') and l != b('r"""\n'):
+ if l != b'"""\n' and l != b'r"""\n':
yield 2, 'missing docstring begin (""")'
else:
docopen = True
elif docopen:
- if l == b('"""\n'):
+ 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:
+ 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):
+ if l.lower()[4:-1] == bytes(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("~"):
+ if l.strip() != modnamelen * b"~":
yield 4, "wrong module name underline, should be ~~~...~"
else:
@@ -151,16 +146,16 @@ def check_fileheader(fn, lines):
@checker('.py', '.html', '.rst')
def check_whitespace_and_spelling(fn, lines):
for lno, line in enumerate(lines):
- if b("\t") in line:
+ if b"\t" in line:
yield lno+1, "OMG TABS!!!1 "
- if line[:-1].rstrip(b(' \t')) != line[:-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:
+ 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'])
+bad_tags = [b'<u>', b'<s>', b'<strike>', b'<center>', b'<font']
@checker('.html')
def check_xhtml(fn, lines):
@@ -183,7 +178,7 @@ def main(argv):
elif len(args) == 1:
path = args[0]
else:
- print args
+ print(args)
parser.error('No more then one path supported')
verbose = options.verbose
@@ -214,7 +209,7 @@ def main(argv):
continue
if verbose:
- print "Checking %s..." % fn
+ print("Checking %s..." % fn)
try:
f = open(fn, 'rb')
@@ -222,8 +217,8 @@ def main(argv):
lines = list(f)
finally:
f.close()
- except (IOError, OSError), err:
- print "%s: cannot open: %s" % (fn, err)
+ except (IOError, OSError) as err:
+ print("%s: cannot open: %s" % (fn, err))
num += 1
continue
@@ -231,15 +226,15 @@ def main(argv):
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)
+ print("%s:%d: %s" % (fn, lno, msg), file=out)
num += 1
if verbose:
- print
+ print()
if num == 0:
- print "No errors found."
+ print("No errors found.")
else:
- print out.getvalue().rstrip('\n')
- print "%d error%s found." % (num, num > 1 and "s" or "")
+ print(out.getvalue().rstrip('\n'))
+ print("%d error%s found." % (num, num > 1 and "s" or ""))
return int(num > 0)
diff --git a/utils/convert.py b/utils/convert.py
deleted file mode 100755
index c90be8e6..00000000
--- a/utils/convert.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/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/reindent.py b/utils/reindent.py
index 59828fd8..ef53fe8c 100755
--- a/utils/reindent.py
+++ b/utils/reindent.py
@@ -38,6 +38,7 @@ 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.
"""
+from __future__ import print_function
__version__ = "1"
@@ -59,8 +60,8 @@ makebackup = True
def usage(msg=None):
if msg is not None:
- print >> sys.stderr, msg
- print >> sys.stderr, __doc__
+ print(msg, file=sys.stderr)
+ print(__doc__, file=sys.stderr)
def errprint(*args):
sep = ""
@@ -75,7 +76,7 @@ def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "drnvh",
["dryrun", "recurse", "nobackup", "verbose", "help"])
- except getopt.error, msg:
+ except getopt.error as msg:
usage(msg)
return
for o, a in opts:
@@ -101,7 +102,7 @@ def main():
def check(file):
if os.path.isdir(file) and not os.path.islink(file):
if verbose:
- print "listing directory", file
+ print("listing directory", file)
names = os.listdir(file)
for name in names:
fullname = os.path.join(file, name)
@@ -113,10 +114,10 @@ def check(file):
return
if verbose:
- print "checking", file, "...",
+ print("checking", file, "...", end=' ')
try:
f = open(file)
- except IOError, msg:
+ except IOError as msg:
errprint("%s: I/O Error: %s" % (file, str(msg)))
return
@@ -124,24 +125,24 @@ def check(file):
f.close()
if r.run():
if verbose:
- print "changed."
+ print("changed.")
if dryrun:
- print "But this is a dry run, so leaving it alone."
+ 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
+ print("backed up", file, "to", bak)
f = open(file, "w")
r.write(f)
f.close()
if verbose:
- print "wrote new", file
+ print("wrote new", file)
return True
else:
if verbose:
- print "unchanged."
+ print("unchanged.")
return False
def _rstrip(line, JUNK='\n \t'):
@@ -262,7 +263,7 @@ class Reindenter:
return line
# Line-eater for tokenize.
- def tokeneater(self, type, token, (sline, scol), end, line,
+ def tokeneater(self, type, token, position, end, line,
INDENT=tokenize.INDENT,
DEDENT=tokenize.DEDENT,
NEWLINE=tokenize.NEWLINE,
@@ -285,7 +286,7 @@ class Reindenter:
elif type == COMMENT:
if self.find_stmt:
- self.stats.append((sline, -1))
+ self.stats.append((position[0], -1))
# but we're still looking for a new stmt, so leave
# find_stmt alone
@@ -298,7 +299,7 @@ class Reindenter:
# ENDMARKER.
self.find_stmt = 0
if line: # not endmarker
- self.stats.append((sline, self.level))
+ self.stats.append((position[0], self.level))
# Count number of leading blanks.
def getlspace(line):