diff --git a/.gitignore b/.gitignore index 298a9c370..be28908ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.pyc *.egg *.so +*.swp .dir-locals.el .ropeproject/ diff --git a/AUTHORS b/AUTHORS index f30631c42..e1e4e8a59 100644 --- a/AUTHORS +++ b/AUTHORS @@ -24,11 +24,12 @@ Other contributors, listed alphabetically, are: * Charles Duffy -- original graphviz extension * Kevin Dunn -- MathJax extension * Josip Dzolonga -- coverage builder +* Buck Evan -- dummy builder * Hernan Grecco -- search improvements * Horst Gutmann -- internationalization support * Martin Hans -- autodoc improvements * Doug Hellmann -- graphviz improvements -* Timotheus Kampik - stop words language fix +* Timotheus Kampik - JS enhancements, stop words language fix * Takeshi Komiya -- numref feature * Dave Kuhlman -- original LaTeX writer * Blaise Laflamme -- pyramid theme @@ -50,6 +51,7 @@ Other contributors, listed alphabetically, are: * Rob Ruana -- napoleon extension * Stefan Seefeld -- toctree improvements * Shibukawa Yoshiki -- pluggable search API and Japanese search +* Taku Shimizu -- epub3 builder * Antonio Valentino -- qthelp builder * Filip Vavera -- napoleon todo directive * Pauli Virtanen -- autodoc improvements, autosummary extension @@ -60,6 +62,7 @@ Other contributors, listed alphabetically, are: * Sebastian Wiesner -- image handling, distutils support * Michael Wilson -- Intersphinx HTTP basic auth support * Joel Wurtz -- cellspanning support in LaTeX +* Hong Xu -- svg support in imgmath extension and various bug fixes Many thanks for all contributions! diff --git a/CHANGES b/CHANGES index 8c935097d..96ebb2ec3 100644 --- a/CHANGES +++ b/CHANGES @@ -4,20 +4,55 @@ Release 1.4 (in development) Incompatible changes -------------------- +* Drop ``PorterStemmer`` package support. Use ``PyStemmer`` instead of ``PorterStemmer`` + to accelerate stemming. +* sphinx_rtd_theme has become optional. Please install it manually. + Refs #2087, #2086, #1845 and #2097. Thanks to Victor Zverovich. +* #2231: Use DUrole instead of DUspan for custom roles in LaTeX writer. It enables to take + title of roles as an argument of custom macros. +* #2022: 'Thumbs.db' and '.DS_Store' are added to `exclude_patterns` default values in + conf.py that will be provided on sphinx-quickstart. +* #2027, #2208: The ``html_title`` accepts string values only. And The None value cannot be + accepted. +* ``sphinx.ext.graphviz``: show graph image in inline by default +* #2060, #2224: The ``manpage`` role now generate ``sphinx.addnodes.manpage`` node instead + of ``sphinx.addnodes.literal_emphasis`` node. +* #2022: :confval:`html_extra_path` also copies dotfiles in the extra directory, and + refers to :confval:`exclude_patterns` to exclude extra files and directories. + Features added -------------- -* #2092: add todo directive support in napoleon package +* #2092: add todo directive support in napoleon package. * #1962: when adding directives, roles or nodes from an extension, warn if such an element is already present (built-in or added by another extension). * #1909: Add "doc" references to Intersphinx inventories. -* C++ type alias support (e.g., ``.. type:: T = int``) +* C++ type alias support (e.g., ``.. type:: T = int``). * C++ template support for classes, functions, type aliases, and variables (#1729, #1314). * C++, added new scope management directives ``namespace-push`` and ``namespace-pop``. +* #1970: Keyboard shortcuts to navigate Next and Previous topics * Intersphinx: Added support for fetching Intersphinx inventories with URLs - using HTTP basic auth + using HTTP basic auth. * C++, added support for template parameter in function info field lists. * C++, added support for pointers to member (function). +* #2113: Allow ``:class:`` option to code-block directive. +* #2192: Imgmath (pngmath with svg support). +* #2200: Support XeTeX and LuaTeX for the LaTeX builder. +* #1906: Use xcolor over color for \fcolorbox where available for LaTeX output. +* #2216: Texinputs makefile improvements. +* #2170: Support for Chinese language search index. +* #2214: Add sphinx.ext.githubpages to publish the docs on GitHub Pages +* #1030: Make page reference names for latex_show_pagerefs translatable +* #2162: Add Sphinx.add_source_parser() to add source_suffix and source_parsers from extension +* #2207: Add sphinx.parsers.Parser class; a base class for new parsers +* #656: Add ``graphviz_dot`` option to graphviz directives to switch the ``dot`` command +* #1939: Added the ``dummy`` builder: syntax check without output. +* #2230: Add ``math_number_all`` option to number all displayed math in math extensions +* #2235: ``needs_sphinx`` supports micro version comparison +* #2282: Add "language" attribute to html tag in the "basic" theme +* #1779: Add EPUB 3 builder +* #1751: Add :confval:`todo_link_only` to avoid file path and line indication on + :rst:dir:`todolist`. Bugs fixed ---------- @@ -28,10 +63,16 @@ Bugs fixed * C++, add missing support for virtual base classes (thanks to Rapptz). * C++, add support for final classes. * C++, fix parsing of types prefixed with 'enum'. -* #2023: Dutch search support uses Danish stemming info +* #2023: Dutch search support uses Danish stemming info. * C++, add support for user-defined literals. * #1804: Now html output wraps overflowed long-line-text in the sidebar. Thanks to Hassen ben tanfous. +* #2183: Fix porterstemmer causes ``make json`` to fail. +* #1899: Ensure list is sent to OptParse. +* #2164: Fix wrong check for pdftex inside sphinx.sty (for graphicx package option). +* #2165, #2218: Remove faulty and non-need conditional from sphinx.sty. +* Fix broken LaTeX code is generated if unknown language is given +* #1944: Fix rst_prolog breaks file-wide metadata Documentation ------------- @@ -39,15 +80,87 @@ Documentation * #1757: Fix for usage of :confval:`html_last_updated_fmt`. Thanks to Ralf Hemmecke. -Release 1.3.4 (in development) +Release 1.3.6 (in development) ============================== Bugs fixed ---------- + +Release 1.3.5 (released Jan 24, 2016) +===================================== + +Bugs fixed +---------- + +* Fix line numbers was not shown on warnings in LaTeX and texinfo builders +* Fix filenames were not shown on warnings of citations +* Fix line numbers was not shown on warnings in LaTeX and texinfo builders +* Fix line numbers was not shown on warnings of indices +* #2026: Fix LaTeX builder raises error if parsed-literal includes links +* #2243: Ignore strange docstring types for classes, do not crash +* #2247: Fix #2205 breaks make html for definition list with classifiers + that contains regular-expression like string +* #1565: Show warning if Pygments throws an ErrorToken +* #2211: Fix paragraphs in table cell doesn't work in Latex output +* #2253: ``:pyobject:`` option of ``literalinclude`` directive can't detect indented + body block when the block starts with blank or comment lines. +* Fix TOC is not shown when no ``:maxdepth:`` for toctrees (ref: #771) +* Fix warning message for ``:numref:`` if target is in orphaned doc (ref: #2244) + +Release 1.3.4 (released Jan 12, 2016) +===================================== + +Bugs fixed +---------- + * #2134: Fix figure caption with reference causes latex build error * #2094: Fix rubric with reference not working in Latex - +* #2147: Fix literalinclude code in latex does not break in pages +* #1833: Fix email addresses is showed again if latex_show_urls is not None +* #2176: sphinx.ext.graphviz: use instead of to embed svg +* #967: Fix SVG inheritance diagram is not hyperlinked (clickable) +* #1237: Fix footnotes not working in definition list in LaTeX +* #2168: Fix raw directive does not work for text writer +* #2171: Fix cannot linkcheck url with unicode +* #2182: LaTeX: support image file names with more than 1 dots +* #2189: Fix previous sibling link for first file in subdirectory uses last file, not + intended previous from root toctree +* #2003: Fix decode error under python2 (only) when ``make linkcheck`` is run +* #2186: Fix LaTeX output of \mathbb in math +* #1480, #2188: LaTeX: Support math in section titles +* #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug +* #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters +* #2193: Fix shutil.SameFileError if source directory and destination directory are same +* #2178: Fix unparseable C++ cross-reference when referencing a function with :cpp:any: +* #2206: Fix Sphinx latex doc build failed due to a footnotes +* #2201: Fix wrong table caption for tables with over 30 rows +* #2213: Set
in the classic theme to fit with

+* #1815: Fix linkcheck does not raise an exception if warniserror set to true and link is + broken +* #2197: Fix slightly cryptic error message for missing index.rst file +* #1894: Unlisted phony targets in quickstart Makefile +* #2125: Fix unifies behavior of collapsed fields (``GroupedField`` and ``TypedField``) +* #1408: Check latex_logo validity before copying +* #771: Fix latex output doesn't set tocdepth +* #1820: On Windows, console coloring is broken with colorama version 0.3.3. + Now sphinx use colorama>=0.3.5 to avoid this problem. +* #2072: Fix footnotes in chapter-titles do not appear in PDF output +* #1580: Fix paragraphs in longtable don't work in Latex output +* #1366: Fix centered image not centered in latex +* #1860: Fix man page using ``:samp:`` with braces - font doesn't reset +* #1610: Sphinx crashes in japanese indexing in some systems +* Fix Sphinx crashes if mecab initialization failed +* #2160: Fix broken TOC of PDFs if section includes an image +* #2172: Fix dysfunctional admonition \py@lightbox in sphinx.sty. Thanks to jfbu. +* #2198,#2205: ``make gettext`` generate broken msgid for definition lists. +* #2062: Escape characters in doctests are treated incorrectly with Python 2. +* #2225: Fix if the option does not begin with dash, linking is not performed +* #2226: Fix math is not HTML-encoded when :nowrap: is given (jsmath, mathjax) +* #1601, #2220: 'any' role breaks extended domains behavior. Affected extensions doesn't + support resolve_any_xref and resolve_xref returns problematic node instead of None. + sphinxcontrib-httpdomain is one of them. +* #2229: Fix no warning is given for unknown options Release 1.3.3 (released Dec 2, 2015) ==================================== @@ -55,6 +168,7 @@ Release 1.3.3 (released Dec 2, 2015) Bugs fixed ---------- +* #2177: Fix parallel hangs * #2012: Fix exception occurred if ``numfig_format`` is invalid * #2142: Provide non-minified JS code in ``sphinx/search/non-minified-js/*.js`` for source distribution on PyPI. @@ -101,11 +215,7 @@ Bugs fixed * #1923: Use babel features only if the babel latex element is nonempty. * #1942: Fix a KeyError in websupport. * #1903: Fix strange id generation for glossary terms. -* #1796, On py3, automated .mo building cause UnicodeDecodeError -* Fix: ``make text`` will crush if a definition list item has more than 1 classifiers as: -* #1796: On py3, automated .mo building cause UnicodeDecodeError * ``make text`` will crush if a definition list item has more than 1 classifiers as: -* Fixed #1855: make gettext generates broken po file for definition lists with classifier. ``term : classifier1 : classifier2``. * #1855: make gettext generates broken po file for definition lists with classifier. * #1869: Fix problems when dealing with files containing non-ASCII characters. Thanks to @@ -120,6 +230,8 @@ Bugs fixed * #1994: More supporting non-standard parser (like recommonmark parser) for Translation and WebSupport feature. Now node.rawsource is fall backed to node.astext() during docutils transforming. +* #1989: "make blahblah" on Windows indicate help messages for sphinx-build every time. + It was caused by wrong make.bat that generated by Sphinx-1.3.0/1.3.1. * On Py2 environment, conf.py that is generated by sphinx-quickstart should have u prefixed config value for 'version' and 'release'. * #2102: On Windows + Py3, using ``|today|`` and non-ASCII date format will raise @@ -132,7 +244,7 @@ Bugs fixed Suzumizaki. * #1818: `sphinx.ext.todo` directive generates broken html class attribute as 'admonition-' when :confval:`language` is specified with non-ASCII linguistic area like - 'ru' or 'ja'. To fix this, now ``todo`` directive can use ```:class:`` option. + 'ru' or 'ja'. To fix this, now ``todo`` directive can use ``:class:`` option. * #2140: Fix footnotes in table has broken in LaTeX * #2127: MecabBinder for html searching feature doesn't work with Python 3. Thanks to Tomoko Uchida. @@ -612,7 +724,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 - `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 @@ -941,13 +1053,12 @@ Features added * Command-line interfaces: - PR#75: Added ``--follow-links`` option to sphinx-apidoc. - - #869: sphinx-build now has the option :option:`-T` for printing the full + - #869: sphinx-build now has the option ``-T`` for printing the full traceback after an unhandled exception. - - sphinx-build now supports the standard :option:`--help` and - :option:`--version` options. + - sphinx-build now supports the standard ``--help`` and ``--version`` options. - sphinx-build now provides more specific error messages when called with invalid options or arguments. - - sphinx-build now has a verbose option :option:`-v` which can be repeated for + - sphinx-build now has a verbose option ``-v`` which can be repeated for 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. @@ -969,7 +1080,7 @@ Features added stemming routines. Saves about 20 seconds when building the Python documentation. - PR#108: Add experimental support for parallel building with a new - :option:`-j` option. + :option:`sphinx-build -j` option. Documentation ------------- @@ -1231,7 +1342,7 @@ Features added indicators. - #367: Added automatic exclusion of hidden members in inheritance diagrams, and an option to selectively enable it. - - Added `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. @@ -1559,7 +1670,7 @@ Features added * General: - Added a "nitpicky" mode that emits warnings for all missing - references. It is activated by the :option:`-n` command-line switch + references. It is activated by the :option:`sphinx-build -n` command-line switch or the `nitpicky` config value. - Added ``latexpdf`` target in quickstart Makefile. diff --git a/LICENSE b/LICENSE index 4944ef5a1..8f9e7f1ac 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ License for Sphinx ================== -Copyright (c) 2007-2015 by the Sphinx team (see AUTHORS file). +Copyright (c) 2007-2016 by the Sphinx team (see AUTHORS file). All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/doc/_templates/index.html b/doc/_templates/index.html index ccef89a78..4c23114db 100644 --- a/doc/_templates/index.html +++ b/doc/_templates/index.html @@ -62,11 +62,11 @@

{%trans%} - You can also download PDF versions of the Sphinx documentation: - a version generated from + You can also download PDF/EPUB versions of the Sphinx documentation: + a PDF version generated from the LaTeX Sphinx produces, and - a version generated - by rst2pdf.{%endtrans%} + a EPUB version. + {%endtrans%}

{%trans%}Examples{%endtrans%}

diff --git a/doc/_templates/indexsidebar.html b/doc/_templates/indexsidebar.html index 56094809f..b6f12f031 100644 --- a/doc/_templates/indexsidebar.html +++ b/doc/_templates/indexsidebar.html @@ -14,15 +14,7 @@

{%trans%}Current version: {{ version }}{%endtrans%}

{%trans%}Get Sphinx from the Python Package Index, or install it with:{%endtrans%}

-{% if version.split('b')|length > 1 %} -
pip install Sphinx=={{ version }}
-

{%trans%}Stable version docs -are also available.{%endtrans%}

-{% else %}
pip install -U Sphinx
-

{%trans%}Latest development version docs -are also available.{%endtrans%}

-{% endif %} {% endif %}

{%trans%}Questions? Suggestions?{%endtrans%}

diff --git a/doc/_themes/sphinx13/layout.html b/doc/_themes/sphinx13/layout.html index 0e6294cc4..bf28cd089 100644 --- a/doc/_themes/sphinx13/layout.html +++ b/doc/_themes/sphinx13/layout.html @@ -4,7 +4,7 @@ Sphinx layout template for the sphinxdoc theme. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/doc/_themes/sphinx13/static/sphinx13.css b/doc/_themes/sphinx13/static/sphinx13.css index 222432d5c..8b3ebdf3a 100644 --- a/doc/_themes/sphinx13/static/sphinx13.css +++ b/doc/_themes/sphinx13/static/sphinx13.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- sphinx13 theme. * - * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/doc/builders.rst b/doc/builders.rst index 93e01e4b7..cc9c9f3e8 100644 --- a/doc/builders.rst +++ b/doc/builders.rst @@ -140,6 +140,26 @@ The builder's "name" must be given to the **-b** command-line option of .. autoattribute:: supported_image_types +.. module:: sphinx.builders.epub3 +.. class:: Epub3Builder + + This builder produces the same output as the standalone HTML builder, but + also generates an *epub* file for ebook readers. See :ref:`epub-faq` for + details about it. For definition of the epub format, have a look at + ``_ or ``_. + The builder creates *EPUB 3* files. + + This builder is still *experimental* because it can't generate valid EPUB 3 + files. + + .. autoattribute:: name + + .. autoattribute:: format + + .. autoattribute:: supported_image_types + + .. versionadded:: 1.4 + .. module:: sphinx.builders.latex .. class:: LaTeXBuilder @@ -341,6 +361,18 @@ for details. .. autoattribute:: supported_image_types +.. module:: sphinx.builders.dummy +.. class:: DummyBuilder + + This builder produces no output. The input is only parsed and checked for + consistency. This is useful for linting purposes. + + .. autoattribute:: name + + .. autoattribute:: supported_image_types + + .. versionadded:: 1.4 + .. module:: sphinx.builders.linkcheck .. class:: CheckExternalLinksBuilder diff --git a/doc/conf.py b/doc/conf.py index 22ab60972..753ffab4c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -15,7 +15,7 @@ templates_path = ['_templates'] exclude_patterns = ['_build'] project = 'Sphinx' -copyright = '2007-2015, Georg Brandl and the Sphinx team' +copyright = '2007-2016, Georg Brandl and the Sphinx team' version = sphinx.__released__ release = version show_authors = True diff --git a/doc/config.rst b/doc/config.rst index a95201f66..58f04c895 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -96,8 +96,11 @@ General configuration If given, a dictionary of parser classes for different source suffices. The keys are the suffix, the values can be either a class or a string giving a - fully-qualified name of a parser class. Files with a suffix that is not in - the dictionary will be parsed with the default reStructuredText parser. + fully-qualified name of a parser class. The parser class can be either + ``docutils.parsers.Parser`` or :class:`sphinx.parsers.Parser`. Files with a + suffix that is not in the dictionary will be parsed with the default + reStructuredText parser. + For example:: @@ -128,7 +131,7 @@ General configuration :confval:`exclude_dirnames`) :confval:`exclude_patterns` is also consulted when looking for static files - in :confval:`html_static_path`. + in :confval:`html_static_path` and :confval:`html_extra_path`. .. versionadded:: 1.0 @@ -217,6 +220,9 @@ General configuration .. versionadded:: 1.0 + .. versionchanged:: 1.4 + also accepts micro version string + .. confval:: needs_extensions This value can be a dictionary specifying version requirements for extensions @@ -234,7 +240,7 @@ General configuration If true, Sphinx will warn about *all* references where the target cannot be found. Default is ``False``. You can activate this mode temporarily using - the :option:`-n` command-line switch. + the :option:`-n ` command-line switch. .. versionadded:: 1.0 @@ -453,7 +459,7 @@ documentation on :ref:`intl` for details. this path are searched by the standard :mod:`gettext` module. Internal messages are fetched from a text domain of ``sphinx``; so if you - add the directory :file:`./locale` to this settting, the message catalogs + add the directory :file:`./locale` to this setting, the message catalogs (compiled from ``.po`` format using :program:`msgfmt`) must be in :file:`./locale/{language}/LC_MESSAGES/sphinx.mo`. The text domain of individual documents depends on :confval:`gettext_compact`. @@ -565,8 +571,7 @@ that use Sphinx's HTMLWriter class. The "title" for HTML documentation generated with Sphinx's own templates. This is appended to the ```` tag of individual pages, and used in the navigation bar as the "topmost" element. It defaults to :samp:`'{<project>} - v{<revision>} documentation'` (with the values coming from the config - values). + v{<revision>} documentation'`. .. confval:: html_short_title @@ -580,7 +585,7 @@ that use Sphinx's HTMLWriter class. A dictionary of values to pass into the template engine's context for all pages. Single values can also be put in this dictionary using the - :option:`-A` command-line option of ``sphinx-build``. + :option:`-A <sphinx-build -A>` command-line option of ``sphinx-build``. .. versionadded:: 0.5 @@ -635,6 +640,11 @@ that use Sphinx's HTMLWriter class. .. versionadded:: 1.2 + .. versionchanged:: 1.4 + The dotfiles in the extra directory will be copied to the output directory. + And it refers :confval:`exclude_patterns` on copying extra files and + directories, and ignores if path matches to patterns. + .. confval:: html_last_updated_fmt If this is not None, a 'Last updated on:' timestamp is inserted @@ -874,6 +884,7 @@ that use Sphinx's HTMLWriter class. * ``es`` -- Spanish * ``sv`` -- Swedish * ``tr`` -- Turkish + * ``zh`` -- Chinese .. admonition:: Accelerating build speed @@ -908,6 +919,12 @@ that use Sphinx's HTMLWriter class. .. versionadded:: 1.1 + + The Chinese support has these options: + + * ``dict`` -- the ``jieba`` dictionary path if want to use + custom dictionary. + .. confval:: html_search_scorer The name of a JavaScript file (relative to the configuration directory) that @@ -1128,11 +1145,25 @@ the `Dublin Core metadata <http://dublincore.org/>`_. The title of the document. It defaults to the :confval:`html_title` option but can be set independently for epub creation. +.. confval:: epub3_description + + The description of the document. The default value is ``''``. + + .. versionadded:: 1.4 + .. confval:: epub_author The author of the document. This is put in the Dublin Core metadata. The default value is ``'unknown'``. +.. confval:: epub3_contributor + + The name of a person, organization, etc. that played a secondary role in + the creation of the content of an EPUB Publication. The default value is + ``'unknown'``. + + .. versionadded:: 1.4 + .. confval:: epub_language The language of the document. This is put in the Dublin Core metadata. The @@ -1288,6 +1319,14 @@ the `Dublin Core metadata <http://dublincore.org/>`_. .. versionadded:: 1.2 +.. confval:: epub3_page_progression_direction + + The global direction in which the content flows. + Allowed values are ltr (left-to-right), rtl (right-to-left) and default. + The default value is ``'ltr'``. + + .. versionadded:: 1.4 + .. _latex-options: Options for LaTeX output @@ -1432,6 +1471,8 @@ These options influence LaTeX output. '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. + + .. versionadded:: 1.3 ``'footer'`` Additional footer content (before the indices), default empty. diff --git a/doc/domains.rst b/doc/domains.rst index e7bfc1a53..803a4343c 100644 --- a/doc/domains.rst +++ b/doc/domains.rst @@ -594,7 +594,7 @@ a visibility statement (``public``, ``private`` or ``protected``). .. rst:directive:: .. cpp:member:: (member) variable declaration .. cpp:var:: (member) variable declaration - Describe a varible or member variable, e.g.,:: + Describe a variable or member variable, e.g.,:: .. cpp:member:: std::string MyClass::myMember @@ -671,7 +671,7 @@ a visibility statement (``public``, ``private`` or ``protected``). Namespacing ~~~~~~~~~~~~~~~~~ -Declarations in the C++ doamin are as default placed in global scope. +Declarations in the C++ domain are as default placed in global scope. The current scope can be changed using three namespace directives. They manage a stack declarations where ``cpp:namespace`` resets the stack and changes a given scope. diff --git a/doc/ext/githubpages.rst b/doc/ext/githubpages.rst new file mode 100644 index 000000000..0cd76a2c9 --- /dev/null +++ b/doc/ext/githubpages.rst @@ -0,0 +1,12 @@ +.. highlight:: rest + +:mod:`sphinx.ext.githubpages` -- Publish HTML docs in GitHub Pages +================================================================== + +.. module:: sphinx.ext.githubpages + :synopsis: Publish HTML docs in GitHub Pages + +.. versionadded:: 1.4 + +This extension creates ``.nojekyll`` file on generated HTML directory to publish +the document on GitHub Pages. diff --git a/doc/ext/graphviz.rst b/doc/ext/graphviz.rst index d5a5969f4..ca34fa281 100644 --- a/doc/ext/graphviz.rst +++ b/doc/ext/graphviz.rst @@ -87,6 +87,15 @@ It adds these directives: caption to the diagram. Naturally, diagrams marked as "inline" cannot have a caption. +.. deprecated:: 1.4 + ``inline`` option is deprecated. + All three directives generate inline node by default. If ``caption`` is given, + these generate block node instead. + +.. versionchanged:: 1.4 + All three directives support a ``graphviz_dot`` option that can be switch the + ``dot`` command within the directive. + There are also these new config values: .. confval:: graphviz_dot @@ -97,8 +106,8 @@ There are also these new config values: Since this setting is not portable from system to system, it is normally not useful to set it in ``conf.py``; rather, giving it on the - :program:`sphinx-build` command line via the :option:`-D` option should be - preferable, like this:: + :program:`sphinx-build` command line via the :option:`-D <sphinx-build -D>` + option should be preferable, like this:: sphinx-build -b html -D graphviz_dot=C:\graphviz\bin\dot.exe . _build/html @@ -111,7 +120,18 @@ There are also these new config values: .. confval:: graphviz_output_format The output format for Graphviz when building HTML files. This must be either - ``'png'`` or ``'svg'``; the default is ``'png'``. + ``'png'`` or ``'svg'``; the default is ``'png'``. If ``'svg'`` is used, in + order to make the URL links work properly, an appropriate ``target`` + attribute must be set, such as ``"_top"`` and ``"_blank"``. For example, the + link in the following graph should work in the svg output: :: + + .. graphviz:: + + digraph example { + a [label="sphinx", href="http://sphinx-doc.org", target="_top"]; + b [label="other"]; + a -> b; + } .. versionadded:: 1.0 Previously, output always was PNG. diff --git a/doc/ext/math.rst b/doc/ext/math.rst index 4c1546109..61fa0ca83 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -4,7 +4,7 @@ Math support in Sphinx ====================== .. module:: sphinx.ext.mathbase - :synopsis: Common math support for pngmath and mathjax / jsmath. + :synopsis: Common math support for imgmath and mathjax / jsmath. .. versionadded:: 0.5 @@ -17,7 +17,7 @@ support extensions should, if possible, reuse that support too. .. note:: :mod:`.mathbase` is not meant to be added to the :confval:`extensions` config - value, instead, use either :mod:`sphinx.ext.pngmath` or + value, instead, use either :mod:`sphinx.ext.imgmath` or :mod:`sphinx.ext.mathjax` as described below. The input language for mathematics is LaTeX markup. This is the de-facto @@ -28,6 +28,13 @@ Keep in mind that when you put math markup in **Python docstrings** read by :mod:`autodoc <sphinx.ext.autodoc>`, you either have to double all backslashes, or use Python raw strings (``r"raw"``). +:mod:`.mathbase` provides the following config values: + +.. confval:: math_number_all + + Set this option to ``True`` if you want all displayed math to be numbered. + The default is ``False``. + :mod:`.mathbase` defines these new markup elements: .. rst:role:: math @@ -96,20 +103,27 @@ or use Python raw strings (``r"raw"``). beautiful mathematical formulas. -:mod:`sphinx.ext.pngmath` -- Render math as PNG images ------------------------------------------------------- +:mod:`sphinx.ext.imgmath` -- Render math as images +-------------------------------------------------- -.. module:: sphinx.ext.pngmath - :synopsis: Render math as PNG images. +.. module:: sphinx.ext.imgmath + :synopsis: Render math as PNG or SVG images. -This extension renders math via LaTeX and dvipng_ into PNG images. This of -course means that the computer where the docs are built must have both programs -available. +.. versionadded:: 1.4 + +This extension renders math via LaTeX and dvipng_ or dvisvgm_ into PNG or SVG +images. This of course means that the computer where the docs are built must +have both programs available. There are various config values you can set to influence how the images are built: -.. confval:: pngmath_latex +.. confval:: imgmath_image_format + + The output image format. The default is ``'png'``. It should be either + ``'png'`` or ``'svg'``. + +.. confval:: imgmath_latex The command name with which to invoke LaTeX. The default is ``'latex'``; you may need to set this to a full path if ``latex`` is not in the executable @@ -117,45 +131,54 @@ built: Since this setting is not portable from system to system, it is normally not useful to set it in ``conf.py``; rather, giving it on the - :program:`sphinx-build` command line via the :option:`-D` option should be - preferable, like this:: + :program:`sphinx-build` command line via the :option:`-D <sphinx-build -D>` + option should be preferable, like this:: - sphinx-build -b html -D pngmath_latex=C:\tex\latex.exe . _build/html + sphinx-build -b html -D imgmath_latex=C:\tex\latex.exe . _build/html - .. versionchanged:: 0.5.1 - This value should only contain the path to the latex executable, not - further arguments; use :confval:`pngmath_latex_args` for that purpose. + This value should only contain the path to the latex executable, not further + arguments; use :confval:`imgmath_latex_args` for that purpose. -.. confval:: pngmath_dvipng +.. confval:: imgmath_dvipng The command name with which to invoke ``dvipng``. The default is ``'dvipng'``; you may need to set this to a full path if ``dvipng`` is not in - the executable search path. + the executable search path. This option is only used when + ``imgmath_image_format`` is set to ``'png'``. -.. confval:: pngmath_latex_args +.. confval:: imgmath_dvisvgm + + The command name with which to invoke ``dvisvgm``. The default is + ``'dvisvgm'``; you may need to set this to a full path if ``dvisvgm`` is not + in the executable search path. This option is only used when + ``imgmath_image_format`` is ``'svg'``. + +.. confval:: imgmath_latex_args Additional arguments to give to latex, as a list. The default is an empty list. - .. versionadded:: 0.5.1 - -.. confval:: pngmath_latex_preamble +.. confval:: imgmath_latex_preamble Additional LaTeX code to put into the preamble of the short LaTeX files that are used to translate the math snippets. This is empty by default. Use it e.g. to add more packages whose commands you want to use in the math. -.. confval:: pngmath_dvipng_args +.. confval:: imgmath_dvipng_args Additional arguments to give to dvipng, as a list. The default value is ``['-gamma', '1.5', '-D', '110', '-bg', 'Transparent']`` which makes the image a bit darker and larger then it is by default, and produces PNGs with a - transparent background. + transparent background. This option is used only when + ``imgmath_image_format`` is ``'png'``. - .. versionchanged:: 1.2 - Now includes ``-bg Transparent`` by default. +.. confval:: imgmath_dvisvgm_args -.. confval:: pngmath_use_preview + Additional arguments to give to dvisvgm, as a list. The default value is + ``['--no-fonts']``. This option is used only when ``imgmath_image_format`` + is ``'svg'``. + +.. confval:: imgmath_use_preview ``dvipng`` has the ability to determine the "depth" of the rendered text: for example, when typesetting a fraction inline, the baseline of surrounding text @@ -165,14 +188,20 @@ built: ``vertical-align`` style that correctly aligns the baselines. Unfortunately, this only works when the `preview-latex package`_ is - installed. Therefore, the default for this option is ``False``. + installed. Therefore, the default for this option is ``False``. -.. confval:: pngmath_add_tooltips + Currently this option is only used when ``imgmath_image_format`` is + ``'png'``. + +.. confval:: imgmath_add_tooltips Default: ``True``. If false, do not add the LaTeX code as an "alt" attribute for math images. - .. versionadded:: 1.1 +.. confval:: imgmath_font_size + + The font size (in ``pt``) of the displayed math. The default value is + ``12``. It must be a positive integer. :mod:`sphinx.ext.mathjax` -- Render math via JavaScript @@ -235,6 +264,7 @@ package jsMath_. It provides this config value: .. _dvipng: http://savannah.nongnu.org/projects/dvipng/ +.. _dvisvgm: http://dvisvgm.bplaced.net/ .. _MathJax: http://www.mathjax.org/ .. _jsMath: http://www.math.union.edu/~dpvc/jsmath/ .. _preview-latex package: http://www.gnu.org/software/auctex/preview-latex.html diff --git a/doc/ext/todo.rst b/doc/ext/todo.rst index 8ab6eb37a..a809bc665 100644 --- a/doc/ext/todo.rst +++ b/doc/ext/todo.rst @@ -33,3 +33,11 @@ There is also an additional config value: If this is ``True``, :rst:dir:`todo` and :rst:dir:`todolist` produce output, else they produce nothing. The default is ``False``. + +.. confval:: todo_link_only + + If this is ``True``, :rst:dir:`todolist` produce output without file path and line, + The default is ``False``. + + .. versionadded:: 1.4 + diff --git a/doc/ext/viewcode.rst b/doc/ext/viewcode.rst index f2b6c9283..5bf8eb033 100644 --- a/doc/ext/viewcode.rst +++ b/doc/ext/viewcode.rst @@ -15,11 +15,7 @@ a highlighted version of the source code, and a link will be added to all object descriptions that leads to the source code of the described object. A link back from the source to the description will also be inserted. -There are currently no configuration values for this extension; you just need to -add ``'sphinx.ext.viewcode'`` to your :confval:`extensions` value for it to -work. - -There is also an additional config value: +There is an additional config value: .. confval:: viewcode_import diff --git a/doc/extdev/appapi.rst b/doc/extdev/appapi.rst index 2c85d44be..11fa35294 100644 --- a/doc/extdev/appapi.rst +++ b/doc/extdev/appapi.rst @@ -155,7 +155,7 @@ package. add_directive('literalinclude', literalinclude_directive, content = 0, arguments = (1, 0, 0), linenos = directives.flag, - language = direcitves.unchanged, + language = directives.unchanged, encoding = directives.encoding) .. versionchanged:: 0.6 @@ -340,6 +340,12 @@ package. .. versionadded:: 1.1 +.. method:: Sphinx.add_source_parser(name, suffix, parser) + + Register a parser class for specified *suffix*. + + .. versionadded:: 1.4 + .. method:: Sphinx.require_sphinx(version) Compare *version* (which must be a ``major.minor`` version string, diff --git a/doc/extdev/envapi.rst b/doc/extdev/envapi.rst index 84ad3e0d9..729725fc5 100644 --- a/doc/extdev/envapi.rst +++ b/doc/extdev/envapi.rst @@ -17,7 +17,11 @@ Build environment API .. attribute:: srcdir - Source directory (the directory containing ``conf.py``). + Source directory. + + .. attribute:: confdir + + Directory containing ``conf.py``. .. attribute:: doctreedir diff --git a/doc/extdev/index.rst b/doc/extdev/index.rst index 5144c5f8b..b27db4b2d 100644 --- a/doc/extdev/index.rst +++ b/doc/extdev/index.rst @@ -52,4 +52,5 @@ APIs used for writing extensions builderapi markupapi domainapi + parserapi nodes diff --git a/doc/extdev/parserapi.rst b/doc/extdev/parserapi.rst new file mode 100644 index 000000000..7008a15a8 --- /dev/null +++ b/doc/extdev/parserapi.rst @@ -0,0 +1,8 @@ +.. _parser-api: + +Parser API +========== + +.. module:: sphinx.parsers + +.. autoclass:: Parser diff --git a/doc/extensions.rst b/doc/extensions.rst index 8347f4965..47632e593 100644 --- a/doc/extensions.rst +++ b/doc/extensions.rst @@ -32,6 +32,7 @@ These extensions are built in and can be activated by respective entries in the ext/viewcode ext/linkcode ext/napoleon + ext/githubpages Third-party extensions diff --git a/doc/intl.rst b/doc/intl.rst index a358c436a..bd4f9e889 100644 --- a/doc/intl.rst +++ b/doc/intl.rst @@ -63,7 +63,7 @@ be translated you need to follow these instructions: msgfmt "usage.po" -o "locale/es/LC_MESSAGES/usage.mo" * Set :confval:`locale_dirs` to ``["locale/"]``. -* Set :confval:`language` to ``es`` (also possible via :option:`-D`). +* Set :confval:`language` to ``es`` (also possible via :option:`-D <sphinx-build -D>`). * Run your desired build. diff --git a/doc/invocation.rst b/doc/invocation.rst index 1d0c613c3..8fe01bf8d 100644 --- a/doc/invocation.rst +++ b/doc/invocation.rst @@ -100,9 +100,9 @@ Extension options Enable `sphinx.ext.coverage` extension. -.. option:: --ext-pngmath +.. option:: --ext-imgmath - Enable `sphinx.ext.pngmath` extension. + Enable `sphinx.ext.imgmath` extension. .. option:: --ext-mathjax diff --git a/doc/markup/inline.rst b/doc/markup/inline.rst index 10db17d79..0e825b66a 100644 --- a/doc/markup/inline.rst +++ b/doc/markup/inline.rst @@ -242,9 +242,8 @@ objects: .. rst:role:: option - A command-line option to an executable program. The leading hyphen(s) must - be included. This generates a link to a :rst:dir:`option` directive, if it - exists. + A command-line option to an executable program. This generates a link to + a :rst:dir:`option` directive, if it exists. The following role creates a cross-reference to a term in a diff --git a/doc/rest.rst b/doc/rest.rst index c6a4ada04..9fca31b6e 100644 --- a/doc/rest.rst +++ b/doc/rest.rst @@ -223,8 +223,10 @@ as long as the text:: ================= Normally, there are no heading levels assigned to certain characters as the -structure is determined from the succession of headings. However, for the -Python documentation, this convention is used which you may follow: +structure is determined from the succession of headings. However, this +convention is used in `Python's Style Guide for documentating +<https://docs.python.org/devguide/documenting.html#style-guide>`_ which you may +follow: * ``#`` with overline, for parts * ``*`` with overline, for chapters diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 95bd61ebc..385746f72 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -122,8 +122,9 @@ this:: $ sphinx-build -b html sourcedir builddir where *sourcedir* is the :term:`source directory`, and *builddir* is the -directory in which you want to place the built documentation. The :option:`-b` -option selects a builder; in this example Sphinx will build HTML files. +directory in which you want to place the built documentation. +The :option:`-b <sphinx-build -b>` option selects a builder; in this example +Sphinx will build HTML files. |more| See :ref:`invocation` for all options that :program:`sphinx-build` supports. diff --git a/doc/web/quickstart.rst b/doc/web/quickstart.rst index 996942db6..1611774c1 100644 --- a/doc/web/quickstart.rst +++ b/doc/web/quickstart.rst @@ -135,7 +135,7 @@ add this data to the ``COMMENT_OPTIONS`` that are used in the template. .. note:: - This only works works if your documentation is served from your + This only works if your documentation is served from your document root. If it is served from another directory, you will need to prefix the url route with that directory, and give the `docroot` keyword argument when creating the web support object:: diff --git a/setup.py b/setup.py index cc977f50f..6d1ae2de4 100644 --- a/setup.py +++ b/setup.py @@ -53,12 +53,11 @@ requires = [ 'snowballstemmer>=1.1', 'babel>=1.3,!=2.0', 'alabaster>=0.7,<0.8', - 'sphinx_rtd_theme>=0.1,<2.0', ] extras_require = { # Environment Marker works for wheel 0.24 or later ':sys_platform=="win32"': [ - 'colorama', + 'colorama>=0.3.5', ], 'websupport': [ 'sqlalchemy>=0.9', @@ -73,7 +72,7 @@ extras_require = { # for sdist installation with pip-1.5.6 if sys.platform == 'win32': - requires.append('colorama') + requires.append('colorama>=0.3.5') # Provide a "compile_catalog" command that also creates the translated # JavaScript files if Babel is available. diff --git a/sphinx-apidoc.py b/sphinx-apidoc.py index 7752fc0d1..56394ea96 100755 --- a/sphinx-apidoc.py +++ b/sphinx-apidoc.py @@ -4,7 +4,7 @@ Sphinx - Python documentation toolchain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx-autogen.py b/sphinx-autogen.py index ea085573f..bcb630855 100755 --- a/sphinx-autogen.py +++ b/sphinx-autogen.py @@ -4,7 +4,7 @@ Sphinx - Python documentation toolchain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx-build.py b/sphinx-build.py index 7c539d643..ab7919dbb 100755 --- a/sphinx-build.py +++ b/sphinx-build.py @@ -4,7 +4,7 @@ Sphinx - Python documentation toolchain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx-quickstart.py b/sphinx-quickstart.py index 89ad8f891..fcc594132 100755 --- a/sphinx-quickstart.py +++ b/sphinx-quickstart.py @@ -4,7 +4,7 @@ Sphinx - Python documentation toolchain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/__init__.py b/sphinx/__init__.py index 1abbd23aa..71401fab8 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -5,7 +5,7 @@ The Sphinx documentation toolchain. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/__main__.py b/sphinx/__main__.py index cd19db393..42022bf50 100644 --- a/sphinx/__main__.py +++ b/sphinx/__main__.py @@ -5,7 +5,7 @@ The Sphinx documentation toolchain. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import sys diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py index b30bd40ae..3ff5772ca 100644 --- a/sphinx/addnodes.py +++ b/sphinx/addnodes.py @@ -5,7 +5,7 @@ Additional docutils nodes. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -212,6 +212,10 @@ class termsep(nodes.Structural, nodes.Element): """Separates two terms within a <term> node.""" +class manpage(nodes.Inline, nodes.TextElement): + """Node for references to manpages.""" + + # make the new nodes known to docutils; needed because the HTML writer will # choke at some point if these are not added nodes._add_node_class_names(k for k in globals().keys() diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py index 805e862c9..58724fd5a 100644 --- a/sphinx/apidoc.py +++ b/sphinx/apidoc.py @@ -11,7 +11,7 @@ Copyright 2008 Société des arts technologiques (SAT), http://www.sat.qc.ca/ - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function @@ -20,6 +20,7 @@ import os import sys import optparse from os import path +from six import binary_type from sphinx.util.osutil import walk from sphinx import __display_version__ @@ -369,6 +370,15 @@ Note: By default this script will not overwrite already created files.""") mastertoctree = text, language = 'en', ) + if isinstance(opts.header, binary_type): + d['project'] = d['project'].decode('utf-8') + if isinstance(opts.author, binary_type): + d['author'] = d['author'].decode('utf-8') + if isinstance(opts.version, binary_type): + d['version'] = d['version'].decode('utf-8') + if isinstance(opts.release, binary_type): + d['release'] = d['release'].decode('utf-8') + if not opts.dryrun: qs.generate(d, silent=True, overwrite=opts.force) elif not opts.notoc: diff --git a/sphinx/application.py b/sphinx/application.py index c9d5338f5..e257df19c 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -7,7 +7,7 @@ Gracefully adapted from the TextPress system by Armin. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function @@ -77,6 +77,7 @@ class Sphinx(object): self.next_listener_id = 0 self._extensions = {} self._extension_metadata = {} + self._additional_source_parsers = {} self._listeners = {} self._setting_up_extension = ['?'] self.domains = BUILTIN_DOMAINS.copy() @@ -161,7 +162,7 @@ class Sphinx(object): # check the Sphinx version if requested if self.config.needs_sphinx and \ - self.config.needs_sphinx > sphinx.__display_version__[:3]: + self.config.needs_sphinx > sphinx.__display_version__: raise VersionRequirementError( 'This project needs at least Sphinx v%s and therefore cannot ' 'be built with this version.' % self.config.needs_sphinx) @@ -185,6 +186,8 @@ class Sphinx(object): self._init_i18n() # check all configuration values for permissible types self.config.check_types(self.warn) + # set up source_parsers + self._init_source_parsers() # set up the build environment self._init_env(freshenv) # set up the builder @@ -211,6 +214,13 @@ class Sphinx(object): else: self.info('not available for built-in messages') + def _init_source_parsers(self): + for suffix, parser in iteritems(self._additional_source_parsers): + if suffix not in self.config.source_suffix: + self.config.source_suffix.append(suffix) + if suffix not in self.config.source_parsers: + self.config.source_parsers[suffix] = parser + def _init_env(self, freshenv): if freshenv: self.env = BuildEnvironment(self.srcdir, self.doctreedir, @@ -757,6 +767,10 @@ class Sphinx(object): assert issubclass(cls, SearchLanguage) languages[cls.lang] = cls + def add_source_parser(self, suffix, parser): + self.debug('[app] adding search source_parser: %r, %r', (suffix, parser)) + self._additional_source_parsers[suffix] = parser + class TemplateBridge(object): """ diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index eebd6af64..38e009a8f 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -5,7 +5,7 @@ Builder superclass for all builders. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -14,9 +14,8 @@ from os import path try: import multiprocessing - import threading except ImportError: - multiprocessing = threading = None + multiprocessing = None from docutils import nodes @@ -451,6 +450,7 @@ class Builder(object): return getattr(self.config, optname) BUILTIN_BUILDERS = { + 'dummy': ('dummy', 'DummyBuilder'), 'html': ('html', 'StandaloneHTMLBuilder'), 'dirhtml': ('html', 'DirectoryHTMLBuilder'), 'singlehtml': ('html', 'SingleFileHTMLBuilder'), @@ -462,6 +462,7 @@ BUILTIN_BUILDERS = { 'qthelp': ('qthelp', 'QtHelpBuilder'), 'applehelp': ('applehelp', 'AppleHelpBuilder'), 'epub': ('epub', 'EpubBuilder'), + 'epub3': ('epub3', 'Epub3Builder'), 'latex': ('latex', 'LaTeXBuilder'), 'text': ('text', 'TextBuilder'), 'man': ('manpage', 'ManualPageBuilder'), diff --git a/sphinx/builders/applehelp.py b/sphinx/builders/applehelp.py index c98962633..53a0c99ad 100644 --- a/sphinx/builders/applehelp.py +++ b/sphinx/builders/applehelp.py @@ -5,7 +5,7 @@ Build Apple help books. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py index 4fb98ba12..c077b7dd2 100644 --- a/sphinx/builders/changes.py +++ b/sphinx/builders/changes.py @@ -5,7 +5,7 @@ Changelog builder. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py index 56e63625e..5ebaf2dc5 100644 --- a/sphinx/builders/devhelp.py +++ b/sphinx/builders/devhelp.py @@ -7,7 +7,7 @@ .. _Devhelp: http://live.gnome.org/devhelp - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/builders/dummy.py b/sphinx/builders/dummy.py new file mode 100644 index 000000000..edf43ab9d --- /dev/null +++ b/sphinx/builders/dummy.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +""" + sphinx.builders.dummy + ~~~~~~~~~~~~~~~~~~~~ + + Do syntax checks, but no writing. + + :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + + +from sphinx.builders import Builder + + +class DummyBuilder(Builder): + name = 'dummy' + allow_parallel = True + + def init(self): + pass + + def get_outdated_docs(self): + return self.env.found_docs + + def get_target_uri(self, docname, typ=None): + return '' + + def prepare_writing(self, docnames): + pass + + def write_doc(self, docname, doctree): + pass + + def finish(self): + pass diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py index 2a80642dd..fde2cbc12 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -6,7 +6,7 @@ Build epub files. Originally derived from qthelp.py. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -39,9 +39,9 @@ from sphinx.util.console import brown # output but that may be customized by (re-)setting module attributes, # e.g. from conf.py. -_mimetype_template = 'application/epub+zip' # no EOL! +MIMETYPE_TEMPLATE = 'application/epub+zip' # no EOL! -_container_template = u'''\ +CONTAINER_TEMPLATE = u'''\ <?xml version="1.0" encoding="UTF-8"?> <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> @@ -52,7 +52,7 @@ _container_template = u'''\ </container> ''' -_toc_template = u'''\ +TOC_TEMPLATE = u'''\ <?xml version="1.0"?> <ncx version="2005-1" xmlns="http://www.daisy.org/z3986/2005/ncx/"> <head> @@ -70,7 +70,7 @@ _toc_template = u'''\ </ncx> ''' -_navpoint_template = u'''\ +NAVPOINT_TEMPLATE = u'''\ %(indent)s <navPoint id="%(navpoint)s" playOrder="%(playorder)d"> %(indent)s <navLabel> %(indent)s <text>%(text)s</text> @@ -78,10 +78,10 @@ _navpoint_template = u'''\ %(indent)s <content src="%(refuri)s" /> %(indent)s </navPoint>''' -_navpoint_indent = ' ' -_navPoint_template = 'navPoint%d' +NAVPOINT_INDENT = ' ' +NODE_NAVPOINT_TEMPLATE = 'navPoint%d' -_content_template = u'''\ +CONTENT_TEMPLATE = u'''\ <?xml version="1.0" encoding="UTF-8"?> <package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="%(uid)s"> @@ -108,40 +108,40 @@ _content_template = u'''\ </package> ''' -_cover_template = u'''\ +COVER_TEMPLATE = u'''\ <meta name="cover" content="%(cover)s"/> ''' -_coverpage_name = u'epub-cover.html' +COVERPAGE_NAME = u'epub-cover.html' -_file_template = u'''\ +FILE_TEMPLATE = u'''\ <item id="%(id)s" href="%(href)s" media-type="%(media_type)s" />''' -_spine_template = u'''\ +SPINE_TEMPLATE = u'''\ <itemref idref="%(idref)s" />''' -_guide_template = u'''\ +GUIDE_TEMPLATE = u'''\ <reference type="%(type)s" title="%(title)s" href="%(uri)s" />''' -_toctree_template = u'toctree-l%d' +TOCTREE_TEMPLATE = u'toctree-l%d' -_link_target_template = u' [%(uri)s]' +LINK_TARGET_TEMPLATE = u' [%(uri)s]' -_footnote_label_template = u'#%d' +FOOTNOTE_LABEL_TEMPLATE = u'#%d' -_footnotes_rubric_name = u'Footnotes' +FOOTNOTES_RUBRIC_NAME = u'Footnotes' -_css_link_target_class = u'link-target' +CSS_LINK_TARGET_CLASS = u'link-target' # XXX These strings should be localized according to epub_language -_guide_titles = { +GUIDE_TITLES = { 'toc': u'Table of Contents', 'cover': u'Cover' } -_media_types = { +MEDIA_TYPES = { '.html': 'application/xhtml+xml', '.css': 'text/css', '.png': 'image/png', @@ -153,12 +153,12 @@ _media_types = { '.ttf': 'application/x-font-ttf', } -_vector_graphics_extensions = ('.svg',) +VECTOR_GRAPHICS_EXTENSIONS = ('.svg',) # Regular expression to match colons only in local fragment identifiers. # If the URI contains a colon before the #, # it is an external link that should not change. -_refuri_re = re.compile("([^#:]*#)(.*)") +REFURI_RE = re.compile("([^#:]*#)(.*)") # The epub publisher @@ -183,6 +183,25 @@ class EpubBuilder(StandaloneHTMLBuilder): # don't add sidebar etc. embedded = True + mimetype_template = MIMETYPE_TEMPLATE + container_template = CONTAINER_TEMPLATE + toc_template = TOC_TEMPLATE + navpoint_template = NAVPOINT_TEMPLATE + navpoint_indent = NAVPOINT_INDENT + node_navpoint_template = NODE_NAVPOINT_TEMPLATE + content_template = CONTENT_TEMPLATE + cover_template = COVER_TEMPLATE + coverpage_name = COVERPAGE_NAME + file_template = FILE_TEMPLATE + spine_template = SPINE_TEMPLATE + guide_template = GUIDE_TEMPLATE + toctree_template = TOCTREE_TEMPLATE + link_target_template = LINK_TARGET_TEMPLATE + css_link_target_class = CSS_LINK_TARGET_CLASS + guide_titles = GUIDE_TITLES + media_types = MEDIA_TYPES + refuri_re = REFURI_RE + def init(self): StandaloneHTMLBuilder.init(self) # the output files for epub must be .html only @@ -224,7 +243,7 @@ class EpubBuilder(StandaloneHTMLBuilder): return result classes = doctree.parent.attributes['classes'] for level in range(8, 0, -1): # or range(1, 8)? - if (_toctree_template % level) in classes: + if (self.toctree_template % level) in classes: result.append({ 'level': level, 'refuri': self.esc(refuri), @@ -285,7 +304,7 @@ class EpubBuilder(StandaloneHTMLBuilder): """ for node in tree.traverse(nodes.reference): if 'refuri' in node: - m = _refuri_re.match(node['refuri']) + m = self.refuri_re.match(node['refuri']) if m: node['refuri'] = self.fix_fragment(m.group(1), m.group(2)) if 'refid' in node: @@ -331,11 +350,11 @@ class EpubBuilder(StandaloneHTMLBuilder): return fn.parent, fn.parent.index(fn) + 1 for node in tree.traverse(nodes.rubric): if len(node.children) == 1 and \ - node.children[0].astext() == _footnotes_rubric_name: + node.children[0].astext() == FOOTNOTES_RUBRIC_NAME: return node.parent, node.parent.index(node) + 1 doc = tree.traverse(nodes.document)[0] rub = nodes.rubric() - rub.append(nodes.Text(_footnotes_rubric_name)) + rub.append(nodes.Text(FOOTNOTES_RUBRIC_NAME)) doc.append(rub) return doc, doc.index(rub) + 1 @@ -351,12 +370,12 @@ class EpubBuilder(StandaloneHTMLBuilder): uri.startswith('ftp:')) and uri not in node.astext(): idx = node.parent.index(node) + 1 if show_urls == 'inline': - uri = _link_target_template % {'uri': uri} + uri = self.link_target_template % {'uri': uri} link = nodes.inline(uri, uri) - link['classes'].append(_css_link_target_class) + link['classes'].append(self.css_link_target_class) node.parent.insert(idx, link) elif show_urls == 'footnote': - label = _footnote_label_template % nr + label = FOOTNOTE_LABEL_TEMPLATE % nr nr += 1 footnote_ref = make_footnote_ref(doc, label) node.parent.insert(idx, footnote_ref) @@ -383,13 +402,13 @@ class EpubBuilder(StandaloneHTMLBuilder): for key, columns in tree: for entryname, (links, subitems) in columns: for (i, (ismain, link)) in enumerate(links): - m = _refuri_re.match(link) + m = self.refuri_re.match(link) if m: links[i] = (ismain, self.fix_fragment(m.group(1), m.group(2))) for subentryname, subentrylinks in subitems: for (i, (ismain, link)) in enumerate(subentrylinks): - m = _refuri_re.match(link) + m = self.refuri_re.match(link) if m: subentrylinks[i] = (ismain, self.fix_fragment(m.group(1), m.group(2))) @@ -397,7 +416,7 @@ class EpubBuilder(StandaloneHTMLBuilder): def is_vector_graphics(self, filename): """Does the filename extension indicate a vector graphic format?""" ext = path.splitext(filename)[-1] - return ext in _vector_graphics_extensions + return ext in VECTOR_GRAPHICS_EXTENSIONS def copy_image_files_pil(self): """Copy images using the PIL. @@ -478,7 +497,7 @@ class EpubBuilder(StandaloneHTMLBuilder): self.info('writing %s file...' % outname) f = codecs.open(path.join(outdir, outname), 'w', 'utf-8') try: - f.write(_mimetype_template) + f.write(self.mimetype_template) finally: f.close() @@ -493,7 +512,7 @@ class EpubBuilder(StandaloneHTMLBuilder): raise f = codecs.open(path.join(outdir, outname), 'w', 'utf-8') try: - f.write(_container_template) + f.write(self.container_template) finally: f.close() @@ -538,17 +557,17 @@ class EpubBuilder(StandaloneHTMLBuilder): if filename in self.ignored_files: continue ext = path.splitext(filename)[-1] - if ext not in _media_types: + if ext not in self.media_types: # we always have JS and potentially OpenSearch files, don't # always warn about them if ext not in ('.js', '.xml'): self.warn('unknown mimetype for %s, ignoring' % filename) continue filename = filename.replace(os.sep, '/') - projectfiles.append(_file_template % { + projectfiles.append(self.file_template % { 'href': self.esc(filename), 'id': self.esc(self.make_id(filename)), - 'media_type': self.esc(_media_types[ext]) + 'media_type': self.esc(self.media_types[ext]) }) self.files.append(filename) @@ -559,20 +578,20 @@ class EpubBuilder(StandaloneHTMLBuilder): continue if item['refuri'] in self.ignored_files: continue - spine.append(_spine_template % { + spine.append(self.spine_template % { 'idref': self.esc(self.make_id(item['refuri'])) }) for info in self.domain_indices: - spine.append(_spine_template % { + spine.append(self.spine_template % { 'idref': self.esc(self.make_id(info[0] + self.out_suffix)) }) if self.get_builder_config('use_index', 'epub'): - spine.append(_spine_template % { + spine.append(self.spine_template % { 'idref': self.esc(self.make_id('genindex' + self.out_suffix)) }) # add the optional cover - content_tmpl = _content_template + content_tmpl = self.content_template html_tmpl = None if self.config.epub_cover: image, html_tmpl = self.config.epub_cover @@ -580,22 +599,22 @@ class EpubBuilder(StandaloneHTMLBuilder): mpos = content_tmpl.rfind('</metadata>') cpos = content_tmpl.rfind('\n', 0, mpos) + 1 content_tmpl = content_tmpl[:cpos] + \ - _cover_template % {'cover': self.esc(self.make_id(image))} + \ + COVER_TEMPLATE % {'cover': self.esc(self.make_id(image))} + \ content_tmpl[cpos:] if html_tmpl: - spine.insert(0, _spine_template % { - 'idref': self.esc(self.make_id(_coverpage_name))}) - if _coverpage_name not in self.files: - ext = path.splitext(_coverpage_name)[-1] - self.files.append(_coverpage_name) - projectfiles.append(_file_template % { - 'href': self.esc(_coverpage_name), - 'id': self.esc(self.make_id(_coverpage_name)), - 'media_type': self.esc(_media_types[ext]) + spine.insert(0, self.spine_template % { + 'idref': self.esc(self.make_id(self.coverpage_name))}) + if self.coverpage_name not in self.files: + ext = path.splitext(self.coverpage_name)[-1] + self.files.append(self.coverpage_name) + projectfiles.append(self.file_template % { + 'href': self.esc(self.coverpage_name), + 'id': self.esc(self.make_id(self.coverpage_name)), + 'media_type': self.esc(self.media_types[ext]) }) ctx = {'image': self.esc(image), 'title': self.config.project} self.handle_page( - path.splitext(_coverpage_name)[0], ctx, html_tmpl) + path.splitext(self.coverpage_name)[0], ctx, html_tmpl) guide = [] auto_add_cover = True @@ -609,21 +628,21 @@ class EpubBuilder(StandaloneHTMLBuilder): auto_add_cover = False if type == 'toc': auto_add_toc = False - guide.append(_guide_template % { + guide.append(self.guide_template % { 'type': self.esc(type), 'title': self.esc(title), 'uri': self.esc(uri) }) if auto_add_cover and html_tmpl: - guide.append(_guide_template % { + guide.append(self.guide_template % { 'type': 'cover', - 'title': _guide_titles['cover'], - 'uri': self.esc(_coverpage_name) + 'title': self.guide_titles['cover'], + 'uri': self.esc(self.coverpage_name) }) if auto_add_toc and self.refnodes: - guide.append(_guide_template % { + guide.append(self.guide_template % { 'type': 'toc', - 'title': _guide_titles['toc'], + 'title': self.guide_titles['toc'], 'uri': self.esc(self.refnodes[0]['refuri']) }) projectfiles = '\n'.join(projectfiles) @@ -644,10 +663,10 @@ class EpubBuilder(StandaloneHTMLBuilder): if incr: self.playorder += 1 self.tocid += 1 - node['indent'] = _navpoint_indent * level - node['navpoint'] = self.esc(_navPoint_template % self.tocid) + node['indent'] = self.navpoint_indent * level + node['navpoint'] = self.esc(self.node_navpoint_template % self.tocid) node['playorder'] = self.playorder - return _navpoint_template % node + return self.navpoint_template % node def insert_subnav(self, node, subnav): """Insert nested navpoints for given node. @@ -730,7 +749,7 @@ class EpubBuilder(StandaloneHTMLBuilder): level = min(level, self.config.epub_tocdepth) f = codecs.open(path.join(outdir, outname), 'w', 'utf-8') try: - f.write(_toc_template % self.toc_metadata(level, navpoints)) + f.write(self.toc_template % self.toc_metadata(level, navpoints)) finally: f.close() diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py new file mode 100644 index 000000000..ded8c50d9 --- /dev/null +++ b/sphinx/builders/epub3.py @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +""" + sphinx.builders.epub3 + ~~~~~~~~~~~~~~~~~~~~~ + + Build epub3 files. + Originally derived from epub.py. + + :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import codecs +from os import path + +from sphinx.builders.epub import EpubBuilder + + +# (Fragment) templates from which the metainfo files content.opf, toc.ncx, +# mimetype, and META-INF/container.xml are created. +# This template section also defines strings that are embedded in the html +# output but that may be customized by (re-)setting module attributes, +# e.g. from conf.py. + +NAVIGATION_DOC_TEMPLATE = u'''\ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"\ + xmlns:epub="http://www.idpf.org/2007/ops" lang="%(lang)s" xml:lang="%(lang)s"> + <head> + <title>%(toc_locale)s + + + + + +''' + +NAVLIST_TEMPLATE = u'''\ +%(indent)s
  • +%(indent)s %(text)s +%(indent)s
  • +''' +NAVLIST_INDENT = ' ' + + +PACKAGE_DOC_TEMPLATE = u'''\ + + + + %(lang)s + %(title)s + %(description)s + %(author)s + %(contributor)s + %(publisher)s + %(copyright)s + %(id)s + %(date)s + %(date)s + + + + +%(files)s + + + +%(spine)s + + +%(guide)s + + +''' + +# The epub3 publisher + + +class Epub3Builder(EpubBuilder): + """ + Builder that outputs epub3 files. + + It creates the metainfo files content.opf, nav.xhtml, toc.ncx, mimetype, + and META-INF/container.xml. Afterwards, all necessary files are zipped to + an epub file. + """ + name = 'epub3' + + navigation_doc_template = NAVIGATION_DOC_TEMPLATE + navlist_template = NAVLIST_TEMPLATE + navlist_indent = NAVLIST_INDENT + content_template = PACKAGE_DOC_TEMPLATE + + # Finish by building the epub file + def handle_finish(self): + """Create the metainfo files and finally the epub.""" + self.get_toc() + self.build_mimetype(self.outdir, 'mimetype') + self.build_container(self.outdir, 'META-INF/container.xml') + self.build_content(self.outdir, 'content.opf') + self.build_navigation_doc(self.outdir, 'nav.xhtml') + self.build_toc(self.outdir, 'toc.ncx') + self.build_epub(self.outdir, self.config.epub_basename + '.epub') + + def content_metadata(self, files, spine, guide): + """Create a dictionary with all metadata for the content.opf + file properly escaped. + """ + metadata = super(Epub3Builder, self).content_metadata( + files, spine, guide) + metadata['description'] = self.esc(self.config.epub3_description) + metadata['contributor'] = self.esc(self.config.epub3_contributor) + metadata['page_progression_direction'] = self.esc( + self.config.epub3_page_progression_direction) + return metadata + + def new_navlist(self, node, level): + """Create a new entry in the toc from the node at given level.""" + # XXX Modifies the node + self.tocid += 1 + node['indent'] = self.navlist_indent * level + navpoint = self.navlist_template % node + return navpoint + + def build_navlist(self, nodes): + """Create the toc navigation structure. + + This method is almost same as build_navpoints method in epub.py. + This is because the logical navigation structure of epub3 is not + different from one of epub2. + + The difference from build_navpoints method is templates which are used + when generating navigation documents. + """ + navstack = [] + navlist = [] + level = 1 + lastnode = None + for node in nodes: + if not node['text']: + continue + file = node['refuri'].split('#')[0] + if file in self.ignored_files: + continue + if node['level'] > self.config.epub_tocdepth: + continue + if node['level'] == level: + navlist.append(self.new_navlist(node, level)) + elif node['level'] == level + 1: + navstack.append(navlist) + navlist = [] + level += 1 + if lastnode and self.config.epub_tocdup: + navlist.append(self.new_navlist(node, level)) + navlist[-1] = '
      \n' + navlist[-1] + else: + while node['level'] < level: + subnav = '\n'.join(navlist) + navlist = navstack.pop() + navlist[-1] = self.insert_subnav(navlist[-1], subnav) + level -= 1 + navlist[-1] = navlist[-1] + '
    ' + navlist.append(self.new_navlist(node, level)) + lastnode = node + while level != 1: + subnav = '\n'.join(navlist) + navlist = navstack.pop() + navlist[-1] = self.insert_subnav(navlist[-1], subnav) + level -= 1 + navlist[-1] = navlist[-1] + '' + return '\n'.join(navlist) + + def navigation_doc_metadata(self, navlist): + """Create a dictionary with all metadata for the nav.xhtml file + properly escaped. + """ + metadata = {} + metadata['lang'] = self.esc(self.config.epub_language) + metadata['toc_locale'] = self.esc(self.guide_titles['toc']) + metadata['navlist'] = navlist + return metadata + + def build_navigation_doc(self, outdir, outname): + """Write the metainfo file nav.xhtml.""" + self.info('writing %s file...' % outname) + + if self.config.epub_tocscope == 'default': + doctree = self.env.get_and_resolve_doctree( + self.config.master_doc, self, + prune_toctrees=False, includehidden=False) + refnodes = self.get_refnodes(doctree, []) + self.toc_add_files(refnodes) + else: + # 'includehidden' + refnodes = self.refnodes + navlist = self.build_navlist(refnodes) + f = codecs.open(path.join(outdir, outname), 'w', 'utf-8') + try: + f.write(self.navigation_doc_template % + self.navigation_doc_metadata(navlist)) + finally: + f.close() + # Add nav.xhtml to epub file + self.files.append(outname) diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index ec6a18805..ef4992a26 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -5,7 +5,7 @@ The MessageCatalogBuilder class. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 79fd06902..03199f3b9 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -5,7 +5,7 @@ Several HTML builders. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -27,7 +27,7 @@ from docutils.frontend import OptionParser from docutils.readers.doctree import Reader as DoctreeReader from sphinx import package_dir, __display_version__ -from sphinx.util import jsonimpl, copy_static_entry +from sphinx.util import jsonimpl, copy_static_entry, copy_extra_entry from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \ movefile, ustrftime, copyfile from sphinx.util.nodes import inline_all_toctrees @@ -644,11 +644,12 @@ class StandaloneHTMLBuilder(Builder): self.info(bold('copying extra files... '), nonl=True) extraentries = [path.join(self.confdir, epath) for epath in self.config.html_extra_path] + matchers = compile_matchers(self.config.exclude_patterns) for entry in extraentries: if not path.exists(entry): self.warn('html_extra_path entry %r does not exist' % entry) continue - copy_static_entry(entry, self.outdir, self) + copy_extra_entry(entry, self.outdir, matchers) self.info('done') def write_buildinfo(self): diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py index 9a21fb15b..2f06cb0e1 100644 --- a/sphinx/builders/htmlhelp.py +++ b/sphinx/builders/htmlhelp.py @@ -6,7 +6,7 @@ Build HTML help support files. Parts adapted from Python's Doc/tools/prechm.py. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py index 1eef58d66..49922dfb5 100644 --- a/sphinx/builders/latex.py +++ b/sphinx/builders/latex.py @@ -5,7 +5,7 @@ LaTeX builder. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -20,6 +20,7 @@ from docutils.frontend import OptionParser from sphinx import package_dir, addnodes from sphinx.util import texescape +from sphinx.errors import SphinxError from sphinx.locale import _ from sphinx.builders import Builder from sphinx.environment import NoUri @@ -94,9 +95,18 @@ class LaTeXBuilder(Builder): destination_path=path.join(self.outdir, targetname), encoding='utf-8') self.info("processing " + targetname + "... ", nonl=1) + toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree) + if toctrees: + if toctrees[0].get('maxdepth') > 0: + tocdepth = toctrees[0].get('maxdepth') + else: + tocdepth = None + else: + tocdepth = None doctree = self.assemble_doctree( docname, toctree_only, appendices=((docclass != 'howto') and self.config.latex_appendices or [])) + doctree['tocdepth'] = tocdepth self.post_process_images(doctree) self.info("writing... ", nonl=1) doctree.settings = docsettings @@ -191,6 +201,9 @@ class LaTeXBuilder(Builder): # the logo is handled differently if self.config.latex_logo: logobase = path.basename(self.config.latex_logo) - copyfile(path.join(self.confdir, self.config.latex_logo), - path.join(self.outdir, logobase)) + logotarget = path.join(self.outdir, logobase) + if not path.isfile(path.join(self.confdir, self.config.latex_logo)): + raise SphinxError('logo file %r does not exist' % self.config.latex_logo) + elif not path.isfile(logotarget): + copyfile(path.join(self.confdir, self.config.latex_logo), logotarget) self.info('done') diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index b05c5b2e0..5904d659b 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -5,7 +5,7 @@ The CheckExternalLinksBuilder class. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -17,7 +17,7 @@ from os import path from six.moves import queue from six.moves.urllib.request import build_opener, Request, HTTPRedirectHandler -from six.moves.urllib.parse import unquote, urlsplit, quote +from six.moves.urllib.parse import unquote from six.moves.urllib.error import HTTPError from six.moves.html_parser import HTMLParser from docutils import nodes @@ -33,6 +33,7 @@ except ImportError: pass from sphinx.builders import Builder +from sphinx.util import encode_uri from sphinx.util.console import purple, red, darkgreen, darkgray, \ darkred, turquoise from sphinx.util.pycompat import TextIOWrapper @@ -94,6 +95,17 @@ def check_anchor(f, hash): return parser.found +def get_content_charset(f): + content_type = f.headers.get('content-type') + if content_type: + params = (p.strip() for p in content_type.split(';')[1:]) + for param in params: + if param.startswith('charset='): + return param[8:] + + return None + + class CheckExternalLinksBuilder(Builder): """ Checks for broken external links. @@ -153,15 +165,7 @@ class CheckExternalLinksBuilder(Builder): try: req_url.encode('ascii') except UnicodeError: - split = urlsplit(req_url) - req_url = (split[0].encode() + '://' + # scheme - split[1].encode('idna') + # netloc - quote(split[2].encode('utf-8'))) # path - if split[3]: # query - req_url += '?' + quote(split[3].encode('utf-8')) - # go back to Unicode strings which is required by Python 3 - # (but now all parts are pure ascii) - req_url = req_url.decode('ascii') + req_url = encode_uri(req_url) # need to actually check the URI try: @@ -172,6 +176,8 @@ class CheckExternalLinksBuilder(Builder): encoding = 'utf-8' if hasattr(f.headers, 'get_content_charset'): encoding = f.headers.get_content_charset() or encoding + else: + encoding = get_content_charset(f) or encoding found = check_anchor(TextIOWrapper(f, encoding), unquote(hash)) f.close() @@ -237,11 +243,12 @@ class CheckExternalLinksBuilder(Builder): elif status == 'working': self.info(darkgreen('ok ') + uri + info) elif status == 'broken': - self.info(red('broken ') + uri + red(' - ' + info)) self.write_entry('broken', docname, lineno, uri + ': ' + info) - if self.app.quiet: + if self.app.quiet or self.app.warningiserror: self.warn('broken link: %s' % uri, '%s:%s' % (self.env.doc2path(docname), lineno)) + else: + self.info(red('broken ') + uri + red(' - ' + info)) elif status == 'redirected': text, color = { 301: ('permanently', darkred), diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py index 2af853dd8..a2e75f9f7 100644 --- a/sphinx/builders/manpage.py +++ b/sphinx/builders/manpage.py @@ -5,7 +5,7 @@ Manual pages builder. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py index 825f5651f..f6cfa84c5 100644 --- a/sphinx/builders/qthelp.py +++ b/sphinx/builders/qthelp.py @@ -5,7 +5,7 @@ Build input files for the Qt collection generator. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py index 7528c0777..dec278c86 100644 --- a/sphinx/builders/texinfo.py +++ b/sphinx/builders/texinfo.py @@ -5,7 +5,7 @@ Texinfo builder. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/text.py b/sphinx/builders/text.py index 9e624d0d5..85da4a1a2 100644 --- a/sphinx/builders/text.py +++ b/sphinx/builders/text.py @@ -5,7 +5,7 @@ Plain-text Sphinx builder. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/websupport.py b/sphinx/builders/websupport.py index 66af0ab80..843b0899e 100644 --- a/sphinx/builders/websupport.py +++ b/sphinx/builders/websupport.py @@ -5,7 +5,7 @@ Builder for the web support package. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py index 18d8cbfb5..91cb273f5 100644 --- a/sphinx/builders/xml.py +++ b/sphinx/builders/xml.py @@ -5,7 +5,7 @@ Docutils-native XML and pseudo-XML builders. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py index e411836c3..f5b141e8c 100644 --- a/sphinx/cmdline.py +++ b/sphinx/cmdline.py @@ -5,7 +5,7 @@ sphinx-build command-line handling. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function @@ -120,7 +120,7 @@ def main(argv): # parse options try: - opts, args = parser.parse_args(argv[1:]) + opts, args = parser.parse_args(list(argv[1:])) except SystemExit as err: return err.code @@ -144,6 +144,10 @@ def main(argv): file=sys.stderr) return 1 outdir = abspath(args[1]) + if srcdir == outdir: + print('Error: source directory and destination directory are same.', + file=sys.stderr) + return 1 except IndexError: parser.print_help() return 1 diff --git a/sphinx/config.py b/sphinx/config.py index 0b7ac9cad..74ea23bd7 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -5,7 +5,7 @@ Build configuration file handling. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -92,7 +92,7 @@ class Config(object): html_theme_options = ({}, 'html'), html_title = (lambda self: l_('%s %s documentation') % (self.project, self.release), - 'html'), + 'html', [str]), html_short_title = (lambda self: self.html_title, 'html'), html_style = (None, 'html', [str]), html_logo = (None, 'html', [str]), @@ -169,7 +169,9 @@ class Config(object): epub_theme = ('epub', 'html'), epub_theme_options = ({}, 'html'), epub_title = (lambda self: self.html_title, 'html'), + epub3_description = ('', 'epub3', [str]), epub_author = ('unknown', 'html'), + epub3_contributor = ('unknown', 'epub3', [str]), epub_language = (lambda self: self.language or 'en', 'html'), epub_publisher = ('unknown', 'html'), epub_copyright = (lambda self: self.copyright, 'html'), @@ -188,6 +190,7 @@ class Config(object): epub_max_image_width = (0, 'env'), epub_show_urls = ('inline', 'html'), epub_use_index = (lambda self: self.html_use_index, 'html'), + epub3_page_progression_direction = ('ltr', 'epub3', [str]), # LaTeX options latex_documents = (lambda self: [(self.master_doc, diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py index 2200cdb6c..36ca3d34d 100644 --- a/sphinx/directives/__init__.py +++ b/sphinx/directives/__init__.py @@ -5,7 +5,7 @@ Handlers for additional ReST directives. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index f31ba7a99..fac8f6419 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -3,7 +3,7 @@ sphinx.directives.code ~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -93,6 +93,7 @@ class CodeBlock(Directive): 'lineno-start': int, 'emphasize-lines': directives.unchanged_required, 'caption': directives.unchanged_required, + 'class': directives.class_option, 'name': directives.unchanged, } @@ -119,6 +120,7 @@ class CodeBlock(Directive): literal['language'] = self.arguments[0] literal['linenos'] = 'linenos' in self.options or \ 'lineno-start' in self.options + literal['classes'] += self.options.get('class', []) extra_args = literal['highlight_args'] = {} if hl_lines is not None: extra_args['hl_lines'] = hl_lines @@ -165,6 +167,7 @@ class LiteralInclude(Directive): 'append': directives.unchanged_required, 'emphasize-lines': directives.unchanged_required, 'caption': directives.unchanged, + 'class': directives.class_option, 'name': directives.unchanged, 'diff': directives.unchanged_required, } @@ -322,6 +325,7 @@ class LiteralInclude(Directive): retnode['linenos'] = 'linenos' in self.options or \ 'lineno-start' in self.options or \ 'lineno-match' in self.options + retnode['classes'] += self.options.get('class', []) extra_args = retnode['highlight_args'] = {} if hl_lines is not None: extra_args['hl_lines'] = hl_lines diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index 794dbda5e..51294570c 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -3,7 +3,7 @@ sphinx.directives.other ~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 5d530ae5b..e4d397efe 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -6,7 +6,7 @@ Support for domains, which are groupings of description directives and roles describing e.g. constructs of one programming language. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py index 6b71f882d..23ed04d05 100644 --- a/sphinx/domains/c.py +++ b/sphinx/domains/c.py @@ -5,7 +5,7 @@ The C language domain. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index fcd352e71..10602931d 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -5,7 +5,7 @@ The C++ language domain. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -2268,11 +2268,19 @@ class Symbol(object): self._assert_invariants() def clear_doc(self, docname): + newChildren = [] for sChild in self.children: sChild.clear_doc(docname) if sChild.declaration and sChild.docname == docname: sChild.declaration = None sChild.docname = None + # Just remove operators, because there is no identification if + # they got removed. + # Don't remove other symbols because they may be used in namespace + # directives. + if sChild.identifier or sChild.declaration: + newChildren.append(sChild) + self.children = newChildren def get_all_symbols(self): yield self @@ -2442,8 +2450,10 @@ class Symbol(object): for otherChild in other.children: if not otherChild.identifier: if not otherChild.declaration: - print("WTF?") + print("Problem in symbol tree merging") + print("OtherChild.dump:") print(otherChild.dump(0)) + print("Other.dump:") print(other.dump(0)) assert otherChild.declaration operator = otherChild.declaration.name.names[-1] @@ -2595,7 +2605,6 @@ class Symbol(object): assert False # should have returned in the loop def to_string(self, indent): - self._assert_invariants() res = ['\t'*indent] if not self.parent: res.append('::') @@ -3915,6 +3924,13 @@ class CPPXRefRole(XRefRole): parent = env.ref_context.get('cpp:parentSymbol', None) if parent: refnode['cpp:parentKey'] = parent.get_lookup_key() + if refnode['reftype'] == 'any': + # Assume the removal part of fix_parens for :any: refs. + # The addition part is done with the reference is resolved. + if not has_explicit_title and title.endswith('()'): + title = title[:-2] + if target.endswith('()'): + target = target[:-2] # TODO: should this really be here? if not has_explicit_title: target = target.lstrip('~') # only has a meaning for the title @@ -3997,7 +4013,7 @@ class CPPDomain(Domain): else: ourNames[name] = docname - def _resolve_xref_inner(self, env, fromdocname, builder, + def _resolve_xref_inner(self, env, fromdocname, builder, typ, target, node, contnode, emitWarnings=True): class Warner(object): def warn(self, msg): @@ -4039,19 +4055,24 @@ class CPPDomain(Domain): name = text_type(fullNestedName).lstrip(':') docname = s.docname assert docname + if typ == 'any' and declaration.objectType == 'function': + if env.config.add_function_parentheses: + if not node['refexplicit']: + title = contnode.pop(0).astext() + contnode += nodes.Text(title + '()') return make_refnode(builder, fromdocname, docname, declaration.get_newest_id(), contnode, name ), declaration.objectType def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): - return self._resolve_xref_inner(env, fromdocname, builder, target, - node, contnode)[0] + return self._resolve_xref_inner(env, fromdocname, builder, typ, + 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, + 'any', target, node, contnode, emitWarnings=False) if node: return [('cpp:' + self.role_for_objtype(objtype), node)] diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py index 843629b3b..f7e2703e4 100644 --- a/sphinx/domains/javascript.py +++ b/sphinx/domains/javascript.py @@ -5,7 +5,7 @@ The JavaScript domain. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index b64e797b0..ba5998084 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -5,7 +5,7 @@ The Python domain. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py index b47961469..f0ad66ddc 100644 --- a/sphinx/domains/rst.py +++ b/sphinx/domains/rst.py @@ -5,7 +5,7 @@ The reStructuredText domain. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index efd406082..9fb16a99f 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -5,7 +5,7 @@ The standard domain. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -210,10 +210,6 @@ class Program(Directive): class OptionXRefRole(XRefRole): def process_link(self, env, refnode, has_explicit_title, title, target): - # validate content - if not re.match(r'(.+ )?[-/+\w]', 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 @@ -457,7 +453,7 @@ class StandardDomain(Domain): 'productionlist': ProductionList, } roles = { - 'option': OptionXRefRole(), + 'option': OptionXRefRole(warn_dangling=True), 'envvar': EnvVarXRefRole(), # links to tokens in grammar productions 'token': XRefRole(), @@ -495,6 +491,7 @@ class StandardDomain(Domain): 'the label must precede a section header)', 'numref': 'undefined label: %(target)s', 'keyword': 'unknown keyword: %(target)s', + 'option': 'unknown option: %(target)s', } def clear_doc(self, docname): @@ -633,16 +630,25 @@ class StandardDomain(Domain): return None if env.config.numfig is False: - env.warn(fromdocname, 'numfig is disabled. :numref: is ignored.') + env.warn(fromdocname, 'numfig is disabled. :numref: is ignored.', + lineno=node.line) return contnode try: target_node = env.get_doctree(docname).ids[labelid] figtype = get_figtype(target_node) + except: + return None + + try: figure_id = target_node['ids'][0] fignumber = env.toc_fignumbers[docname][figtype][figure_id] except (KeyError, IndexError): - return None + # target_node is found, but fignumber is not assigned. + # Maybe it is defined in orphaned document. + env.warn(fromdocname, "no number is assigned for %s: %s" % (figtype, labelid), + lineno=node.line) + return contnode title = contnode.astext() if target == fully_normalize_name(title): @@ -651,7 +657,8 @@ class StandardDomain(Domain): try: newtitle = title % '.'.join(map(str, fignumber)) except TypeError: - env.warn(fromdocname, 'invalid numfig_format: %s' % title) + env.warn(fromdocname, 'invalid numfig_format: %s' % title, + lineno=node.line) return None return self.build_reference_node(fromdocname, builder, @@ -666,22 +673,23 @@ class StandardDomain(Domain): return make_refnode(builder, fromdocname, docname, labelid, contnode) elif typ == 'option': + progname = node.get('std:program') target = target.strip() - # most obvious thing: we are a flag option without program - if target.startswith(('-', '/', '+')): - progname = node.get('std:program') - elif re.search(r'[-/+]', target): - try: - progname, target = re.split(r' (?=-|--|/|\+)', target, 1) - except ValueError: - return None - progname = ws_re.sub('-', progname.strip()) - else: - progname = None - docname, labelid = self.data['progoptions'].get((progname, target), - ('', '')) + docname, labelid = self.data['progoptions'].get((progname, target), ('', '')) if not docname: - return None + commands = [] + while ws_re.search(target): + subcommand, target = ws_re.split(target, 1) + commands.append(subcommand) + progname = "-".join(commands) + + docname, labelid = self.data['progoptions'].get((progname, target), + ('', '')) + if docname: + break + else: + return None + return make_refnode(builder, fromdocname, docname, labelid, contnode) else: diff --git a/sphinx/environment.py b/sphinx/environment.py index 58463cae8..ad07b642a 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -5,7 +5,7 @@ Global creation environment. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -23,8 +23,8 @@ from os import path from glob import glob from itertools import groupby -from six import iteritems, itervalues, text_type, class_types, string_types -from six.moves import cPickle as pickle, zip +from six import iteritems, itervalues, text_type, class_types, string_types, next +from six.moves import cPickle as pickle from docutils import nodes from docutils.io import FileInput, NullOutput from docutils.core import Publisher @@ -38,7 +38,7 @@ from docutils.frontend import OptionParser from sphinx import addnodes from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \ - FilenameUniqDict, get_figtype, import_object + FilenameUniqDict, get_figtype, import_object, split_index_msg, split_docinfo from sphinx.util.nodes import clean_astext, make_refnode, WarningStream, is_translatable from sphinx.util.osutil import SEP, getcwd, fs_encoding from sphinx.util.i18n import find_catalog_files @@ -105,13 +105,16 @@ class SphinxStandaloneReader(standalone.Reader): DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, AutoNumbering, SortIds, RemoveTranslatableInline] - def __init__(self, parsers={}, *args, **kwargs): + def __init__(self, app, parsers={}, *args, **kwargs): standalone.Reader.__init__(self, *args, **kwargs) self.parser_map = {} for suffix, parser_class in parsers.items(): if isinstance(parser_class, string_types): parser_class = import_object(parser_class, 'source parser') - self.parser_map[suffix] = parser_class() + parser = parser_class() + if hasattr(parser, 'set_application'): + parser.set_application(app) + self.parser_map[suffix] = parser def read(self, source, parser, settings): self.source = source @@ -157,11 +160,12 @@ class SphinxFileInput(FileInput): arg = [data] self.app.emit('source-read', self.env.docname, arg) data = arg[0] + docinfo, data = split_docinfo(data) 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 + return docinfo + data class BuildEnvironment: @@ -618,8 +622,8 @@ class BuildEnvironment: self._read_serial(docnames, app) if config.master_doc not in self.all_docs: - self.warn(None, 'master file %s not found' % - self.doc2path(config.master_doc)) + raise SphinxError('master file %s not found' % + self.doc2path(config.master_doc)) self.app = None @@ -776,7 +780,7 @@ class BuildEnvironment: codecs.register_error('sphinx', self.warn_and_replace) # publish manually - reader = SphinxStandaloneReader(parsers=self.config.source_parsers) + reader = SphinxStandaloneReader(self.app, parsers=self.config.source_parsers) pub = Publisher(reader=reader, writer=SphinxDummyWriter(), destination_class=NullOutput) @@ -1123,7 +1127,14 @@ class BuildEnvironment: def note_indexentries_from(self, docname, document): entries = self.indexentries[docname] = [] for node in document.traverse(addnodes.index): - entries.extend(node['entries']) + try: + for type, value, tid, main in node['entries']: + split_index_msg(type, value) + except ValueError as exc: + self.warn_node(exc, node) + node.parent.remove(node) + else: + entries.extend(node['entries']) def note_citations_from(self, docname, document): for node in document.traverse(nodes.citation): @@ -1656,7 +1667,7 @@ class BuildEnvironment: for role in domain.roles: res = domain.resolve_xref(self, refdoc, builder, role, target, node, contnode) - if res: + if res and isinstance(res[0], nodes.Element): results.append(('%s:%s' % (domain.name, role), res)) # now, see how many matches we got... if not results: @@ -1951,54 +1962,31 @@ class BuildEnvironment: for (key_, group) in groupby(newlist, keyfunc2)] def collect_relations(self): - relations = {} - getinc = self.toctree_includes.get + traversed = set() + + def traverse_toctree(parent, docname): + # traverse toctree by pre-order + yield parent, docname + traversed.add(docname) + + for child in (self.toctree_includes.get(docname) or []): + for subparent, subdocname in traverse_toctree(docname, child): + if subdocname not in traversed: + yield subparent, subdocname + traversed.add(subdocname) + + relations = {} + docnames = traverse_toctree(None, self.config.master_doc) + prevdoc = None + parent, docname = next(docnames) + for nextparent, nextdoc in docnames: + relations[docname] = [parent, prevdoc, nextdoc] + prevdoc = docname + docname = nextdoc + parent = nextparent + + relations[docname] = [parent, prevdoc, None] - def collect(parents, parents_set, docname, previous, next): - # circular relationship? - if docname in parents_set: - # we will warn about this in resolve_toctree() - return - includes = getinc(docname) - # previous - if not previous: - # if no previous sibling, go to parent - previous = parents[0][0] - else: - # else, go to previous sibling, or if it has children, to - # the last of its children, or if that has children, to the - # last of those, and so forth - while 1: - previncs = getinc(previous) - if previncs: - previous = previncs[-1] - else: - break - # next - if includes: - # if it has children, go to first of them - next = includes[0] - elif next: - # else, if next sibling, go to it - pass - else: - # else, go to the next sibling of the parent, if present, - # else the grandparent's sibling, if present, and so forth - for parname, parindex in parents: - parincs = getinc(parname) - if parincs and parindex + 1 < len(parincs): - next = parincs[parindex+1] - break - # else it will stay None - # same for children - if includes: - for subindex, args in enumerate(zip(includes, - [None] + includes, - includes[1:] + [None])): - collect([(docname, subindex)] + parents, - parents_set.union([docname]), *args) - relations[docname] = [parents[0][0], previous, next] - collect([(None, 0)], set(), self.config.master_doc, None, None) return relations def check_consistency(self): diff --git a/sphinx/errors.py b/sphinx/errors.py index 6761e87f6..8d695c190 100644 --- a/sphinx/errors.py +++ b/sphinx/errors.py @@ -6,7 +6,7 @@ Contains SphinxError and a few subclasses (in an extra module to avoid circular import problems). - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/__init__.py b/sphinx/ext/__init__.py index 62c6416c3..776250c4d 100644 --- a/sphinx/ext/__init__.py +++ b/sphinx/ext/__init__.py @@ -5,6 +5,6 @@ Contains Sphinx features not activated by default. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index 13621c118..fc2e237b6 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -7,7 +7,7 @@ the doctree, thus avoiding duplication between docstrings and documentation for those who like elaborate docstrings. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -1292,9 +1292,11 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): docstrings.append(initdocstring) doc = [] for docstring in docstrings: - if not isinstance(docstring, text_type): - docstring = force_decode(docstring, encoding) - doc.append(prepare_docstring(docstring)) + if isinstance(docstring, text_type): + doc.append(prepare_docstring(docstring, ignore)) + elif isinstance(docstring, str): # this will not trigger on Py3 + doc.append(prepare_docstring(force_decode(docstring, encoding), + ignore)) return doc def add_content(self, more_content, no_docstring=False): diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 359eb9673..9ef48ca88 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -49,7 +49,7 @@ resolved to a Python object, and otherwise it becomes simple emphasis. This can be used as the default role to make links 'smart'. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 2cacadfd7..8495da7b4 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -14,7 +14,7 @@ generate: sphinx-autogen -o source/generated source/*.rst - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py index c564aeedd..78281bb85 100644 --- a/sphinx/ext/coverage.py +++ b/sphinx/ext/coverage.py @@ -6,7 +6,7 @@ Check Python modules and C API for coverage. Mostly written by Josip Dzolonga for the Google Highly Open Participation contest. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index e22024d42..0f5241a19 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -6,7 +6,7 @@ Mimic doctest by automatically executing code snippets and checking their results. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import @@ -45,14 +45,6 @@ else: return text -class _SpoofOutSphinx(doctest._SpoofOut): - # override: convert console encoding to unicode - if PY2: - def getvalue(self): - result = doctest._SpoofOut.getvalue(self) - return result.decode('string_escape') - - # set up the necessary directives class TestDirective(Directive): @@ -184,11 +176,6 @@ class TestCode(object): class SphinxDocTestRunner(doctest.DocTestRunner): - def __init__(self, *args, **kw): - doctest.DocTestRunner.__init__(self, *args, **kw) - # Override a fake output target for capturing doctest output. - self._fakeout = _SpoofOutSphinx() - def summarize(self, out, verbose=None): string_io = StringIO() old_stdout = sys.stdout @@ -262,9 +249,10 @@ Results of doctest builder run on %s self.outfile.write(text) def _warn_out(self, text): - self.info(text, nonl=True) - if self.app.quiet: + if self.app.quiet or self.app.warningiserror: self.warn(text) + else: + self.info(text, nonl=True) if isinstance(text, binary_type): text = force_decode(text, None) self.outfile.write(text) diff --git a/sphinx/ext/extlinks.py b/sphinx/ext/extlinks.py index 1f93fc944..8bd8017a9 100644 --- a/sphinx/ext/extlinks.py +++ b/sphinx/ext/extlinks.py @@ -20,7 +20,7 @@ You can also give an explicit caption, e.g. :exmpl:`Foo `. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/githubpages.py b/sphinx/ext/githubpages.py new file mode 100644 index 000000000..1d5c4c55d --- /dev/null +++ b/sphinx/ext/githubpages.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +""" + sphinx.ext.githubpages + ~~~~~~~~~~~~~~~~~~~~~~ + + To publish HTML docs at GitHub Pages, create .nojekyll file. + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import os +import sphinx + + +def create_nojekyll(app, env): + if app.builder.format == 'html': + path = os.path.join(app.builder.outdir, '.nojekyll') + open(path, 'wt').close() + + +def setup(app): + app.connect('env-updated', create_nojekyll) + return {'version': sphinx.__display_version__, 'parallel_read_safe': True} diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 3970edc07..44a47d5e1 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -6,7 +6,7 @@ Allow graphviz-formatted graphs to be included in Sphinx-generated documents inline. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -36,7 +36,7 @@ class GraphvizError(SphinxError): category = 'Graphviz error' -class graphviz(nodes.General, nodes.Element): +class graphviz(nodes.General, nodes.Inline, nodes.Element): pass @@ -66,6 +66,7 @@ class Graphviz(Directive): 'alt': directives.unchanged, 'inline': directives.flag, 'caption': directives.unchanged, + 'graphviz_dot': directives.unchanged, } def run(self): @@ -96,13 +97,16 @@ class Graphviz(Directive): line=self.lineno)] node = graphviz() node['code'] = dotcode - node['options'] = [] + node['options'] = {} + if 'graphviz_dot' in self.options: + node['options']['graphviz_dot'] = self.options['graphviz_dot'] if 'alt' in self.options: node['alt'] = self.options['alt'] - node['inline'] = 'inline' in self.options + if 'inline' in self.options: + node['inline'] = True caption = self.options.get('caption') - if caption and not node['inline']: + if caption: node = figure_wrapper(self, node, caption) return [node] @@ -120,19 +124,23 @@ class GraphvizSimple(Directive): 'alt': directives.unchanged, 'inline': directives.flag, 'caption': directives.unchanged, + 'graphviz_dot': directives.unchanged, } def run(self): node = graphviz() node['code'] = '%s %s {\n%s\n}\n' % \ (self.name, self.arguments[0], '\n'.join(self.content)) - node['options'] = [] + node['options'] = {} + if 'graphviz_dot' in self.options: + node['options']['graphviz_dot'] = self.options['graphviz_dot'] if 'alt' in self.options: node['alt'] = self.options['alt'] - node['inline'] = 'inline' in self.options + if 'inline' in self.options: + node['inline'] = True caption = self.options.get('caption') - if caption and not node['inline']: + if caption: node = figure_wrapper(self, node, caption) return [node] @@ -140,8 +148,8 @@ class GraphvizSimple(Directive): def render_dot(self, code, options, format, prefix='graphviz'): """Render graphviz code into a PNG or PDF output file.""" - hashkey = (code + str(options) + - str(self.builder.config.graphviz_dot) + + graphviz_dot = options.get('graphviz_dot', self.builder.config.graphviz_dot) + hashkey = (code + str(options) + str(graphviz_dot) + str(self.builder.config.graphviz_dot_args)).encode('utf-8') fname = '%s-%s.%s' % (prefix, sha1(hashkey).hexdigest(), format) @@ -151,8 +159,8 @@ def render_dot(self, code, options, format, prefix='graphviz'): if path.isfile(outfn): return relfn, outfn - if hasattr(self.builder, '_graphviz_warned_dot') or \ - hasattr(self.builder, '_graphviz_warned_ps2pdf'): + if (hasattr(self.builder, '_graphviz_warned_dot') and + self.builder._graphviz_warned_dot.get(graphviz_dot)): return None, None ensuredir(path.dirname(outfn)) @@ -161,9 +169,8 @@ def render_dot(self, code, options, format, prefix='graphviz'): if isinstance(code, text_type): code = code.encode('utf-8') - dot_args = [self.builder.config.graphviz_dot] + dot_args = [graphviz_dot] dot_args.extend(self.builder.config.graphviz_dot_args) - dot_args.extend(options) dot_args.extend(['-T' + format, '-o' + outfn]) if format == 'png': dot_args.extend(['-Tcmapx', '-o%s.map' % outfn]) @@ -173,9 +180,10 @@ def render_dot(self, code, options, format, prefix='graphviz'): if err.errno != ENOENT: # No such file or directory raise self.builder.warn('dot command %r cannot be run (needed for graphviz ' - 'output), check the graphviz_dot setting' % - self.builder.config.graphviz_dot) - self.builder._graphviz_warned_dot = True + 'output), check the graphviz_dot setting' % graphviz_dot) + if not hasattr(self.builder, '_graphviz_warned_dot'): + self.builder._graphviz_warned_dot = {} + self.builder._graphviz_warned_dot[graphviz_dot] = True return None, None try: # Graphviz may close standard input when an error occurs, @@ -197,6 +205,15 @@ def render_dot(self, code, options, format, prefix='graphviz'): return relfn, outfn +def warn_for_deprecated_option(self, node): + if hasattr(self.builder, '_graphviz_warned_inline'): + return + + if 'inline' in node: + self.builder.warn(':inline: option for graphviz is deprecated since version 1.4.0.') + self.builder._graphviz_warned_inline = True + + def render_dot_html(self, node, code, options, prefix='graphviz', imgcls=None, alt=None): format = self.builder.config.graphviz_output_format @@ -209,13 +226,6 @@ def render_dot_html(self, node, code, options, prefix='graphviz', self.builder.warn('dot code %r: ' % code + str(exc)) raise nodes.SkipNode - inline = node.get('inline', False) - if inline: - wrapper = 'span' - else: - wrapper = 'p' - - self.body.append(self.starttag(node, wrapper, CLASS='graphviz')) if fname is None: self.body.append(self.encode(code)) else: @@ -223,7 +233,8 @@ def render_dot_html(self, node, code, options, prefix='graphviz', alt = node.get('alt', self.encode(code).strip()) imgcss = imgcls and 'class="%s"' % imgcls or '' if format == 'svg': - svgtag = '%s\n' % (fname, alt, imgcss) + svgtag = ''' +

    %s

    \n''' % (fname, alt) self.body.append(svgtag) else: mapfile = open(outfn + '.map', 'rb') @@ -242,11 +253,11 @@ def render_dot_html(self, node, code, options, prefix='graphviz', (fname, alt, mapname, imgcss)) self.body.extend([item.decode('utf-8') for item in imgmap]) - self.body.append('\n' % wrapper) raise nodes.SkipNode def html_visit_graphviz(self, node): + warn_for_deprecated_option(self, node) render_dot_html(self, node, node['code'], node['options']) @@ -257,8 +268,8 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'): self.builder.warn('dot code %r: ' % code + str(exc)) raise nodes.SkipNode - inline = node.get('inline', False) - if inline: + is_inline = self.is_inline(node) + if is_inline: para_separator = '' else: para_separator = '\n' @@ -270,6 +281,7 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'): def latex_visit_graphviz(self, node): + warn_for_deprecated_option(self, node) render_dot_latex(self, node, node['code'], node['options']) @@ -285,10 +297,12 @@ def render_dot_texinfo(self, node, code, options, prefix='graphviz'): def texinfo_visit_graphviz(self, node): + warn_for_deprecated_option(self, node) render_dot_texinfo(self, node, node['code'], node['options']) def text_visit_graphviz(self, node): + warn_for_deprecated_option(self, node) if 'alt' in node.attributes: self.add_text(_('[graph: %s]') % node['alt']) else: @@ -297,6 +311,7 @@ def text_visit_graphviz(self, node): def man_visit_graphviz(self, node): + warn_for_deprecated_option(self, node) if 'alt' in node.attributes: self.body.append(_('[graph: %s]') % node['alt']) else: diff --git a/sphinx/ext/ifconfig.py b/sphinx/ext/ifconfig.py index 3c77566ef..74580fb4a 100644 --- a/sphinx/ext/ifconfig.py +++ b/sphinx/ext/ifconfig.py @@ -16,7 +16,7 @@ namespace of the project configuration (that is, all variables from ``conf.py`` are available.) - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py new file mode 100644 index 000000000..40a9c1402 --- /dev/null +++ b/sphinx/ext/imgmath.py @@ -0,0 +1,285 @@ +# -*- coding: utf-8 -*- +""" + sphinx.ext.imgmath + ~~~~~~~~~~~~~~~~~~ + + Render math in HTML via dvipng or dvisvgm. + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import re +import codecs +import shutil +import tempfile +import posixpath +from os import path +from subprocess import Popen, PIPE +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 sys_encoding +from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath + + +class MathExtError(SphinxError): + category = 'Math extension error' + + def __init__(self, msg, stderr=None, stdout=None): + if stderr: + msg += '\n[stderr]\n' + stderr.decode(sys_encoding, 'replace') + if stdout: + msg += '\n[stdout]\n' + stdout.decode(sys_encoding, 'replace') + SphinxError.__init__(self, msg) + + +DOC_HEAD = r''' +\documentclass[12pt]{article} +\usepackage[utf8x]{inputenc} +\usepackage{amsmath} +\usepackage{amsthm} +\usepackage{amssymb} +\usepackage{amsfonts} +\usepackage{anyfontsize} +\usepackage{bm} +\pagestyle{empty} +''' + +DOC_BODY = r''' +\begin{document} +\fontsize{%d}{%d}\selectfont %s +\end{document} +''' + +DOC_BODY_PREVIEW = r''' +\usepackage[active]{preview} +\begin{document} +\begin{preview} +\fontsize{%s}{%s}\selectfont %s +\end{preview} +\end{document} +''' + +depth_re = re.compile(br'\[\d+ depth=(-?\d+)\]') + + +def render_math(self, math): + """Render the LaTeX math expression *math* using latex and dvipng or + dvisvgm. + + Return the filename relative to the built document and the "depth", + that is, the distance of image bottom and baseline in pixels, if the + option to use preview_latex is switched on. + + Error handling may seem strange, but follows a pattern: if LaTeX or dvipng + (dvisvgm) aren't available, only a warning is generated (since that enables + people on machines without these programs to at least build the rest of the + docs successfully). If the programs are there, however, they may not fail + since that indicates a problem in the math source. + """ + image_format = self.builder.config.imgmath_image_format + if image_format not in ('png', 'svg'): + raise MathExtError( + 'imgmath_image_format must be either "png" or "svg"') + + font_size = self.builder.config.imgmath_font_size + use_preview = self.builder.config.imgmath_use_preview + latex = DOC_HEAD + self.builder.config.imgmath_latex_preamble + latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % ( + font_size, int(round(font_size * 1.2)), math) + + shasum = "%s.%s" % (sha1(latex.encode('utf-8')).hexdigest(), image_format) + relfn = posixpath.join(self.builder.imgpath, '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 + + # if latex or dvipng (dvisvgm) has failed once, don't bother to try again + if hasattr(self.builder, '_imgmath_warned_latex') or \ + hasattr(self.builder, '_imgmath_warned_image_translator'): + return None, None + + # use only one tempdir per build -- the use of a directory is cleaner + # than using temporary files, since we can clean up everything at once + # just removing the whole directory (see cleanup_tempdir) + if not hasattr(self.builder, '_imgmath_tempdir'): + tempdir = self.builder._imgmath_tempdir = tempfile.mkdtemp() + else: + tempdir = self.builder._imgmath_tempdir + + tf = codecs.open(path.join(tempdir, 'math.tex'), 'w', 'utf-8') + tf.write(latex) + tf.close() + + # build latex command; old versions of latex don't have the + # --output-directory option, so we have to manually chdir to the + # temp dir to run it. + ltx_args = [self.builder.config.imgmath_latex, '--interaction=nonstopmode'] + # add custom args from the config file + ltx_args.extend(self.builder.config.imgmath_latex_args) + ltx_args.append('math.tex') + + with cd(tempdir): + try: + p = Popen(ltx_args, stdout=PIPE, stderr=PIPE) + 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 ' + 'display), check the imgmath_latex setting' % + self.builder.config.imgmath_latex) + self.builder._imgmath_warned_latex = True + return None, None + + stdout, stderr = p.communicate() + if p.returncode != 0: + raise MathExtError('latex exited with error', stderr, stdout) + + ensuredir(path.dirname(outfn)) + if image_format == 'png': + image_translator = 'dvipng' + image_translator_executable = self.builder.config.imgmath_dvipng + # use some standard dvipng arguments + image_translator_args = [self.builder.config.imgmath_dvipng] + image_translator_args += ['-o', outfn, '-T', 'tight', '-z9'] + # add custom ones from config value + image_translator_args.extend(self.builder.config.imgmath_dvipng_args) + if use_preview: + image_translator_args.append('--depth') + elif image_format == 'svg': + image_translator = 'dvisvgm' + image_translator_executable = self.builder.config.imgmath_dvisvgm + # use some standard dvisvgm arguments + image_translator_args = [self.builder.config.imgmath_dvisvgm] + image_translator_args += ['-o', outfn] + # add custom ones from config value + image_translator_args.extend(self.builder.config.imgmath_dvisvgm_args) + # last, the input file name + image_translator_args.append(path.join(tempdir, 'math.dvi')) + else: + raise MathExtError( + 'imgmath_image_format must be either "png" or "svg"') + + # last, the input file name + image_translator_args.append(path.join(tempdir, 'math.dvi')) + + try: + p = Popen(image_translator_args, stdout=PIPE, stderr=PIPE) + except OSError as err: + if err.errno != ENOENT: # No such file or directory + raise + self.builder.warn('%s command %r cannot be run (needed for math ' + 'display), check the imgmath_%s setting' % + image_translator, image_translator_executable, + image_translator) + self.builder._imgmath_warned_image_translator = True + return None, None + + stdout, stderr = p.communicate() + if p.returncode != 0: + raise MathExtError('%s exited with error', + image_translator, stderr, stdout) + depth = None + if use_preview and image_format == 'png': # depth is only useful for png + for line in stdout.splitlines(): + m = depth_re.match(line) + if m: + depth = int(m.group(1)) + write_png_depth(outfn, depth) + break + + return relfn, depth + + +def cleanup_tempdir(app, exc): + if exc: + return + if not hasattr(app.builder, '_imgmath_tempdir'): + return + try: + shutil.rmtree(app.builder._mathpng_tempdir) + except Exception: + pass + + +def get_tooltip(self, node): + if self.builder.config.imgmath_add_tooltips: + return ' alt="%s"' % self.encode(node['latex']).strip() + return '' + + +def html_visit_math(self, node): + try: + fname, depth = render_math(self, '$'+node['latex']+'$') + except MathExtError as exc: + msg = text_type(exc) + sm = nodes.system_message(msg, type='WARNING', level=2, + backrefs=[], source=node['latex']) + sm.walkabout(self) + self.builder.warn('display latex %r: ' % node['latex'] + msg) + raise nodes.SkipNode + if fname is None: + # something failed -- use text-only as a bad substitute + self.body.append('%s' % + self.encode(node['latex']).strip()) + else: + c = ('') + raise nodes.SkipNode + + +def html_visit_displaymath(self, node): + if node['nowrap']: + latex = node['latex'] + else: + latex = wrap_displaymath(node['latex'], None, + self.builder.config.math_number_all) + try: + fname, depth = render_math(self, latex) + except MathExtError as exc: + sm = nodes.system_message(str(exc), type='WARNING', level=2, + backrefs=[], source=node['latex']) + sm.walkabout(self) + self.builder.warn('inline latex %r: ' % node['latex'] + str(exc)) + raise nodes.SkipNode + self.body.append(self.starttag(node, 'div', CLASS='math')) + self.body.append('

    ') + if node['number']: + self.body.append('(%s)' % node['number']) + if fname is None: + # something failed -- use text-only as a bad substitute + self.body.append('%s

    \n' % + self.encode(node['latex']).strip()) + else: + self.body.append(('

    \n') + raise nodes.SkipNode + + +def setup(app): + mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None)) + app.add_config_value('imgmath_image_format', 'png', 'html') + app.add_config_value('imgmath_dvipng', 'dvipng', 'html') + app.add_config_value('imgmath_dvisvgm', 'dvisvgm', 'html') + app.add_config_value('imgmath_latex', 'latex', 'html') + app.add_config_value('imgmath_use_preview', False, 'html') + app.add_config_value('imgmath_dvipng_args', + ['-gamma', '1.5', '-D', '110', '-bg', 'Transparent'], + 'html') + app.add_config_value('imgmath_dvisvgm_args', ['--no-fonts'], 'html') + app.add_config_value('imgmath_latex_args', [], 'html') + app.add_config_value('imgmath_latex_preamble', '', 'html') + app.add_config_value('imgmath_add_tooltips', True, 'html') + app.add_config_value('imgmath_font_size', 12, 'html') + app.connect('build-finished', cleanup_tempdir) + return {'version': sphinx.__display_version__, 'parallel_read_safe': True} diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index f618aaf15..4ac2bd2fd 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -32,7 +32,7 @@ r""" The graph is inserted as a PNG+image map into HTML and a PDF in LaTeX. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -227,10 +227,10 @@ class InheritanceGraph(object): } def _format_node_attrs(self, attrs): - return ','.join(['%s=%s' % x for x in attrs.items()]) + return ','.join(['%s=%s' % x for x in sorted(attrs.items())]) def _format_graph_attrs(self, attrs): - return ''.join(['%s=%s;\n' % x for x in attrs.items()]) + return ''.join(['%s=%s;\n' % x for x in sorted(attrs.items())]) def generate_dot(self, name, urls={}, env=None, graph_attrs={}, node_attrs={}, edge_attrs={}): @@ -264,6 +264,7 @@ class InheritanceGraph(object): this_node_attrs = n_attrs.copy() if fullname in urls: this_node_attrs['URL'] = '"%s"' % urls[fullname] + this_node_attrs['target'] = '"_top"' if tooltip: this_node_attrs['tooltip'] = tooltip res.append(' "%s" [%s];\n' % @@ -348,12 +349,20 @@ def html_visit_inheritance_diagram(self, node): name = 'inheritance%s' % graph_hash # Create a mapping from fully-qualified class names to URLs. + graphviz_output_format = self.builder.env.config.graphviz_output_format.upper() + current_filename = self.builder.current_docname + self.builder.out_suffix urls = {} for child in node: if child.get('refuri') is not None: - urls[child['reftitle']] = child.get('refuri') + if graphviz_output_format == 'SVG': + urls[child['reftitle']] = "../" + child.get('refuri') + else: + urls[child['reftitle']] = child.get('refuri') elif child.get('refid') is not None: - urls[child['reftitle']] = '#' + child.get('refid') + if graphviz_output_format == 'SVG': + urls[child['reftitle']] = '../' + current_filename + '#' + child.get('refid') + else: + urls[child['reftitle']] = '#' + child.get('refid') dotcode = graph.generate_dot(name, urls, env=self.builder.env) render_dot_html(self, node, dotcode, [], 'inheritance', 'inheritance', diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index 4d2c6755c..9fe2f765c 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -20,7 +20,7 @@ also be specified individually, e.g. if the docs should be buildable without Internet access. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py index 2cc661430..ff77c2d1b 100644 --- a/sphinx/ext/jsmath.py +++ b/sphinx/ext/jsmath.py @@ -6,7 +6,7 @@ Set up everything for use of JSMath to display math in HTML via JavaScript. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -26,7 +26,7 @@ def html_visit_math(self, node): def html_visit_displaymath(self, node): if node['nowrap']: self.body.append(self.starttag(node, 'div', CLASS='math')) - self.body.append(node['latex']) + self.body.append(self.encode(node['latex'])) self.body.append('') raise nodes.SkipNode for i, part in enumerate(node['latex'].split('\n\n')): diff --git a/sphinx/ext/linkcode.py b/sphinx/ext/linkcode.py index b0ee5e43e..63bd38727 100644 --- a/sphinx/ext/linkcode.py +++ b/sphinx/ext/linkcode.py @@ -5,7 +5,7 @@ Add external links to module code in Python object descriptions. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index 4327fba1c..8ede05b87 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -5,7 +5,7 @@ Set up math support in source files and LaTeX/text output. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -28,20 +28,25 @@ class eqref(nodes.Inline, nodes.TextElement): pass -def wrap_displaymath(math, label): +def wrap_displaymath(math, label, numbering): parts = math.split('\n\n') ret = [] for i, part in enumerate(parts): if not part.strip(): continue - if label is not None and i == 0: - ret.append('\\begin{split}%s\\end{split}' % part + - (label and '\\label{'+label+'}' or '')) - else: - ret.append('\\begin{split}%s\\end{split}\\notag' % part) + ret.append(r'\begin{split}%s\end{split}' % part) if not ret: return '' - return '\\begin{gather}\n' + '\\\\'.join(ret) + '\n\\end{gather}' + if label is not None or numbering: + env_begin = r'\begin{align}' + if label is not None: + env_begin += r'\label{%s}' % label + env_end = r'\end{align}' + else: + env_begin = r'\begin{align*}' + env_end = r'\end{align*}' + return ('%s\\begin{aligned}\n%s\\end{aligned}%s') % ( + env_begin, '\\\\\n'.join(ret), env_end) def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]): @@ -56,6 +61,17 @@ def eq_role(role, rawtext, text, lineno, inliner, options={}, content=[]): return [node], [] +def is_in_section_title(node): + """Determine whether the node is in a section title""" + from sphinx.util.nodes import traverse_parent + + for ancestor in traverse_parent(node): + if isinstance(ancestor, nodes.title) and \ + isinstance(ancestor.parent, nodes.section): + return True + return False + + class MathDirective(Directive): has_content = True @@ -91,7 +107,12 @@ class MathDirective(Directive): def latex_visit_math(self, node): - self.body.append('\\(' + node['latex'] + '\\)') + if is_in_section_title(node): + protect = r'\protect' + else: + protect = '' + equation = protect + r'\(' + node['latex'] + protect + r'\)' + self.body.append(equation) raise nodes.SkipNode @@ -100,7 +121,8 @@ def latex_visit_displaymath(self, node): self.body.append(node['latex']) else: label = node['label'] and node['docname'] + '-' + node['label'] or None - self.body.append(wrap_displaymath(node['latex'], label)) + self.body.append(wrap_displaymath(node['latex'], label, + self.builder.config.math_number_all)) raise nodes.SkipNode @@ -178,10 +200,11 @@ def number_equations(app, doctree, docname): num = 0 numbers = {} for node in doctree.traverse(displaymath): - if node['label'] is not None: + if node['label'] is not None or app.config.math_number_all: num += 1 node['number'] = num - numbers[node['label']] = num + if node['label'] is not None: + numbers[node['label']] = num else: node['number'] = None for node in doctree.traverse(eqref): @@ -192,6 +215,7 @@ def number_equations(app, doctree, docname): def setup_math(app, htmlinlinevisitors, htmldisplayvisitors): + app.add_config_value('math_number_all', False, 'html') app.add_node(math, override=True, latex=(latex_visit_math, None), text=(text_visit_math, None), @@ -214,3 +238,4 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors): app.add_role('eq', eq_role) app.add_directive('math', MathDirective) app.connect('doctree-resolved', number_equations) + app.add_latex_package('amsfonts') diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py index d512db465..511c4f3dd 100644 --- a/sphinx/ext/mathjax.py +++ b/sphinx/ext/mathjax.py @@ -7,7 +7,7 @@ Sphinx's HTML writer -- requires the MathJax JavaScript library on your webserver/computer. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -30,7 +30,7 @@ def html_visit_displaymath(self, node): self.body.append(self.starttag(node, 'div', CLASS='math')) if node['nowrap']: self.body.append(self.builder.config.mathjax_display[0] + - node['latex'] + + self.encode(node['latex']) + self.builder.config.mathjax_display[1]) self.body.append('') raise nodes.SkipNode diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py index 6124ee9be..85c8acec8 100644 --- a/sphinx/ext/napoleon/__init__.py +++ b/sphinx/ext/napoleon/__init__.py @@ -5,7 +5,7 @@ Support for NumPy and Google style docstrings. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index 1065533dc..742a9fbba 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -7,7 +7,7 @@ Classes for docstring parsing and formatting. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -27,6 +27,11 @@ _google_section_regex = re.compile(r'^(\s|\w)+:\s*$') _google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.+?)\s*\)') _numpy_section_regex = re.compile(r'^[=\-`:\'"~^_*+#<>]{2,}\s*$') _xref_regex = re.compile(r'(:\w+:\S+:`.+?`|:\S+:`.+?`|`.+?`)') +_bullet_list_regex = re.compile(r'^(\*|\+|\-)(\s+\S|\s*$)') +_enumerated_list_regex = re.compile( + r'^(?P\()?' + r'(\d+|#|[ivxlcdm]+|[IVXLCDM]+|[a-zA-Z])' + r'(?(paren)\)|\.)(\s+\S|\s*$)') class GoogleDocstring(UnicodeMixin): @@ -349,6 +354,8 @@ class GoogleDocstring(UnicodeMixin): field = '' if has_desc: + if self._is_list(_desc): + return [field, ''] + _desc return [field + _desc[0]] + _desc[1:] else: return [field] @@ -408,6 +415,23 @@ class GoogleDocstring(UnicodeMixin): return False return False + def _is_list(self, lines): + if not lines: + return False + if _bullet_list_regex.match(lines[0]): + return True + if _enumerated_list_regex.match(lines[0]): + return True + if len(lines) < 2 or lines[0].endswith('::'): + return False + indent = self._get_indent(lines[0]) + next_indent = indent + for line in lines[1:]: + if line: + next_indent = self._get_indent(line) + break + return next_indent > indent + def _is_section_header(self): section = self._line_iter.peek().lower() match = _google_section_regex.match(section) @@ -530,10 +554,18 @@ class GoogleDocstring(UnicodeMixin): if self._config.napoleon_use_param: lines = [] for _name, _type, _desc in fields: - field = ':param %s: ' % _name - lines.extend(self._format_block(field, _desc)) + _desc = self._strip_empty(_desc) + if any(_desc): + if self._is_list(_desc): + _desc = [''] + _desc + field = ':param %s: ' % _name + lines.extend(self._format_block(field, _desc)) + else: + lines.append(':param %s:' % _name) + if _type: lines.append(':type %s: %s' % (_name, _type)) + return lines + [''] else: return self._format_fields('Parameters', fields) @@ -777,10 +809,11 @@ class NumpyDocstring(GoogleDocstring): _name, _type = line, '' _name, _type = _name.strip(), _type.strip() _name = self._escape_args_and_kwargs(_name) + if prefer_type and not _type: _type, _name = _name, _type - indent = self._get_indent(line) - _desc = self._dedent(self._consume_indented_block(indent + 1)) + indent = self._get_indent(line) + 1 + _desc = self._dedent(self._consume_indented_block(indent)) _desc = self.__class__(_desc, self._config).lines() return _name, _type, _desc diff --git a/sphinx/ext/napoleon/iterators.py b/sphinx/ext/napoleon/iterators.py index f59a3f088..f66d67f2c 100644 --- a/sphinx/ext/napoleon/iterators.py +++ b/sphinx/ext/napoleon/iterators.py @@ -7,7 +7,7 @@ A collection of helpful iterators. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/pngmath.py b/sphinx/ext/pngmath.py index 8ef860f80..a2801bd1f 100644 --- a/sphinx/ext/pngmath.py +++ b/sphinx/ext/pngmath.py @@ -3,9 +3,10 @@ sphinx.ext.pngmath ~~~~~~~~~~~~~~~~~~ - Render math in HTML via dvipng. + Render math in HTML via dvipng. This extension has been deprecated; please + use sphinx.ext.imgmath instead. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -212,7 +213,8 @@ def html_visit_displaymath(self, node): if node['nowrap']: latex = node['latex'] else: - latex = wrap_displaymath(node['latex'], None) + latex = wrap_displaymath(node['latex'], None, + self.builder.config.math_number_all) try: fname, depth = render_math(self, latex) except MathExtError as exc: @@ -236,6 +238,7 @@ def html_visit_displaymath(self, node): def setup(app): + app.warn('sphinx.ext.pngmath has been deprecated. Please use sphinx.ext.imgmath instead.') mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None)) app.add_config_value('pngmath_dvipng', 'dvipng', 'html') app.add_config_value('pngmath_latex', 'latex', 'html') diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index faa086fc8..a853ec93c 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -8,7 +8,7 @@ all todos of your project and lists them along with a backlink to the original location. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -19,7 +19,8 @@ import sphinx from sphinx.locale import _ from sphinx.environment import NoUri from sphinx.util.nodes import set_source_info -from sphinx.util.compat import Directive, make_admonition +from docutils.parsers.rst import Directive +from docutils.parsers.rst.directives.admonitions import BaseAdmonition class todo_node(nodes.Admonition, nodes.Element): @@ -30,11 +31,12 @@ class todolist(nodes.General, nodes.Element): pass -class Todo(Directive): +class Todo(BaseAdmonition): """ A todo entry, displayed (if configured) in the form of an admonition. """ + node_class = todo_node has_content = True required_arguments = 0 optional_arguments = 0 @@ -44,18 +46,20 @@ class Todo(Directive): } def run(self): - env = self.state.document.settings.env - targetid = 'index-%s' % env.new_serialno('index') - targetnode = nodes.target('', '', ids=[targetid]) - if not self.options.get('class'): self.options['class'] = ['admonition-todo'] - ad = make_admonition(todo_node, self.name, [_('Todo')], self.options, - self.content, self.lineno, self.content_offset, - self.block_text, self.state, self.state_machine) - set_source_info(self, ad[0]) - return [targetnode] + ad + (todo,) = super(Todo, self).run() + if isinstance(todo, nodes.system_message): + return [todo] + + todo.insert(0, nodes.title(text=_('Todo'))) + set_source_info(self, todo) + + env = self.state.document.settings.env + targetid = 'index-%s' % env.new_serialno('index') + targetnode = nodes.target('', '', ids=[targetid]) + return [targetnode, todo] def process_todos(app, doctree): @@ -121,9 +125,13 @@ def process_todo_nodes(app, doctree, fromdocname): for todo_info in env.todo_all_todos: para = nodes.paragraph(classes=['todo-source']) - description = _('(The <> is located in ' - ' %s, line %d.)') % \ - (todo_info['source'], todo_info['lineno']) + if app.config['todo_link_only']: + description = _('<>') + else: + description = ( + _('(The <> is located in %s, line %d.)') % + (todo_info['source'], todo_info['lineno']) + ) desc1 = description[:description.find('<<')] desc2 = description[description.find('>>')+2:] para += nodes.Text(desc1, desc1) @@ -180,6 +188,7 @@ def depart_todo_node(self, node): def setup(app): app.add_config_value('todo_include_todos', False, 'html') + app.add_config_value('todo_link_only', False, 'html') app.add_node(todolist) app.add_node(todo_node, diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py index e6af4f550..d64cc88f7 100644 --- a/sphinx/ext/viewcode.py +++ b/sphinx/ext/viewcode.py @@ -5,7 +5,7 @@ Add links to module code in Python object descriptions. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index 6f22993c2..eb008dc4e 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -5,7 +5,7 @@ Highlight code blocks using Pygments. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -183,9 +183,13 @@ class PygmentsBridge(object): formatter = self.get_formatter(**kwargs) try: hlsource = highlight(source, lexer, formatter) - except ErrorToken: + except ErrorToken as exc: # this is most probably not the selected language, # so let it pass unhighlighted + if warn: + warn('Could not parse literal_block as "%s". highlighting skipped.' % lang) + else: + raise exc hlsource = highlight(source, lexers['none'], formatter) if self.dest == 'html': return hlsource diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py index c8a7165fc..f3ce87a8c 100644 --- a/sphinx/jinja2glue.py +++ b/sphinx/jinja2glue.py @@ -5,7 +5,7 @@ Glue code for the jinja2 templating engine. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py index 444ad5d0c..f7a375dec 100644 --- a/sphinx/locale/__init__.py +++ b/sphinx/locale/__init__.py @@ -5,7 +5,7 @@ Locale utilities. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/make_mode.py b/sphinx/make_mode.py index 7d239f51c..67ba9e1e1 100644 --- a/sphinx/make_mode.py +++ b/sphinx/make_mode.py @@ -11,7 +11,7 @@ This is in its own module so that importing it is fast. It should not import the main Sphinx modules (like sphinx.applications, sphinx.builders). - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/parsers.py b/sphinx/parsers.py new file mode 100644 index 000000000..926de9f1c --- /dev/null +++ b/sphinx/parsers.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +""" + sphinx.parsers + ~~~~~~~~~~~~~~ + + A Base class for additional parsers. + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import docutils.parsers + + +class Parser(docutils.parsers.Parser): + """ + A base class of source parsers. The additonal parsers should inherits this class instead + of ``docutils.parsers.Parser``. Compared with ``docutils.parsers.Parser``, this class + improves accessibility to Sphinx APIs. + + The subclasses can access following objects and functions: + + self.app + The application object (:class:`sphinx.application.Sphinx`) + self.config + The config object (:class:`sphinx.config.Config`) + self.env + The environment object (:class:`sphinx.environment.BuildEnvironment`) + self.warn() + Emit a warning. (Same as :meth:`sphinx.application.Sphinx.warn()`) + self.info() + Emit a informational message. (Same as :meth:`sphinx.application.Sphinx.info()`) + """ + + def set_application(self, app): + """set_application will be called from Sphinx to set app and other instance variables + + :param sphinx.application.Sphinx app: Sphinx application object + """ + self.app = app + self.config = app.config + self.env = app.env + self.warn = app.warn + self.info = app.info diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py index 57707e9d0..3da887d6c 100644 --- a/sphinx/pycode/__init__.py +++ b/sphinx/pycode/__init__.py @@ -5,7 +5,7 @@ Utilities parsing and analyzing Python code. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function @@ -300,7 +300,7 @@ class ModuleAnalyzer(object): yield tokentup tokeniter = tokeniter() for type, tok, spos, epos, line in tokeniter: - if expect_indent: + if expect_indent and type != token.NL: if type != token.INDENT: # no suite -- one-line definition assert stack diff --git a/sphinx/pycode/nodes.py b/sphinx/pycode/nodes.py index 3b244db7f..ee40f3c0d 100644 --- a/sphinx/pycode/nodes.py +++ b/sphinx/pycode/nodes.py @@ -5,7 +5,7 @@ Parse tree node implementations. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/pygments_styles.py b/sphinx/pygments_styles.py index ff2263e1c..469947149 100644 --- a/sphinx/pygments_styles.py +++ b/sphinx/pygments_styles.py @@ -5,7 +5,7 @@ Sphinx theme specific highlighting styles. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index ffc4961dc..7d7271824 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -5,7 +5,7 @@ Quickly setup documentation source to work with Sphinx. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function @@ -60,7 +60,7 @@ DEFAULT_VALUE = { } EXTENSIONS = ('autodoc', 'doctest', 'intersphinx', 'todo', 'coverage', - 'pngmath', 'mathjax', 'ifconfig', 'viewcode') + 'imgmath', 'mathjax', 'ifconfig', 'viewcode', 'githubpages') PROMPT_PREFIX = '> ' @@ -146,6 +146,7 @@ language = %(language)r # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path exclude_patterns = [%(exclude_patterns)s] # The reST default role (used for this markup: `text`) to use for all @@ -190,9 +191,9 @@ html_theme = 'alabaster' # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None +# The name for this set of Sphinx documents. +# " v documentation" by default. +#html_title = u'%(project_str)s v%(release_str)s' # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None @@ -261,11 +262,12 @@ html_static_path = ['%(dot)sstatic'] # 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' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' #html_search_language = 'en' # A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value +# 'ja' uses this config value. +# 'zh' user can custom change `jieba` dictionary path. #html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that @@ -295,8 +297,8 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, '%(project_fn)s.tex', u'%(project_doc_texescaped_str)s', - u'%(author_texescaped_str)s', 'manual'), + (master_doc, '%(project_fn)s.tex', u'%(project_doc_texescaped_str)s', + u'%(author_texescaped_str)s', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -339,9 +341,9 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, '%(project_fn)s', u'%(project_doc_str)s', - author, '%(project_fn)s', 'One line description of project.', - 'Miscellaneous'), + (master_doc, '%(project_fn)s', u'%(project_doc_str)s', + author, '%(project_fn)s', 'One line description of project.', + 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. @@ -370,10 +372,10 @@ epub_copyright = copyright # The basename for the epub file. It defaults to the project name. #epub_basename = project -# The HTML theme for the epub output. Since the default themes are not optimized -# for small screen space, using the same theme for HTML and epub output is -# usually not wise. This defaults to 'epub', a theme designed to save visual -# space. +# The HTML theme for the epub output. Since the default themes are not +# optimized for small screen space, using the same theme for HTML and epub +# output is usually not wise. This defaults to 'epub', a theme designed to save +# visual space. #epub_theme = 'epub' # The language of the text. It defaults to the language option @@ -400,7 +402,7 @@ epub_copyright = copyright # The format is a list of tuples containing the path and title. #epub_pre_files = [] -# HTML files shat should be inserted after the pages created by sphinx. +# HTML files that should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_post_files = [] @@ -488,9 +490,7 @@ $(SPHINXOPTS) %(rsrcdir)s # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) %(rsrcdir)s -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp \ -epub latex latexpdf text man changes linkcheck doctest coverage gettext - +.PHONY: help help: \t@echo "Please use \\`make ' where is one of" \t@echo " html to make standalone HTML files" @@ -503,6 +503,7 @@ help: \t@echo " applehelp to make an Apple Help Book" \t@echo " devhelp to make HTML files and a Devhelp project" \t@echo " epub to make an epub" +\t@echo " epub3 to make an epub3" \t@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" \t@echo " latexpdf to make LaTeX files and run them through pdflatex" \t@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @@ -519,40 +520,48 @@ help: (if enabled)" \t@echo " coverage to run coverage check of the documentation (if enabled)" +.PHONY: clean clean: \trm -rf $(BUILDDIR)/* +.PHONY: html html: \t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html \t@echo \t@echo "Build finished. The HTML pages are in $(BUILDDIR)/html." +.PHONY: dirhtml dirhtml: \t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml \t@echo \t@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." +.PHONY: singlehtml singlehtml: \t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml \t@echo \t@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." +.PHONY: pickle pickle: \t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle \t@echo \t@echo "Build finished; now you can process the pickle files." +.PHONY: json json: \t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json \t@echo \t@echo "Build finished; now you can process the JSON files." +.PHONY: htmlhelp htmlhelp: \t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp \t@echo \t@echo "Build finished; now you can run HTML Help Workshop with the" \\ \t ".hhp project file in $(BUILDDIR)/htmlhelp." +.PHONY: qthelp qthelp: \t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp \t@echo @@ -562,6 +571,7 @@ qthelp: \t@echo "To view the help file:" \t@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/%(project_fn)s.qhc" +.PHONY: applehelp applehelp: \t$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp \t@echo @@ -570,6 +580,7 @@ applehelp: \t "~/Library/Documentation/Help or install it in your application" \\ \t "bundle." +.PHONY: devhelp devhelp: \t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp \t@echo @@ -580,11 +591,19 @@ devhelp: $$HOME/.local/share/devhelp/%(project_fn)s" \t@echo "# devhelp" +.PHONY: epub epub: \t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub \t@echo \t@echo "Build finished. The epub file is in $(BUILDDIR)/epub." +.PHONY: epub3 +epub3: +\t$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 +\t@echo +\t@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." + +.PHONY: latex latex: \t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex \t@echo @@ -592,28 +611,33 @@ latex: \t@echo "Run \\`make' in that directory to run these through (pdf)latex" \\ \t "(use \\`make latexpdf' here to do that automatically)." +.PHONY: latexpdf latexpdf: \t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex \t@echo "Running LaTeX files through pdflatex..." \t$(MAKE) -C $(BUILDDIR)/latex all-pdf \t@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." +.PHONY: latexpdfja latexpdfja: \t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex \t@echo "Running LaTeX files through platex and dvipdfmx..." \t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja \t@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." +.PHONY: text text: \t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text \t@echo \t@echo "Build finished. The text files are in $(BUILDDIR)/text." +.PHONY: man man: \t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man \t@echo \t@echo "Build finished. The manual pages are in $(BUILDDIR)/man." +.PHONY: texinfo texinfo: \t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo \t@echo @@ -621,43 +645,51 @@ texinfo: \t@echo "Run \\`make' in that directory to run these through makeinfo" \\ \t "(use \\`make info' here to do that automatically)." +.PHONY: info info: \t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo \t@echo "Running Texinfo files through makeinfo..." \tmake -C $(BUILDDIR)/texinfo info \t@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." +.PHONY: gettext gettext: \t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale \t@echo \t@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." +.PHONY: changes changes: \t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes \t@echo \t@echo "The overview file is in $(BUILDDIR)/changes." +.PHONY: linkcheck linkcheck: \t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck \t@echo \t@echo "Link check complete; look for any errors in the above output " \\ \t "or in $(BUILDDIR)/linkcheck/output.txt." +.PHONY: doctest doctest: \t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest \t@echo "Testing of doctests in the sources finished, look at the " \\ \t "results in $(BUILDDIR)/doctest/output.txt." +.PHONY: coverage 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." +.PHONY: xml xml: \t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml \t@echo \t@echo "Build finished. The XML files are in $(BUILDDIR)/xml." +.PHONY: pseudoxml pseudoxml: \t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml \t@echo @@ -694,6 +726,7 @@ if "%%1" == "help" ( \techo. qthelp to make HTML files and a qthelp project \techo. devhelp to make HTML files and a Devhelp project \techo. epub to make an epub +\techo. epub3 to make an epub3 \techo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter \techo. text to make text files \techo. man to make manual pages @@ -816,6 +849,14 @@ if "%%1" == "epub" ( \tgoto end ) +if "%%1" == "epub3" ( +\t%%SPHINXBUILD%% -b epub3 %%ALLSPHINXOPTS%% %%BUILDDIR%%/epub3 +\tif errorlevel 1 exit /b 1 +\techo. +\techo.Build finished. The epub3 file is in %%BUILDDIR%%/epub3. +\tgoto end +) + if "%%1" == "latex" ( \t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex \tif errorlevel 1 exit /b 1 @@ -1255,22 +1296,25 @@ Please indicate if you want to use one of the following Sphinx extensions:''') if 'ext_coverage' not in d: do_prompt(d, 'ext_coverage', 'coverage: checks for documentation ' 'coverage (y/n)', 'n', boolean) - if 'ext_pngmath' not in d: - do_prompt(d, 'ext_pngmath', 'pngmath: include math, rendered ' - 'as PNG images (y/n)', 'n', boolean) + if 'ext_imgmath' not in d: + do_prompt(d, 'ext_imgmath', 'imgmath: include math, rendered ' + 'as PNG or SVG images (y/n)', 'n', boolean) if 'ext_mathjax' not in d: do_prompt(d, 'ext_mathjax', 'mathjax: include math, rendered in the ' 'browser by MathJax (y/n)', 'n', boolean) - if d['ext_pngmath'] and d['ext_mathjax']: - print('''Note: pngmath and mathjax cannot be enabled at the same time. -pngmath has been deselected.''') - d['ext_pngmath'] = False + if d['ext_imgmath'] and d['ext_mathjax']: + print('''Note: imgmath and mathjax cannot be enabled at the same time. +imgmath has been deselected.''') + d['ext_imgmath'] = False if 'ext_ifconfig' not in d: do_prompt(d, 'ext_ifconfig', 'ifconfig: conditional inclusion of ' 'content based on config values (y/n)', 'n', boolean) if 'ext_viewcode' not in d: do_prompt(d, 'ext_viewcode', 'viewcode: include links to the source ' 'code of documented Python objects (y/n)', 'n', boolean) + if 'ext_githubpages' not in d: + do_prompt(d, 'ext_githubpages', 'githubpages: create .nojekyll file ' + 'to publish the document on GitHub pages (y/n)', 'n', boolean) if 'no_makefile' in d: d['makefile'] = False @@ -1337,7 +1381,11 @@ def generate(d, overwrite=True, silent=False): d['exclude_patterns'] = '' else: builddir = path.join(srcdir, d['dot'] + 'build') - d['exclude_patterns'] = repr(d['dot'] + 'build') + exclude_patterns = map(repr, [ + d['dot'] + 'build', + 'Thumbs.db', '.DS_Store', + ]) + d['exclude_patterns'] = ', '.join(exclude_patterns) mkdir_p(builddir) mkdir_p(path.join(srcdir, d['dot'] + 'templates')) mkdir_p(path.join(srcdir, d['dot'] + 'static')) diff --git a/sphinx/roles.py b/sphinx/roles.py index 96e098569..59d69a1f1 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -5,7 +5,7 @@ Handlers for additional ReST roles. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -29,7 +29,7 @@ generic_docroles = { 'kbd': nodes.literal, 'mailheader': addnodes.literal_emphasis, 'makevar': addnodes.literal_strong, - 'manpage': addnodes.literal_emphasis, + 'manpage': addnodes.manpage, 'mimetype': addnodes.literal_emphasis, 'newsgroup': addnodes.literal_emphasis, 'program': addnodes.literal_strong, # XXX should be an x-ref diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py index 050ab2d7f..75d03f19d 100644 --- a/sphinx/search/__init__.py +++ b/sphinx/search/__init__.py @@ -5,7 +5,7 @@ Create a full-text search index for offline search. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re @@ -135,6 +135,7 @@ languages = { 'ru': 'sphinx.search.ru.SearchRussian', 'sv': 'sphinx.search.sv.SearchSwedish', 'tr': 'sphinx.search.tr.SearchTurkish', + 'zh': 'sphinx.search.zh.SearchChinese', } diff --git a/sphinx/search/de.py b/sphinx/search/de.py index 89cbe3de5..35c6263c4 100644 --- a/sphinx/search/de.py +++ b/sphinx/search/de.py @@ -311,4 +311,5 @@ class SearchGerman(SearchLanguage): self.stemmer = snowballstemmer.stemmer('german') def stem(self, word): + word = word.lower() return self.stemmer.stemWord(word) diff --git a/sphinx/search/en.py b/sphinx/search/en.py index de77ae294..9501cddeb 100644 --- a/sphinx/search/en.py +++ b/sphinx/search/en.py @@ -5,25 +5,18 @@ English search language: includes the JS porter stemmer. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from sphinx.search import SearchLanguage try: - # http://bitbucket.org/methane/porterstemmer/ - from porterstemmer import Stemmer as CStemmer - CSTEMMER = True - PYSTEMMER = False + from Stemmer import Stemmer as PyStemmer + PYSTEMMER = True except ImportError: - CSTEMMER = False - try: - from Stemmer import Stemmer as PyStemmer - PYSTEMMER = True - except ImportError: - from sphinx.util.stemmer import PorterStemmer - PYSTEMMER = False + from sphinx.util.stemmer import PorterStemmer + PYSTEMMER = False english_stopwords = set(""" a and are as at @@ -231,11 +224,7 @@ class SearchEnglish(SearchLanguage): stopwords = english_stopwords def init(self, options): - if CSTEMMER: - class Stemmer(CStemmer): - def stem(self, word): - return self(word.lower()) - elif PYSTEMMER: + if PYSTEMMER: class Stemmer(object): def __init__(self): self.stemmer = PyStemmer('porter') diff --git a/sphinx/search/ja.py b/sphinx/search/ja.py index 23de74d37..6e9ead616 100644 --- a/sphinx/search/ja.py +++ b/sphinx/search/ja.py @@ -5,7 +5,7 @@ Japanese search language: includes routine to split words. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -29,6 +29,7 @@ try: except ImportError: native_module = False +from sphinx.errors import SphinxError from sphinx.search import SearchLanguage @@ -86,9 +87,16 @@ class MecabBinder(object): if dict: param += ' -d %s' % dict + fs_enc = sys.getfilesystemencoding() or sys.getdefaultencoding() + self.ctypes_libmecab = ctypes.CDLL(libpath) + self.ctypes_libmecab.mecab_new2.argtypes = (ctypes.c_char_p,) + self.ctypes_libmecab.mecab_new2.restype = ctypes.c_void_p + self.ctypes_libmecab.mecab_sparse_tostr.argtypes = (ctypes.c_void_p, ctypes.c_char_p) self.ctypes_libmecab.mecab_sparse_tostr.restype = ctypes.c_char_p - self.ctypes_mecab = self.ctypes_libmecab.mecab_new2(param) + self.ctypes_mecab = self.ctypes_libmecab.mecab_new2(param.encode(fs_enc)) + if self.ctypes_mecab is None: + raise SphinxError('mecab initialization failed') def __del__(self): if self.ctypes_libmecab: diff --git a/sphinx/search/zh.py b/sphinx/search/zh.py new file mode 100644 index 000000000..92f66e971 --- /dev/null +++ b/sphinx/search/zh.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +""" + sphinx.search.zh + ~~~~~~~~~~~~~~~~ + + Chinese search language: includes routine to split words. + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import os +import re + +from sphinx.search import SearchLanguage + +try: + from Stemmer import Stemmer as PyStemmer + PYSTEMMER = True +except ImportError: + from sphinx.util.stemmer import PorterStemmer + PYSTEMMER = False + +try: + import jieba + JIEBA = True +except ImportError: + JIEBA = False + +english_stopwords = set(""" +a and are as at +be but by +for +if in into is it +near no not +of on or +such +that the their then there these they this to +was will with +""".split()) + +js_porter_stemmer = """ +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|\ +ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|\ +iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} +""" + + +class SearchChinese(SearchLanguage): + """ + Chinese search implementation + """ + + lang = 'zh' + language_name = 'Chinese' + js_stemmer_code = js_porter_stemmer + stopwords = english_stopwords + latin1_letters = re.compile(r'\w+(?u)[\u0000-\u00ff]') + + def init(self, options): + if JIEBA: + dict_path = options.get('dict') + if dict_path and os.path.isfile(dict_path): + jieba.set_dictionary(dict_path) + + if 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; + make at least the stem method nicer. + """ + def stem(self, word): + word = word.lower() + return PorterStemmer.stem(self, word, 0, len(word) - 1) + + self.stemmer = Stemmer() + + def split(self, input): + chinese = [] + if JIEBA: + chinese = list(jieba.cut_for_search(input)) + + latin1 = self.latin1_letters.findall(input) + return chinese + latin1 + + def word_filter(self, stemmed_word): + return len(stemmed_word) > 1 + + def stem(self, word): + return self.stemmer.stem(word) diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py index 1a942c5da..128c1415c 100644 --- a/sphinx/setup_command.py +++ b/sphinx/setup_command.py @@ -8,7 +8,7 @@ :author: Sebastian Wiesner :contact: basti.wiesner@gmx.net - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile index 5e6030c0d..d748006cc 100644 --- a/sphinx/texinputs/Makefile +++ b/sphinx/texinputs/Makefile @@ -8,6 +8,8 @@ ALLDVI = $(addsuffix .dvi,$(ALLDOCS)) ARCHIVEPRREFIX = # Additional LaTeX options LATEXOPTS = +# format: pdf or dvi +FMT = pdf LATEX = latex PDFLATEX = pdflatex @@ -41,9 +43,15 @@ tar: all-$(FMT) tar cf $(ARCHIVEPREFIX)docs-$(FMT).tar $(ARCHIVEPREFIX)docs-$(FMT) rm -r $(ARCHIVEPREFIX)docs-$(FMT) +gz: tar + gzip -9 < $(ARCHIVEPREFIX)docs-$(FMT).tar > $(ARCHIVEPREFIX)docs-$(FMT).tar.gz + bz2: tar bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar +xz: tar + xz -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar + # The number of LaTeX runs is quite conservative, but I don't expect it # to get run often, so the little extra time won't hurt. %.dvi: %.tex @@ -63,8 +71,8 @@ bz2: tar $(PDFLATEX) $(LATEXOPTS) '$<' clean: - rm -f *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla + rm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz $(ALLPDF) $(ALLDVI) -.PHONY: all all-pdf all-dvi all-ps clean +.PHONY: all all-pdf all-dvi all-ps clean zip tar gz bz2 xz .PHONY: all-pdf-ja diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 210f6ea1d..f94d5c934 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -19,7 +19,13 @@ \RequirePackage{makeidx} \RequirePackage{framed} \RequirePackage{ifthen} -\RequirePackage{color} +%The xcolor package draws better fcolorboxes +%around verbatim code +\IfFileExists{xcolor.sty}{ + \RequirePackage[xcdraw]{xcolor} +}{ + \RequirePackage{color} +} % For highlighted code. \RequirePackage{fancyvrb} % For table captions. @@ -52,18 +58,12 @@ %\renewcommand{\paperwidth}{7in} % O'Reilly ``Programmming Python'' % use pdfoutput for pTeX and dvipdfmx +% when pTeX (\kanjiskip is defined), set pdfoutput to evade \include{pdfcolor} \ifx\kanjiskip\undefined\else - \ifx\Gin@driver{dvipdfmx.def}\undefined\else - \newcount\pdfoutput\pdfoutput=0 - \fi + \newcount\pdfoutput\pdfoutput=0 \fi -% For graphicx, check if we are compiling under latex or pdflatex. -\ifx\pdftexversion\undefined - \usepackage{graphicx} -\else - \usepackage[pdftex]{graphicx} -\fi +\RequirePackage{graphicx} % for PDF output, use colors and maximal compression \newif\ifsphinxpdfoutput\sphinxpdfoutputfalse @@ -270,16 +270,15 @@ \fbox{\TheSbox} } -\newcommand{\py@lightbox}{{% - \setlength\parskip{0pt}\par - \noindent\rule[0ex]{\linewidth}{0.5pt}% - \par\noindent\vspace{-0.5ex}% - }} -\newcommand{\py@endlightbox}{{% - \setlength{\parskip}{0pt}% - \par\noindent\rule[0.5ex]{\linewidth}{0.5pt}% - \par\vspace{-0.5ex}% - }} +\newcommand{\py@lightbox}{% + \par\allowbreak + \noindent\rule{\linewidth}{0.5pt}\par\nobreak + {\parskip\z@skip\noindent}% + } +\newcommand{\py@endlightbox}{% + \par\nobreak + {\parskip\z@skip\noindent\rule[.4\baselineskip]{\linewidth}{0.5pt}}\par + } % Some are quite plain: \newcommand{\py@noticestart@note}{\py@lightbox} @@ -445,15 +444,18 @@ \RequirePackage{hypcap} % From docutils.writers.latex2e -\providecommand{\DUspan}[2]{% - {% group ("span") to limit the scope of styling commands - \@for\node@class@name:=#1\do{% - \ifcsname docutilsrole\node@class@name\endcsname% - \csname docutilsrole\node@class@name\endcsname% +% inline markup (custom roles) +% \DUrole{#1}{#2} tries \DUrole#1{#2} +\providecommand*{\DUrole}[2]{% + \ifcsname DUrole#1\endcsname% + \csname DUrole#1\endcsname{#2}% + \else% backwards compatibility: try \docutilsrole#1{#2} + \ifcsname docutilsrole#1\endcsname% + \csname docutilsrole#1\endcsname{#2}% + \else% + #2% \fi% - }% - {#2}% node content - }% close "span" + \fi% } \providecommand*{\DUprovidelength}[2]{ @@ -525,11 +527,18 @@ \fi % Define literal-block environment -\RequirePackage{float} -\floatstyle{plaintop} +\RequirePackage{newfloat} +\DeclareFloatingEnvironment{literal-block} \ifx\thechapter\undefined - \newfloat{literal-block}{htbp}{loc}[section] + \SetupFloatingEnvironment{literal-block}{within=section,placement=h} \else - \newfloat{literal-block}{htbp}{loc}[chapter] + \SetupFloatingEnvironment{literal-block}{within=chapter,placement=h} \fi -\floatname{literal-block}{List} +\SetupFloatingEnvironment{literal-block}{name=List} +% control caption around literal-block +\RequirePackage{capt-of} +\RequirePackage{needspace} +% if the left page space is less than \literalblockneedsapce, insert page-break +\newcommand{\literalblockneedspace}{5\baselineskip} +% margin before the caption of literal-block +\newcommand{\literalblockcaptiontopvspace}{0.5\baselineskip} diff --git a/sphinx/themes/agogo/layout.html b/sphinx/themes/agogo/layout.html index 6a80a207f..9a24b834f 100644 --- a/sphinx/themes/agogo/layout.html +++ b/sphinx/themes/agogo/layout.html @@ -5,7 +5,7 @@ Sphinx layout template for the agogo theme, originally written by Andi Albrecht. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/sphinx/themes/agogo/static/agogo.css_t b/sphinx/themes/agogo/static/agogo.css_t index 87801d685..26df9d6d5 100644 --- a/sphinx/themes/agogo/static/agogo.css_t +++ b/sphinx/themes/agogo/static/agogo.css_t @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- agogo theme. * - * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/basic/changes/frameset.html b/sphinx/themes/basic/changes/frameset.html index 9d9af9eb5..e14cb9e15 100644 --- a/sphinx/themes/basic/changes/frameset.html +++ b/sphinx/themes/basic/changes/frameset.html @@ -1,6 +1,6 @@ - + {% trans version=version|e, docstitle=docstitle|e %}Changes in Version {{ version }} — {{ docstitle }}{% endtrans %} diff --git a/sphinx/themes/basic/changes/rstsource.html b/sphinx/themes/basic/changes/rstsource.html index abd12c1d0..0a27479b0 100644 --- a/sphinx/themes/basic/changes/rstsource.html +++ b/sphinx/themes/basic/changes/rstsource.html @@ -1,6 +1,6 @@ - + {% trans filename=filename, docstitle=docstitle|e %}{{ filename }} — {{ docstitle }}{% endtrans %}