Merge branch '3.x' into 6040_autosummary_recursive

This commit is contained in:
Takeshi KOMIYA 2020-04-21 23:04:38 +09:00
commit b9da9237bc
665 changed files with 92475 additions and 68089 deletions

View File

@ -7,5 +7,5 @@ jobs:
steps:
- checkout
- run: /python3.6/bin/pip install -U pip setuptools
- run: /python3.6/bin/pip install -U .[test,websupport]
- run: /python3.6/bin/pip install -U .[test]
- run: make test PYTHON=/python3.6/bin/python

View File

@ -1,3 +1,4 @@
comment: false
coverage:
status:
project:

6
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,6 @@
# Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
blank_issues_enabled: false # default: true
contact_links:
- name: Question
url: https://groups.google.com/forum/#!forum/sphinx-users
about: For Q&A purpose, please use sphinx-users mailing list.

View File

@ -1,17 +0,0 @@
---
name: Question
about: For Q&A purpose, please use https://groups.google.com/forum/#!forum/sphinx-users
title: For Q&A purpose, please use sphinx-users group
labels: 'question'
assignees: ''
---
# Important
This is a list of issues for Sphinx, **not a forum**.
If you'd like to post a question, please move to sphinx-users group.
https://groups.google.com/forum/#!forum/sphinx-users
Thanks,

View File

@ -1,9 +1,20 @@
Subject: <short purpose of this pull request>
<!--
Before posting a pull request, please choose a appropriate branch:
- Breaking changes: master
- Critical or severe bugs: X.Y.Z
- Others: X.Y
For more details, see https://www.sphinx-doc.org/en/master/devguide.html#branch-model
-->
### Feature or Bugfix
<!-- please choose -->
- Feature
- Bugfix
- Refactoring
### Purpose
- <long purpose of this pull request>

1
.gitignore vendored
View File

@ -23,6 +23,7 @@ distribute-*
env/
build/
dist/
docker/
Sphinx.egg-info/
doc/_build/
doc/locale/

View File

@ -1,6 +1,6 @@
language: python
sudo: false
os: linux
dist: xenial
language: python
cache: pip
env:
@ -9,7 +9,7 @@ env:
- SKIP_LATEX_BUILD=1
- IS_PYTHON=true
matrix:
jobs:
include:
- python: '3.5'
env:
@ -19,10 +19,14 @@ matrix:
- TOXENV=du13
- python: '3.7'
env:
- TOXENV=py37
- TOXENV=du14
- python: '3.8'
env:
- TOXENV=du15
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
- python: 'nightly'
env: TOXENV=py38
env:
- TOXENV=du16
- python: '3.6'
env: TOXENV=docs
- python: '3.6'
@ -33,8 +37,7 @@ matrix:
env: TOXENV=flake8
- language: node_js
node_js:
- 10.7
node_js: '10.7'
env: IS_PYTHON=false
services: xvfb

View File

@ -25,6 +25,7 @@ Other contributors, listed alphabetically, are:
* Henrique Bastos -- SVG support for graphviz extension
* Daniel Bültmann -- todo extension
* Marco Buttu -- doctest extension (pyversion option)
* Nathan Damon -- bugfix in validation of static paths in html builders
* Etienne Desautels -- apidoc module
* Michael Droettboom -- inheritance_diagram extension
* Charles Duffy -- original graphviz extension
@ -35,7 +36,7 @@ Other contributors, listed alphabetically, are:
* Hernan Grecco -- search improvements
* Horst Gutmann -- internationalization support
* Martin Hans -- autodoc improvements
* Zac Hatfield-Dodds -- doctest reporting improvements
* Zac Hatfield-Dodds -- doctest reporting improvements, intersphinx performance
* Doug Hellmann -- graphviz improvements
* Tim Hoffmann -- theme improvements
* Antti Kaihola -- doctest extension (skipif option)
@ -63,6 +64,7 @@ Other contributors, listed alphabetically, are:
* \T. Powers -- HTML output improvements
* Jeppe Pihl -- literalinclude improvements
* Rob Ruana -- napoleon extension
* Vince Salvino -- JavaScript search improvements
* Stefan Seefeld -- toctree improvements
* Gregory Szorc -- performance improvements
* Taku Shimizu -- epub3 builder

621
CHANGES
View File

@ -1,4 +1,4 @@
Release 3.0.0 (in development)
Release 3.1.0 (in development)
==============================
Dependencies
@ -7,18 +7,35 @@ Dependencies
Incompatible changes
--------------------
* Drop features and APIs deprecated in 1.8.x
* #247: autosummary: stub files are overwritten automatically by default. see
:confval:`autosummary_generate_overwrite` to change the behavior
* #7477: imgconverter: Invoke "magick convert" command by default on Windows
Deprecated
----------
* The ``module`` argument of ``sphinx.ext.autosummary.generate.
find_autosummary_in_docstring()``
Features added
--------------
* #247: autosummary: Add :confval:`autosummary_generate_overwrite` to overwrite
old stub file
* LaTeX: Make the ``toplevel_sectioning`` setting optional in LaTeX theme
* LaTeX: Allow to override papersize and pointsize from LaTeX themes
* LaTeX: Add :confval:`latex_theme_options` to override theme options
* #7410: Allow to suppress "circular toctree references detected" warnings using
:confval:`suppress_warnings`
* C, added scope control directives, :rst:dir:`c:namespace`,
:rst:dir:`c:namespace-push`, and :rst:dir:`c:namespace-pop`.
* #7466: autosummary: headings in generated documents are not translated
* #7490: autosummary: Add ``:caption:`` option to autosummary directive to set a
caption to the toctree
* #7481: html theme: Add right margin to footnote/citation labels
* #7482: html theme: CSS spacing for code blocks with captions and line numbers
* #7443: html theme: Add new options :confval:`globaltoc_collapse` and
:confval:`globaltoc_includehidden` to control the behavior of globaltoc in
sidebar
* #7484: html theme: Avoid clashes between sidebar and other blocks
* #7476: html theme: Relbar breadcrumb should contain current page
* #7506: html theme: A canonical URL is not escaped
Bugs fixed
----------
@ -26,7 +43,7 @@ Bugs fixed
Testing
--------
Release 2.2.0 (in development)
Release 3.0.3 (in development)
==============================
Dependencies
@ -35,7 +52,546 @@ Dependencies
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
Testing
--------
Release 3.0.2 (released Apr 19, 2020)
=====================================
Features added
--------------
* C, parse attributes and add :confval:`c_id_attributes`
and :confval:`c_paren_attributes` to support user-defined attributes.
Bugs fixed
----------
* #7461: py domain: fails with IndexError for empty tuple in type annotation
* #7510: py domain: keyword-only arguments are documented as having a default of
None
* #7418: std domain: :rst:role:`term` role could not match case-insensitively
* #7461: autodoc: empty tuple in type annotation is not shown correctly
* #7479: autodoc: Sphinx builds has been slower since 3.0.0 on mocking
* C++, fix spacing issue in east-const declarations.
* #7414: LaTeX: Xindy language options were incorrect
* sphinx crashes with ImportError on python3.5.1
Release 3.0.1 (released Apr 11, 2020)
=====================================
Incompatible changes
--------------------
* #7418: std domain: :rst:dir:`term` role becomes case sensitive
Bugs fixed
----------
* #7428: py domain: a reference to class ``None`` emits a nitpicky warning
* #7445: py domain: a return annotation ``None`` in the function signature is
not converted to a hyperlink when using intersphinx
* #7418: std domain: duplication warning for glossary terms is case insensitive
* #7438: C++, fix merging overloaded functions in parallel builds.
* #7422: autodoc: fails with ValueError when using autodoc_mock_imports
* #7435: autodoc: ``autodoc_typehints='description'`` doesn't suppress typehints
in signature for classes/methods
* #7451: autodoc: fails with AttributeError when an object returns non-string
object as a ``__doc__`` member
* #7423: crashed when giving a non-string object to logger
* #7479: html theme: Do not include xmlns attribute with HTML 5 doctype
* #7426: html theme: Escape some links in HTML templates
Release 3.0.0 (released Apr 06, 2020)
=====================================
Dependencies
------------
3.0.0b1
* LaTeX: drop dependency on :program:`extractbb` for image inclusion in
Japanese documents as ``.xbb`` files are unneeded by :program:`dvipdfmx`
since TeXLive2015 (refs: #6189)
* babel-2.0 or above is available (Unpinned)
Incompatible changes
--------------------
3.0.0b1
* Drop features and APIs deprecated in 1.8.x
* #247: autosummary: stub files are overwritten automatically by default. see
:confval:`autosummary_generate_overwrite` to change the behavior
* #5923: autodoc: the members of ``object`` class are not documented by default
when ``:inherited-members:`` and ``:special-members:`` are given.
* #6830: py domain: ``meta`` fields in info-field-list becomes reserved. They
are not displayed on output document now
* #6417: py domain: doctree of desc_parameterlist has been changed. The
argument names, annotations and default values are wrapped with inline node
* The structure of ``sphinx.events.EventManager.listeners`` has changed
* Due to the scoping changes for :rst:dir:`productionlist` some uses of
:rst:role:`token` must be modified to include the scope which was previously
ignored.
* #6903: Internal data structure of Python, reST and standard domains have
changed. The node_id is added to the index of objects and modules. Now they
contains a pair of docname and node_id for cross reference.
* #7276: C++ domain: Non intended behavior is removed such as ``say_hello_``
links to ``.. cpp:function:: say_hello()``
* #7210: js domain: Non intended behavior is removed such as ``parseInt_`` links
to ``.. js:function:: parseInt``
* #7229: rst domain: Non intended behavior is removed such as ``numref_`` links
to ``.. rst:role:: numref``
* #6903: py domain: Non intended behavior is removed such as ``say_hello_``
links to ``.. py:function:: say_hello()``
* #7246: py domain: Drop special cross reference helper for exceptions,
functions and methods
* The C domain has been rewritten, with additional directives and roles.
The existing ones are now more strict, resulting in new warnings.
* The attribute ``sphinx_cpp_tagname`` in the ``desc_signature_line`` node
has been renamed to ``sphinx_line_type``.
* #6462: double backslashes in domain directives are no longer replaced by
single backslashes as default. A new configuration value
:confval:`strip_signature_backslash` can be used by users to reenable it.
3.0.0 final
* #7222: ``sphinx.util.inspect.unwrap()`` is renamed to ``unwrap_all()``
Deprecated
----------
3.0.0b1
* ``desc_signature['first']``
* ``sphinx.directives.DescDirective``
* ``sphinx.domains.std.StandardDomain.add_object()``
* ``sphinx.domains.python.PyDecoratorMixin``
* ``sphinx.ext.autodoc.get_documenters()``
* ``sphinx.ext.autosummary.process_autosummary_toc()``
* ``sphinx.parsers.Parser.app``
* ``sphinx.testing.path.Path.text()``
* ``sphinx.testing.path.Path.bytes()``
* ``sphinx.util.inspect.getargspec()``
* ``sphinx.writers.latex.LaTeXWriter.format_docclass()``
Features added
--------------
3.0.0b1
* #247: autosummary: Add :confval:`autosummary_generate_overwrite` to overwrite
old stub file
* #5923: autodoc: ``:inherited-members:`` option takes a name of anchestor class
not to document inherited members of the class and uppers
* #6830: autodoc: consider a member private if docstring contains
``:meta private:`` in info-field-list
* #7165: autodoc: Support Annotated type (PEP-593)
* #2815: autodoc: Support singledispatch functions and methods
* #7079: autodoc: :confval:`autodoc_typehints` accepts ``"description"``
configuration. It shows typehints as object description
* #7314: apidoc: Propagate ``--maxdepth`` option through package documents
* #6558: glossary: emit a warning for duplicated glossary entry
* #3106: domain: Register hyperlink target for index page automatically
* #6558: std domain: emit a warning for duplicated generic objects
* #6830: py domain: Add new event: :event:`object-description-transform`
* #6895: py domain: Do not emit nitpicky warnings for built-in types
* py domain: Support lambda functions in function signature
* #6417: py domain: Allow to make a style for arguments of functions and methods
* #7238, #7239: py domain: Emit a warning on describing a python object if the
entry is already added as the same name
* #7341: py domain: type annotations in singature are converted to cross refs
* Support priority of event handlers. For more detail, see
:py:meth:`.Sphinx.connect()`
* #3077: Implement the scoping for :rst:dir:`productionlist` as indicated
in the documentation.
* #1027: Support backslash line continuation in :rst:dir:`productionlist`.
* #7108: config: Allow to show an error message from conf.py via ``ConfigError``
* #7032: html: :confval:`html_scaled_image_link` will be disabled for images having
``no-scaled-link`` class
* #7144: Add CSS class indicating its domain for each desc node
* #7211: latex: Use babel for Chinese document when using XeLaTeX
* #6672: LaTeX: Support LaTeX Theming (experimental)
* #7005: LaTeX: Add LaTeX styling macro for :rst:role:`kbd` role
* #7220: genindex: Show "main" index entries at first
* #7103: linkcheck: writes all links to ``output.json``
* #7025: html search: full text search can be disabled for individual document
using ``:nosearch:`` file-wide metadata
* #7293: html search: Allow to override JavaScript splitter via
``SearchLanguage.js_splitter_code``
* #7142: html theme: Add a theme option: ``pygments_dark_style`` to switch the
style of code-blocks in dark mode
* The C domain has been rewritten adding for example:
- Cross-referencing respecting the current scope.
- Possible to document anonymous entities.
- More specific directives and roles for each type of entitiy,
e.g., handling scoping of enumerators.
- New role :rst:role:`c:expr` for rendering expressions and types
in text.
* Added ``SphinxDirective.get_source_info()``
and ``SphinxRole.get_source_info()``.
* #7324: sphinx-build: Emit a warning if multiple files having different file
extensions for same document found
3.0.0 final
* Added ``ObjectDescription.transform_content()``.
Bugs fixed
----------
3.0.0b1
* C++, fix cross reference lookup in certain cases involving
function overloads.
* #5078: C++, fix cross reference lookup when a directive contains multiple
declarations.
* C++, suppress warnings for directly dependent typenames in cross references
generated automatically in signatures.
* #5637: autodoc: Incorrect handling of nested class names on show-inheritance
* #7267: autodoc: error message for invalid directive options has wrong location
* #7329: autodoc: info-field-list is wrongly generated from type hints into the
class description even if ``autoclass_content='class'`` set
* #7331: autodoc: a cython-function is not recognized as a function
* #5637: inheritance_diagram: Incorrect handling of nested class names
* #7139: ``code-block:: guess`` does not work
* #7325: html: source_suffix containing dot leads to wrong source link
* #7357: html: Resizing SVG image fails with ValueError
* #7278: html search: Fix use of ``html_file_suffix`` instead of
``html_link_suffix`` in search results
* #7297: html theme: ``bizstyle`` does not support ``sidebarwidth``
* #3842: singlehtml: Path to images broken when master doc is not in source root
* #7179: std domain: Fix whitespaces are suppressed on referring GenericObject
* #7289: console: use bright colors instead of bold
* #1539: C, parse array types.
* #2377: C, parse function pointers even in complex types.
* #7345: sphinx-build: Sphinx crashes if output directory exists as a file
* #7290: sphinx-build: Ignore bdb.BdbQuit when handling exceptions
* #6240: napoleon: Attributes and Methods sections ignore :noindex: option
3.0.0 final
* #7364: autosummary: crashed when :confval:`autosummary_generate` is False
* #7370: autosummary: raises UnboundLocalError when unknown module given
* #7367: C++, alternate operator spellings are now supported.
* C, alternate operator spellings are now supported.
* #7368: C++, comma operator in expressions, pack expansion in template
argument lists, and more comprehensive error messages in some cases.
* C, C++, fix crash and wrong duplicate warnings related to anon symbols.
* #6477: Escape first "!" in a cross reference linking no longer possible
* #7219: py domain: The index entry generated by ``py:function`` directive is
different with one from ``index`` directive with "builtin" type
* #7301: capital characters are not allowed for node_id
* #7301: epub: duplicated node_ids are generated
* #6564: html: a width of table was ignored on HTML builder
* #7401: Incorrect argument is passed for :event:`env-get-outdated` handlers
* #7355: autodoc: a signature of cython-function is not recognized well
* #7222: autodoc: ``__wrapped__`` functions are not documented correctly
* #7409: intersphinx: ValueError is raised when an extension sets up
:confval:`intersphinx_mapping` on :event:`config-inited` event
* #7343: Sphinx builds has been slower since 2.4.0 on debug mode
Release 2.4.4 (released Mar 05, 2020)
=====================================
Bugs fixed
----------
* #7197: LaTeX: platex cause error to build image directive with target url
* #7223: Sphinx builds has been slower since 2.4.0
Release 2.4.3 (released Feb 22, 2020)
=====================================
Bugs fixed
----------
* #7184: autodoc: ``*args`` and ``**kwarg`` in type comments are not handled
properly
* #7189: autodoc: classmethod coroutines are not detected
* #7183: intersphinx: ``:attr:`` reference to property is broken
* #6244, #6387: html search: Search breaks/hangs when built with dirhtml builder
* #7195: todo: emit doctree-resolved event with non-document node incorrectly
Release 2.4.2 (released Feb 19, 2020)
=====================================
Bugs fixed
----------
* #7138: autodoc: ``autodoc.typehints`` crashed when variable has unbound object
as a value
* #7156: autodoc: separator for keyword only arguments is not shown
* #7146: autodoc: IndexError is raised on suppressed type_comment found
* #7161: autodoc: typehints extension does not support parallel build
* #7178: autodoc: TypeError is raised on fetching type annotations
* #7151: crashed when extension assigns a value to ``env.indexentries``
* #7170: text: Remove debug print
* #7137: viewcode: Avoid to crash when non-python code given
Release 2.4.1 (released Feb 11, 2020)
=====================================
Bugs fixed
----------
* #7120: html: crashed when on scaling SVG images which have float dimentions
* #7126: autodoc: TypeError: 'getset_descriptor' object is not iterable
Release 2.4.0 (released Feb 09, 2020)
=====================================
Deprecated
----------
* The ``decode`` argument of ``sphinx.pycode.ModuleAnalyzer()``
* ``sphinx.directives.other.Index``
* ``sphinx.environment.temp_data['gloss_entries']``
* ``sphinx.environment.BuildEnvironment.indexentries``
* ``sphinx.environment.collectors.indexentries.IndexEntriesCollector``
* ``sphinx.ext.apidoc.INITPY``
* ``sphinx.ext.apidoc.shall_skip()``
* ``sphinx.io.FiletypeNotFoundError``
* ``sphinx.io.get_filetype()``
* ``sphinx.pycode.ModuleAnalyzer.encoding``
* ``sphinx.roles.Index``
* ``sphinx.util.detect_encoding()``
* ``sphinx.util.get_module_source()``
* ``sphinx.util.inspect.Signature``
* ``sphinx.util.inspect.safe_getmembers()``
* ``sphinx.writers.latex.LaTeXTranslator.settings.author``
* ``sphinx.writers.latex.LaTeXTranslator.settings.contentsname``
* ``sphinx.writers.latex.LaTeXTranslator.settings.docclass``
* ``sphinx.writers.latex.LaTeXTranslator.settings.docname``
* ``sphinx.writers.latex.LaTeXTranslator.settings.title``
* ``sphinx.writers.latex.ADDITIONAL_SETTINGS``
* ``sphinx.writers.latex.DEFAULT_SETTINGS``
* ``sphinx.writers.latex.LUALATEX_DEFAULT_FONTPKG``
* ``sphinx.writers.latex.PDFLATEX_DEFAULT_FONTPKG``
* ``sphinx.writers.latex.XELATEX_DEFAULT_FONTPKG``
* ``sphinx.writers.latex.XELATEX_GREEK_DEFAULT_FONTPKG``
Features added
--------------
* #6910: inheritance_diagram: Make the background of diagrams transparent
* #6446: duration: Add ``sphinx.ext.durations`` to inspect which documents slow
down the build
* #6837: LaTeX: Support a nested table
* #7115: LaTeX: Allow to override LATEXOPTS and LATEXMKOPTS via environment
variable
* #6966: graphviz: Support ``:class:`` option
* #6696: html: ``:scale:`` option of image/figure directive not working for SVG
images (imagesize-1.2.0 or above is required)
* #6994: imgconverter: Support illustrator file (.ai) to .png conversion
* autodoc: Support Positional-Only Argument separator (PEP-570 compliant)
* autodoc: Support type annotations for variables
* #2755: autodoc: Add new event: :event:`autodoc-before-process-signature`
* #2755: autodoc: Support type_comment style (ex. ``# type: (str) -> str``)
annotation (python3.8+ or `typed_ast <https://github.com/python/typed_ast>`_
is required)
* #7051: autodoc: Support instance variables without defaults (PEP-526)
* #6418: autodoc: Add a new extension ``sphinx.ext.autodoc.typehints``. It shows
typehints as object description if ``autodoc_typehints = "description"`` set.
This is an experimental extension and it will be integrated into autodoc core
in Sphinx-3.0
* SphinxTranslator now calls visitor/departure method for super node class if
visitor/departure method for original node class not found
* #6418: Add new event: :event:`object-description-transform`
* py domain: :rst:dir:`py:data` and :rst:dir:`py:attribute` take new options
named ``:type:`` and ``:value:`` to describe its type and initial value
* #6785: py domain: ``:py:attr:`` is able to refer properties again
* #6772: apidoc: Add ``-q`` option for quiet mode
Bugs fixed
----------
* #6925: html: Remove redundant type="text/javascript" from <script> elements
* #7112: html: SVG image is not layouted as float even if aligned
* #6906, #6907: autodoc: failed to read the source codes encoeded in cp1251
* #6961: latex: warning for babel shown twice
* #7059: latex: LaTeX compilation falls into infinite loop (wrapfig issue)
* #6581: latex: ``:reversed:`` option for toctree does not effect to LaTeX build
* #6559: Wrong node-ids are generated in glossary directive
* #6986: apidoc: misdetects module name for .so file inside module
* #6899: apidoc: private members are not shown even if ``--private`` given
* #6327: apidoc: Support a python package consisted of __init__.so file
* #6999: napoleon: fails to parse tilde in :exc: role
* #7019: gettext: Absolute path used in message catalogs
* #7023: autodoc: nested partial functions are not listed
* #7023: autodoc: partial functions imported from other modules are listed as
module members without :impoprted-members: option
* #6889: autodoc: Trailing comma in ``:members::`` option causes cryptic warning
* #6568: autosummary: ``autosummary_imported_members`` is ignored on generating
a stub file for submodule
* #7055: linkcheck: redirect is treated as an error
* #7088: HTML template: If ``navigation_with_keys`` option is activated,
modifier keys are ignored, which means the feature can interfere with browser
features
* #7090: std domain: Can't assign numfig-numbers for custom container nodes
* #7106: std domain: enumerated nodes are marked as duplicated when extensions
call ``note_explicit_target()``
* #7095: dirhtml: Cross references are broken via intersphinx and ``:doc:`` role
* C++:
- Don't crash when using the ``struct`` role in some cases.
- Don't warn when using the ``var``/``member`` role for function
parameters.
- Render call and braced-init expressions correctly.
* #7097: Filenames of images generated by
``sphinx.transforms.post_transforms.images.ImageConverter``
or its subclasses (used for latex build) are now sanitized,
to prevent broken paths
Release 2.3.1 (released Dec 22, 2019)
=====================================
Bugs fixed
----------
* #6936: sphinx-autogen: raises AttributeError
Release 2.3.0 (released Dec 15, 2019)
=====================================
Incompatible changes
--------------------
* #6742: ``end-before`` option of :rst:dir:`literalinclude` directive does not
match the first line of the code block.
* #1331: Change default User-Agent header to ``"Sphinx/X.Y.Z requests/X.Y.Z
python/X.Y.Z"``. It can be changed via :confval:`user_agent`.
* #6867: text: content of admonitions starts after a blank line
Deprecated
----------
* ``sphinx.builders.gettext.POHEADER``
* ``sphinx.io.SphinxStandaloneReader.app``
* ``sphinx.io.SphinxStandaloneReader.env``
* ``sphinx.util.texescape.tex_escape_map``
* ``sphinx.util.texescape.tex_hl_escape_map_new``
* ``sphinx.writers.latex.LaTeXTranslator.no_contractions``
Features added
--------------
* #6707: C++, support bit-fields.
* #267: html: Eliminate prompt characters of doctest block from copyable text
* #6548: html: Use favicon for OpenSearch if available
* #6729: html theme: agogo theme now supports ``rightsidebar`` option
* #6780: Add PEP-561 Support
* #6762: latex: Allow to load additonal LaTeX packages via ``extrapackages`` key
of :confval:`latex_elements`
* #1331: Add new config variable: :confval:`user_agent`
* #6000: LaTeX: have backslash also be an inline literal word wrap break
character
* #4186: LaTeX: Support upLaTeX as a new :confval:`latex_engine` (experimental)
* #6812: Improve a warning message when extensions are not parallel safe
* #6818: Improve Intersphinx performance for multiple remote inventories.
* #2546: apidoc: .so file support
* #6798: autosummary: emit ``autodoc-skip-member`` event on generating stub file
* #6483: i18n: make explicit titles in toctree translatable
* #6816: linkcheck: Add :confval:`linkcheck_auth` option to provide
authentication information when doing ``linkcheck`` builds
* #6872: linkcheck: Handles HTTP 308 Permanent Redirect
* #6613: html: Wrap section number in span tag
* #6781: gettext: Add :confval:`gettext_last_translator' and
:confval:`gettext_language_team` to customize headers of POT file
Bugs fixed
----------
* #6668: LaTeX: Longtable before header has incorrect distance
(refs: `latex3/latex2e#173`_)
.. _latex3/latex2e#173: https://github.com/latex3/latex2e/issues/173
* #6618: LaTeX: Avoid section names at the end of a page
* #6738: LaTeX: Do not replace unicode characters by LaTeX macros on unicode
supported LaTeX engines: ¶, §, €, ∞, ±, →, ‣, , superscript and subscript
digits go through "as is" (as default OpenType font supports them)
* #6704: linkcheck: Be defensive and handle newly defined HTTP error code
* #6806: linkcheck: Failure on parsing content
* #6655: image URLs containing ``data:`` causes gettext builder crashed
* #6584: i18n: Error when compiling message catalogs on Hindi
* #6718: i18n: KeyError is raised if section title and table title are same
* #6743: i18n: :confval:`rst_prolog` breaks the translation
* #6708: mathbase: Some deprecated functions have removed
* #6709: autodoc: mock object does not work as a class decorator
* #5070: epub: Wrong internal href fragment links
* #6712: Allow not to install sphinx.testing as runtime (mainly for ALT Linux)
* #6741: html: search result was broken with empty :confval:`html_file_suffix`
* #6001: LaTeX does not wrap long code lines at backslash character
* #6804: LaTeX: PDF build breaks if admonition of danger type contains
code-block long enough not to fit on one page
* #6809: LaTeX: code-block in a danger type admonition can easily spill over
bottom of page
* #6793: texinfo: Code examples broken following "sidebar"
* #6813: An orphan warning is emitted for included document on Windows. Thanks
to @drillan
* #6850: Fix smartypants module calls re.sub() with wrong options
* #6824: HTML search: If a search term is partially matched in the title and
fully matched in a text paragraph on the same page, the search does not
include this match.
* #6848: config.py shouldn't pop extensions from overrides
* #6867: text: extra spaces are inserted to hyphenated words on folding lines
* #6886: LaTeX: xelatex converts straight double quotes into right curly ones
(shows when :confval:`smartquotes` is ``False``)
* #6890: LaTeX: even with smartquotes off, PDF output transforms straight
quotes and consecutive hyphens into curly quotes and dashes
* #6876: LaTeX: multi-line display of authors on title page has ragged edges
* #6887: Sphinx crashes with docutils-0.16b0
* #6920: sphinx-build: A console message is wrongly highlighted
* #6900: sphinx-build: ``-D`` option does not considers ``0`` and ``1`` as a
boolean value
Release 2.2.2 (released Dec 03, 2019)
=====================================
Incompatible changes
--------------------
* #6803: For security reason of python, parallel mode is disabled on macOS and
Python3.8+
Bugs fixed
----------
* #6776: LaTeX: 2019-10-01 LaTeX release breaks :file:`sphinxcyrillic.sty`
* #6815: i18n: French, Hindi, Chinese, Japanese and Korean translation messages
has been broken
* #6803: parallel build causes AttributeError on macOS and Python3.8
Release 2.2.1 (released Oct 26, 2019)
=====================================
Bugs fixed
----------
* #6641: LaTeX: Undefined control sequence ``\sphinxmaketitle``
* #6710: LaTeX not well configured for Greek language as main language
* #6759: validation of html static paths and extra paths no longer throws
an error if the paths are in different directories
Release 2.2.0 (released Aug 19, 2019)
=====================================
Incompatible changes
--------------------
* apidoc: template files are renamed to ``.rst_t``
* html: Field lists will be styled by grid layout
Deprecated
----------
@ -60,7 +616,12 @@ Features added
* #6514: html: Add a label to search input for accessability purposes
* #5602: apidoc: Add ``--templatedir`` option
* #6475: Add ``override`` argument to ``app.add_autodocumenter()``
* #6310: imgmath: let :confval:`imgmath_use_preview` work also with the SVG
format for images rendering inline math
* #6533: LaTeX: refactor visit_enumerated_list() to use ``\sphinxsetlistlabels``
* #6628: quickstart: Use ``https://docs.python.org/3/`` for default setting of
:confval:`intersphinx_mapping`
* #6419: sphinx-build: give reasons why rebuilded
Bugs fixed
----------
@ -72,6 +633,13 @@ Bugs fixed
* #5502: linkcheck: Consider HTTP 503 response as not an error
* #6439: Make generated download links reproducible
* #6486: UnboundLocalError is raised if broken extension installed
* #6567: autodoc: :confval:`autodoc_inherit_docstrings` does not effect to
``__init__()`` and ``__new__()``
* #6574: autodoc: :confval:`autodoc_member_order` does not refer order of
imports when ``'bysource'`` order
* #6574: autodoc: missing type annotation for variadic and keyword parameters
* #6589: autodoc: Formatting issues with autodoc_typehints='none'
* #6605: autodoc: crashed when target code contains custom method-like objects
* #6498: autosummary: crashed with wrong autosummary_generate setting
* #6507: autosummary: crashes without no autosummary_generate setting
* #6511: LaTeX: autonumbered list can not be customized in LaTeX
@ -81,30 +649,13 @@ Bugs fixed
* #6527: :confval:`last_updated` wrongly assumes timezone as UTC
* #5592: std domain: :rst:dir:`option` directive registers an index entry for
each comma separated option
Testing
--------
Release 2.1.3 (in development)
==============================
Dependencies
------------
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
Testing
--------
* #6549: sphinx-build: Escaped characters in error messages
* #6545: doctest comments not getting trimmed since Sphinx 1.8.0
* #6561: glossary: Wrong hyperlinks are generated for non alphanumeric terms
* #6620: i18n: classifiers of definition list are not translated with
docutils-0.15
* #6474: ``DocFieldTransformer`` raises AttributeError when given directive is
not a subclass of ObjectDescription
Release 2.1.2 (released Jun 19, 2019)
=====================================
@ -212,8 +763,6 @@ Features added
* #6180: Support ``--keep-going`` with BuildDoc setup command
* ``math`` directive now supports ``:class:`` option
* #6310: imgmath: let :confval:`imgmath_use_preview` work also with the SVG
format for images rendering inline math
* todo: ``todo`` directive now supports ``:name:`` option
* Enable override via environment of ``SPHINXOPTS`` and ``SPHINXBUILD`` Makefile
variables (refs: #6232, #6303)
@ -968,6 +1517,8 @@ Features added
* #5029: autosummary: expose ``inherited_members`` to template
* #3784: mathjax: Add :confval:`mathjax_options` to give options to script tag
for mathjax
* #726, #969: mathjax: Add :confval:`mathjax_config` to give in-line
configurations for mathjax
* #4362: latex: Don't overwrite .tex file if document not changed
* #1431: latex: Add alphanumeric enumerated list support
* Add :confval:`latex_use_xindy` for UTF-8 savvy indexing, defaults to ``True``
@ -1787,7 +2338,7 @@ Features removed
* ``termsep`` node
* defindex.html template
* LDML format support in `today`, `today_fmt` and `html_last_updated_fmt`
* LDML format support in ``today``, ``today_fmt`` and ``html_last_updated_fmt``
* ``:inline:`` option for the directives of sphinx.ext.graphviz extension
* sphinx.ext.pngmath extension
* ``sphinx.util.compat.make_admonition()``
@ -4591,7 +5142,7 @@ Features added
- Added a "nitpicky" mode that emits warnings for all missing
references. It is activated by the :option:`sphinx-build -n` command-line
switch or the `nitpicky` config value.
switch or the :confval:`nitpicky` config value.
- Added ``latexpdf`` target in quickstart Makefile.
* Markup:

76
CODE_OF_CONDUCT Normal file
View File

@ -0,0 +1,76 @@
Like the technical community as a whole, the Sphinx team and community is made
up of volunteers from all over the world.
Diversity is a strength, but it can also lead to communication issues and
unhappiness. To that end, we have a few ground rules that we ask people to
adhere to.
* **Be friendly and patient.**
* **Be welcoming.**
We strive to be a community that welcomes and supports people of all
backgrounds and identities. This includes, but is not limited to members of
any race, ethnicity, culture, national origin, colour, immigration status,
social and economic class, educational level, sex, sexual orientation, gender
identity and expression, age, size, family status, political belief, religion,
and mental and physical ability.
* **Be considerate.**
Your work will be used by other people, and you in turn will depend on the
work of others. Any decision you take will affect users and colleagues, and
you should take those consequences into account when making decisions.
Remember that we're a world-wide community, so you might not be communicating
in someone else's primary language.
* **Be respectful.**
Not all of us will agree all the time, but disagreement is no excuse for poor
behavior and poor manners. We might all experience some frustration now and
then, but we cannot allow that frustration to turn into a personal attack.
Its important to remember that a community where people feel uncomfortable or
threatened is not a productive one. Members of the Sphinx community should be
respectful when dealing with other members as well as with people outside the
Sphinx community.
* **Be careful in the words that you choose.**
We are a community of professionals, and we conduct ourselves professionally.
Be kind to others. Do not insult or put down other participants. Harassment
and other exclusionary behavior aren't acceptable. This includes, but is not
limited to:
* Violent threats or language directed against another person.
* Discriminatory jokes and language.
* Posting sexually explicit or violent material.
* Posting (or threatening to post) other people's personally identifying
information ("doxing").
* Personal insults, especially those using racist or sexist terms.
* Unwelcome sexual attention.
* Advocating for, or encouraging, any of the above behavior.
* Repeated harassment of others. In general, if someone asks you to stop, then
stop.
* **When we disagree, try to understand why.**
Disagreements, both social and technical, happen all the time and Sphinx is no
exception. It is important that we resolve disagreements and differing views
constructively. Remember that were different. Different people have different
perspectives on issues. Being unable to understand why someone holds a
viewpoint doesnt mean that theyre wrong. Dont forget that it is human to
err and blaming each other doesnt get us anywhere. Instead, focus on helping
to resolve issues and learning from mistakes.
This isnt an exhaustive list of things that you cant do.
Rather, take it in the spirit in which its intended - a guide to make it easier
to enrich all of us and the technical communities in which we participate.
This code of conduct applies to all spaces of the Sphinx community.
Attribution
-----------
Original text courtesy of the Speak Up! project:
http://web.archive.org/web/20141109123859/http://speakup.io/coc.html.

View File

@ -61,7 +61,7 @@ of the core developers before it is merged into the main repository.
#. If you feel uncomfortable or uncertain about an issue or your changes, feel
free to email the *sphinx-dev* mailing list.
#. Fork `the repository`_ on GitHub to start making your changes to the
``master`` branch for next MAJOR version, or ``X.Y`` branch for next
``master`` branch for next MAJOR version, or ``A.x`` branch for next
MINOR version (see `Branch Model`_).
#. Write a test which shows that the bug was fixed or that the feature works
as expected.
@ -94,10 +94,10 @@ These are the basic steps needed to start developing on Sphinx.
Sphinx adopts Semantic Versioning 2.0.0 (refs: https://semver.org/ ).
For changes that preserves backwards-compatibility of API and features,
they should be included in the next MINOR release, use the ``X.Y`` branch.
they should be included in the next MINOR release, use the ``A.x`` branch.
::
git checkout X.Y
git checkout A.x
For incompatible or other substantial changes that should wait until the
next MAJOR release, use the ``master`` branch.
@ -199,11 +199,19 @@ These are the basic steps needed to start developing on Sphinx.
git push origin feature-xyz
#. Submit a pull request from your branch to the respective branch (``master``
or ``X.Y``).
or ``A.x``).
#. Wait for a core developer to review your changes.
Translations
~~~~~~~~~~~~
The Sphinx core messages and documentations are translated on `Transifex
<https://www.transifex.com/>`_. Please join `Sphinx project on Transifex
<https://www.transifex.com/sphinx-doc/>`_ and translate them.
Core Developers
~~~~~~~~~~~~~~~
@ -228,39 +236,6 @@ The following are some general guidelines for core developers:
author in the commit message and any relevant :file:`CHANGES` entry.
Locale updates
~~~~~~~~~~~~~~
The parts of messages in Sphinx that go into builds are translated into several
locales. The translations are kept as gettext ``.po`` files translated from the
master template ``sphinx/locale/sphinx.pot``.
Sphinx uses `Babel <http://babel.pocoo.org/en/latest/>`_ to extract messages
and maintain the catalog files. It is integrated in ``setup.py``:
* Use ``python setup.py extract_messages`` to update the ``.pot`` template.
* Use ``python setup.py update_catalog`` to update all existing language
catalogs in ``sphinx/locale/*/LC_MESSAGES`` with the current messages in the
template file.
* Use ``python setup.py compile_catalog`` to compile the ``.po`` files to binary
``.mo`` files and ``.js`` files.
When an updated ``.po`` file is submitted, run compile_catalog to commit both
the source and the compiled catalogs.
When a new locale is submitted, add a new directory with the ISO 639-1 language
identifier and put ``sphinx.po`` in there. Don't forget to update the possible
values for :confval:`language` in ``doc/usage/configuration.rst``.
The Sphinx core messages can also be translated on `Transifex
<https://www.transifex.com/>`_. There exists a client tool named ``tx`` in the
Python package "transifex_client", which can be used to pull translations in
``.po`` format from Transifex. To do this, go to ``sphinx/locale`` and then run
``tx pull -f -l LANG`` where LANG is an existing language identifier. It is
good practice to run ``python setup.py update_catalog`` afterwards to make sure
the ``.po`` file has the canonical Babel formatting.
Coding Guide
------------
@ -325,8 +300,8 @@ Versioning 2.0.0 (refs: https://semver.org/ ).
All changes including incompatible behaviors and public API updates are
allowed.
``X.Y``
Where ``X.Y`` is the ``MAJOR.MINOR`` release. Used to maintain current
``A.x`` (ex. ``2.x``)
Where ``A.x`` is the ``MAJOR.MINOR`` release. Used to maintain current
MINOR release. All changes are allowed if the change preserves
backwards-compatibility of API and features.
@ -334,8 +309,8 @@ Versioning 2.0.0 (refs: https://semver.org/ ).
new MAJOR version is released, the old ``MAJOR.MINOR`` branch will be
deleted and replaced by an equivalent tag.
``X.Y.Z``
Where ``X.Y.Z`` is the ``MAJOR.MINOR.PATCH`` release. Only
``A.B.x`` (ex. ``2.4.x``)
Where ``A.B.x`` is the ``MAJOR.MINOR.PATCH`` release. Only
backwards-compatible bug fixes are allowed. In Sphinx project, PATCH
version is used for urgent bug fix.
@ -387,18 +362,31 @@ Sphinx 2.x:
* Sphinx 2.x will contain a backwards-compatible replica of the function
which will raise a ``RemovedInSphinx40Warning``.
This is a subclass of :exc:`python:PendingDeprecationWarning`, i.e. it
will not get displayed by default.
* Sphinx 3.x will still contain the backwards-compatible replica.
* Sphinx 3.x will still contain the backwards-compatible replica, but
``RemovedInSphinx40Warning`` will be a subclass of
:exc:`python:DeprecationWarning` then, and gets displayed by default.
* Sphinx 4.0 will remove the feature outright.
The warnings are displayed by default. You can turn off display of these
warnings with:
Deprecation warnings
~~~~~~~~~~~~~~~~~~~~
Sphinx will enable its ``RemovedInNextVersionWarning`` warnings by default,
if :envvar:`python:PYTHONWARNINGS` is not set.
Therefore you can disable them using:
* ``PYTHONWARNINGS= make html`` (Linux/Mac)
* ``export PYTHONWARNINGS=`` and do ``make html`` (Linux/Mac)
* ``set PYTHONWARNINGS=`` and do ``make html`` (Windows)
But you can also explicitly enable the pending ones using e.g.
``PYTHONWARNINGS=default`` (see the
:ref:`Python docs on configuring warnings <python:describing-warning-filters>`)
for more details.
Unit Testing
------------
@ -426,3 +414,42 @@ and other ``test_*.py`` files under ``tests`` directory.
.. versionadded:: 1.8
Sphinx also runs JavaScript tests.
Release procedures
------------------
The release procedures are listed on ``utils/release-checklist``.
Locale Updates
~~~~~~~~~~~~~~
The parts of messages in Sphinx that go into builds are translated into several
locales. The translations are kept as gettext ``.po`` files translated from the
master template :file:`sphinx/locale/sphinx.pot`.
Sphinx uses `Babel <http://babel.pocoo.org/en/latest/>`_ to extract messages
and maintain the catalog files. It is integrated in ``setup.py``:
* Use ``python setup.py extract_messages`` to update the ``.pot`` template.
* Use ``python setup.py update_catalog`` to update all existing language
catalogs in ``sphinx/locale/*/LC_MESSAGES`` with the current messages in the
template file.
* Use ``python setup.py compile_catalog`` to compile the ``.po`` files to binary
``.mo`` files and ``.js`` files.
When an updated ``.po`` file is submitted, run compile_catalog to commit both
the source and the compiled catalogs.
When a new locale is submitted, add a new directory with the ISO 639-1 language
identifier and put ``sphinx.po`` in there. Don't forget to update the possible
values for :confval:`language` in ``doc/usage/configuration.rst``.
The Sphinx core messages can also be translated on `Transifex
<https://www.transifex.com/>`_. There exists a client tool named ``tx`` in the
Python package "transifex_client", which can be used to pull translations in
``.po`` format from Transifex. To do this, go to ``sphinx/locale`` and then run
``tx pull -f -l LANG`` where LANG is an existing language identifier. It is
good practice to run ``python setup.py update_catalog`` afterwards to make sure
the ``.po`` file has the canonical Babel formatting.

View File

@ -183,6 +183,7 @@ Documentation using sphinx_rtd_theme
* `Databricks <https://docs.databricks.com/>`__ (customized)
* `Dataiku DSS <https://doc.dataiku.com/>`__
* `DNF <https://dnf.readthedocs.io/>`__
* `Django-cas-ng <https://djangocas.dev/docs/>`__
* `edX <https://docs.edx.org/>`__
* `Electrum <http://docs.electrum.org/>`__
* `Elemental <http://libelemental.org/documentation/dev/>`__
@ -212,6 +213,7 @@ Documentation using sphinx_rtd_theme
* `Lasagne <https://lasagne.readthedocs.io/>`__
* `latexindent.pl <https://latexindentpl.readthedocs.io/>`__
* `Learning Apache Spark with Python <https://runawayhorse001.github.io/LearningApacheSpark>`__
* `LibCEED <https://libceed.readthedocs.io/>`__
* `Linguistica <https://linguistica-uchicago.github.io/lxa5/>`__
* `Linux kernel <https://www.kernel.org/doc/html/latest/index.html>`__
* `Mailman <http://docs.list.org/>`__
@ -242,6 +244,7 @@ Documentation using sphinx_rtd_theme
* `PyPy <http://doc.pypy.org/>`__
* `python-sqlparse <https://sqlparse.readthedocs.io/>`__
* `PyVISA <https://pyvisa.readthedocs.io/>`__
* `pyvista <https://docs.pyvista.org/>`__
* `Read The Docs <https://docs.readthedocs.io/>`__
* `Free your information from their silos (French) <http://redaction-technique.org/>`__ (customized)
* `Releases Sphinx extension <https://releases.readthedocs.io/>`__
@ -404,6 +407,7 @@ Books produced using Sphinx
* `"Python Professional Programming" (in Japanese) <http://www.amazon.co.jp/dp/4798032948/>`__
* `"Python Professional Programming 2nd Edition" (in Japanese) <https://www.amazon.co.jp/dp/479804315X/>`__
* `"Python Professional Programming 3rd Edition" (in Japanese) <https://www.amazon.co.jp/dp/4798053821/>`__
* `Python Course by Yuri Petrov (Russian) <https://www.yuripetrov.ru/edu/python>`__
* `"Real World HTTP -- Learning The Internet and Web Technology via its history and code (Japanese)" <https://www.oreilly.co.jp/books/9784873118048/>`__
* `"Redmine Primer 5th Edition (in Japanese)" <https://www.shuwasystem.co.jp/products/7980html/4825.html>`__
* `"The repoze.bfg Web Application Framework" <https://www.amazon.com/repoze-bfg-Web-Application-Framework-Version/dp/0615345379>`__

View File

@ -31,6 +31,7 @@ clean-backupfiles:
clean-generated:
find . -name '.DS_Store' -exec rm -f {} +
rm -rf Sphinx.egg-info/
rm -rf dist/
rm -rf doc/_build/
rm -f sphinx/pycode/*.pickle
rm -f utils/*3.py*
@ -49,7 +50,7 @@ clean-buildfiles:
.PHONY: clean-mypyfiles
clean-mypyfiles:
rm -rf .mypy_cache/
find . -name '.mypy_cache' -exec rm -rf {} +
.PHONY: style-check
style-check:

View File

@ -26,6 +26,10 @@
:target: https://codecov.io/gh/sphinx-doc/sphinx
:alt: Code Coverage Status (Codecov)
.. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
:target: https://opensource.org/licenses/BSD-3-Clause
:alt: BSD 3 Clause
Sphinx is a tool that makes it easy to create intelligent and beautiful
documentation for Python projects (or other documents consisting of multiple
reStructuredText sources), written by Georg Brandl. It was originally created
@ -90,6 +94,10 @@ Get in touch
.. _on GitHub: https://github.com/sphinx-doc/sphinx
.. _mailing list: https://groups.google.com/forum/#!forum/sphinx-users
Please adhere to our `code of conduct`__.
__ http://www.sphinx-doc.org/en/master/code_of_conduct.html
Testing
=======

View File

@ -5,7 +5,6 @@ PYTHON ?= python3
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = $(PYTHON) ../sphinx/cmd/build.py
SPHINXPROJ = sphinx
SOURCEDIR = .
BUILDDIR = _build

4
doc/_static/Makefile vendored Normal file
View File

@ -0,0 +1,4 @@
translation.svg: translation.puml
plantuml -tsvg $<
clean:
rm translation.svg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

16
doc/_static/translation.puml vendored Normal file
View File

@ -0,0 +1,16 @@
@startuml
file "SphinxProject"
file ".rst"
database ".pot"
database ".po"
database ".mo"
actor translator
file TranslatedBuild
translator -l-> .po
SphinxProject -r-> .rst
.rst -r-> .pot : sphinx-build gettext
.pot -r-> .po : Pootle
.po -d-> .mo : msgfmt
.mo -l-> TranslatedBuild
.rst -d-> TranslatedBuild : "sphinx-buid -Dlanguage="
@enduml

29
doc/_static/translation.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -92,8 +92,8 @@
create a customized documentation using Sphinx written by the matplotlib
developers.{%endtrans%}</p>
<p>{%trans%}There is a <a href="http://docs.sphinx-users.jp/">Japanese translation</a>
of this documentation, thanks to the Japanese Sphinx user group.{%endtrans%}</p>
<p>{%trans%}There is a translation team in <a href="https://www.transifex.com/sphinx-doc/sphinx-doc/dashboard/">Transifex</a>
of this documentation, thanks to the Sphinx document translators.{%endtrans%}</p>
<p>{%trans%}A Japanese book about Sphinx has been published by O'Reilly:
<a href="https://www.oreilly.co.jp/books/9784873116488/">Sphinxをはじめよう /
Learning Sphinx</a>.{%endtrans%}</p>
@ -120,4 +120,8 @@
<li>{%trans path=pathto("authors")%}<a href="{{ path }}">Sphinx Authors</a></li>{%endtrans%}
</ul>
<h2>{%trans%}Code of Conduct{%endtrans%}</h2>
{%trans path=pathto("code_of_conduct")%}Please adhere to our <a href="{{ path }}">Code of Conduct</a>.{%endtrans%}
{% endblock %}

View File

@ -13,11 +13,6 @@
{% block sidebar1 %}{{ sidebar() }}{% endblock %}
{% block sidebar2 %}{% endblock %}
{% block linktags %}
{{ super() }}
<link rel="canonical" href="http://www.sphinx-doc.org/en/master/{{ pagename }}{{ file_suffix }}" />
{% endblock %}
{% block extrahead %}
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,700'
rel='stylesheet' type='text/css' />
@ -30,7 +25,7 @@
.related { display: none; }
{% endif %}
</style>
<script type="text/javascript">
<script>
// intelligent scrolling of the sidebar content
$(window).scroll(function() {
var sb = $('.sphinxsidebarwrapper');

View File

@ -299,6 +299,11 @@ a.headerlink:hover {
color: white!important;
}
/* avoid font-size when :mod: role in headings */
h1 code, h2 code, h3 code, h4 code {
font-size: inherit;
}
cite, code, tt {
font-family: 'Consolas', 'DejaVu Sans Mono',
'Bitstream Vera Sans Mono', monospace;

View File

@ -1,4 +1,4 @@
:tocdepth: 2
:tocdepth: 1
.. default-role:: any

8
doc/code_of_conduct.rst Normal file
View File

@ -0,0 +1,8 @@
:tocdepth: 2
.. _code_of_conduct:
Sphinx Code of Conduct
======================
.. include:: ../CODE_OF_CONDUCT

View File

@ -7,6 +7,7 @@ import sphinx
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
'sphinx.ext.autosummary', 'sphinx.ext.extlinks',
'sphinx.ext.intersphinx',
'sphinx.ext.viewcode', 'sphinx.ext.inheritance_diagram']
master_doc = 'contents'
@ -14,7 +15,7 @@ templates_path = ['_templates']
exclude_patterns = ['_build']
project = 'Sphinx'
copyright = '2007-2019, Georg Brandl and the Sphinx team'
copyright = '2007-2020, Georg Brandl and the Sphinx team'
version = sphinx.__display_version__
release = version
show_authors = True
@ -25,7 +26,8 @@ modindex_common_prefix = ['sphinx.']
html_static_path = ['_static']
html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']}
html_additional_pages = {'index': 'index.html'}
html_use_opensearch = 'http://sphinx-doc.org'
html_use_opensearch = 'https://www.sphinx-doc.org/en/master'
html_baseurl = 'https://www.sphinx-doc.org/en/master/'
htmlhelp_basename = 'Sphinxdoc'
@ -146,6 +148,9 @@ def setup(app):
app.add_object_type('confval', 'confval',
objname='configuration value',
indextemplate='pair: %s; configuration value')
app.add_object_type('setuptools-confval', 'setuptools-confval',
objname='setuptools configuration value',
indextemplate='pair: %s; setuptools configuration value')
fdesc = GroupedField('parameter', label='Parameters',
names=['param'], can_collapse=True)
app.add_object_type('event', 'event', 'pair: %s; event', parse_event,

View File

@ -34,6 +34,7 @@ Sphinx documentation contents
changes
examples
authors
code_of_conduct

View File

@ -36,6 +36,7 @@ This is the current list of contributed extensions in that repository:
- astah: embed diagram by using astah
- autoanysrc: Gather reST documentation from any source files
- autorun: Execute code in a ``runblock`` directive
- beamer_: A builder for Beamer (LaTeX) output.
- blockdiag: embed block diagrams by using blockdiag_
- cacoo: embed diagram from Cacoo
- cf3domain: a domain for CFEngine 3 policies
@ -148,3 +149,4 @@ started with writing your own extensions.
.. _domaintools: https://bitbucket.org/klorenz/sphinxcontrib-domaintools
.. _restbuilder: https://pypi.org/project/sphinxcontrib-restbuilder/
.. _Lasso: http://www.lassosoft.com/
.. _beamer: https://pypi.org/project/sphinxcontrib-beamer/

View File

@ -70,6 +70,9 @@ def process_todo_nodes(app, doctree, fromdocname):
# Augment each todo with a backlink to the original location.
env = app.builder.env
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
for node in doctree.traverse(todolist):
if not app.config.todo_include_todos:
node.replace_self([])

View File

@ -75,7 +75,7 @@ The first thing to examine is the ``RecipeDirective`` directive:
.. literalinclude:: examples/recipe.py
:language: python
:linenos:
:lines: 17-37
:pyobject: RecipeDirective
Unlike :doc:`helloworld` and :doc:`todo`, this directive doesn't derive from
:class:`docutils.parsers.rst.Directive` and doesn't define a ``run`` method.
@ -103,7 +103,12 @@ reStructuredText in the body.
.. literalinclude:: examples/recipe.py
:language: python
:linenos:
:lines: 40-102
:pyobject: IngredientIndex
.. literalinclude:: examples/recipe.py
:language: python
:linenos:
:pyobject: RecipeIndex
Both ``IngredientIndex`` and ``RecipeIndex`` are derived from :class:`Index`.
They implement custom logic to generate a tuple of values that define the
@ -117,6 +122,10 @@ all it really is is a list of tuples like ``('tomato', 'TomatoSoup', 'test',
'rec-TomatoSoup',...)``. Refer to the :doc:`domain API guide
</extdev/domainapi>` for more information on this API.
These index pages can be referred by combination of domain name and its
``name`` using :rst:role:`ref` role. For example, ``RecipeIndex`` can be
referred by ``:ref:`recipe-recipe```.
.. rubric:: The domain
A Sphinx domain is a specialized container that ties together roles,
@ -126,7 +135,7 @@ creating here.
.. literalinclude:: examples/recipe.py
:language: python
:linenos:
:lines: 105-155
:pyobject: RecipeDomain
There are some interesting things to note about this ``recipe`` domain and domains
in general. Firstly, we actually register our directives, roles and indices
@ -164,7 +173,7 @@ hook the various parts of our extension into Sphinx. Let's look at the
.. literalinclude:: examples/recipe.py
:language: python
:linenos:
:lines: 158-
:pyobject: setup
This looks a little different to what we're used to seeing. There are no calls
to :meth:`~Sphinx.add_directive` or even :meth:`~Sphinx.add_role`. Instead, we

View File

@ -107,6 +107,20 @@ is just a "general" node.
<http://docutils.sourceforge.net/docs/ref/doctree.html>`__ and :ref:`Sphinx
<nodes>`.
.. attention::
It is important to know that while you can extend Sphinx without
leaving your ``conf.py``, if you declare an inherited node right
there, you'll hit an unobvious :py:class:`PickleError`. So if
something goes wrong, please make sure that you put inherited nodes
into a separate Python module.
For more details, see:
- https://github.com/sphinx-doc/sphinx/issues/6751
- https://github.com/sphinx-doc/sphinx/issues/1493
- https://github.com/sphinx-doc/sphinx/issues/1424
.. rubric:: The directive classes
A directive class is a class deriving usually from

View File

@ -45,7 +45,6 @@ package.
.. automethod:: Sphinx.add_enumerable_node(node, figtype, title_getter=None, \*\*kwds)
.. method:: Sphinx.add_directive(name, func, content, arguments, \*\*options)
.. automethod:: Sphinx.add_directive(name, directiveclass)
.. automethod:: Sphinx.add_role(name, role)
@ -54,7 +53,6 @@ package.
.. automethod:: Sphinx.add_domain(domain)
.. method:: Sphinx.add_directive_to_domain(domain, name, func, content, arguments, \*\*options)
.. automethod:: Sphinx.add_directive_to_domain(domain, name, directiveclass)
.. automethod:: Sphinx.add_role_to_domain(domain, name, role)
@ -107,6 +105,7 @@ Emitting events
---------------
.. class:: Sphinx
:noindex:
.. automethod:: emit(event, \*arguments)
@ -216,6 +215,14 @@ connect handlers to the events. Example:
.. versionadded:: 0.5
.. event:: object-description-transform (app, domain, objtype, contentnode)
Emitted when an object description directive has run. The *domain* and
*objtype* arguments are strings indicating object description of the object.
And *contentnode* is a content for the object. It can be modified in-place.
.. versionadded:: 2.4
.. event:: doctree-read (app, doctree)
Emitted when a doctree has been parsed and read by the environment, and is
@ -260,11 +267,6 @@ connect handlers to the events. Example:
environment from the main process. *docnames* is a set of document names
that have been read in the subprocess.
For a sample of how to deal with this event, look at the standard
``sphinx.ext.todo`` extension. The implementation is often similar to that
of :event:`env-purge-doc`, only that information is not removed, but added to
the main environment from the other environment.
.. versionadded:: 1.3
.. event:: env-updated (app, env)

View File

@ -26,6 +26,228 @@ The following is a list of deprecated interfaces.
- (will be) Removed
- Alternatives
* - The ``module`` argument of
``sphinx.ext.autosummary.generate.find_autosummary_in_docstring()``
- 3.0
- 5.0
- N/A
* - ``desc_signature['first']``
-
- 3.0
- N/A
* - ``sphinx.directives.DescDirective``
- 3.0
- 5.0
- ``sphinx.directives.ObjectDescription``
* - ``sphinx.domains.std.StandardDomain.add_object()``
- 3.0
- 5.0
- ``sphinx.domains.std.StandardDomain.note_object()``
* - ``sphinx.domains.python.PyDecoratorMixin``
- 3.0
- 5.0
- N/A
* - ``sphinx.ext.autodoc.get_documenters()``
- 3.0
- 5.0
- ``sphinx.registry.documenters``
* - ``sphinx.ext.autosummary.process_autosummary_toc()``
- 3.0
- 5.0
- N/A
* - ``sphinx.parsers.Parser.app``
- 3.0
- 5.0
- N/A
* - ``sphinx.testing.path.Path.text()``
- 3.0
- 5.0
- ``sphinx.testing.path.Path.read_text()``
* - ``sphinx.testing.path.Path.bytes()``
- 3.0
- 5.0
- ``sphinx.testing.path.Path.read_bytes()``
* - ``sphinx.util.inspect.getargspec()``
- 3.0
- 5.0
- ``inspect.getargspec()``
* - ``sphinx.writers.latex.LaTeXWriter.format_docclass()``
- 3.0
- 5.0
- LaTeX Themes
* - ``decode`` argument of ``sphinx.pycode.ModuleAnalyzer()``
- 2.4
- 4.0
- N/A
* - ``sphinx.directives.other.Index``
- 2.4
- 4.0
- ``sphinx.domains.index.IndexDirective``
* - ``sphinx.environment.temp_data['gloss_entries']``
- 2.4
- 4.0
- ``documents.nameids``
* - ``sphinx.environment.BuildEnvironment.indexentries``
- 2.4
- 4.0
- ``sphinx.domains.index.IndexDomain``
* - ``sphinx.environment.collectors.indexentries.IndexEntriesCollector``
- 2.4
- 4.0
- ``sphinx.domains.index.IndexDomain``
* - ``sphinx.io.FiletypeNotFoundError``
- 2.4
- 4.0
- ``sphinx.errors.FiletypeNotFoundError``
* - ``sphinx.ext.apidoc.INITPY``
- 2.4
- 4.0
- N/A
* - ``sphinx.ext.apidoc.shall_skip()``
- 2.4
- 4.0
- ``sphinx.ext.apidoc.is_skipped_package``
* - ``sphinx.io.get_filetype()``
- 2.4
- 4.0
- ``sphinx.util.get_filetype()``
* - ``sphinx.pycode.ModuleAnalyzer.encoding``
- 2.4
- 4.0
- N/A
* - ``sphinx.roles.Index``
- 2.4
- 4.0
- ``sphinx.domains.index.IndexRole``
* - ``sphinx.util.detect_encoding()``
- 2.4
- 4.0
- ``tokenize.detect_encoding()``
* - ``sphinx.util.get_module_source()``
- 2.4
- 4.0
- N/A
* - ``sphinx.util.inspect.Signature``
- 2.4
- 4.0
- ``sphinx.util.inspect.signature`` and
``sphinx.util.inspect.stringify_signature()``
* - ``sphinx.util.inspect.safe_getmembers()``
- 2.4
- 4.0
- ``inspect.getmembers()``
* - ``sphinx.writers.latex.LaTeXTranslator.settings.author``
- 2.4
- 4.0
- N/A
* - ``sphinx.writers.latex.LaTeXTranslator.settings.contentsname``
- 2.4
- 4.0
- ``document['contentsname']``
* - ``sphinx.writers.latex.LaTeXTranslator.settings.docclass``
- 2.4
- 4.0
- ``document['docclass']``
* - ``sphinx.writers.latex.LaTeXTranslator.settings.docname``
- 2.4
- 4.0
- N/A
* - ``sphinx.writers.latex.LaTeXTranslator.settings.title``
- 2.4
- 4.0
- N/A
* - ``sphinx.writers.latex.ADDITIONAL_SETTINGS``
- 2.4
- 4.0
- ``sphinx.builders.latex.constants.ADDITIONAL_SETTINGS``
* - ``sphinx.writers.latex.DEFAULT_SETTINGS``
- 2.4
- 4.0
- ``sphinx.builders.latex.constants.DEFAULT_SETTINGS``
* - ``sphinx.writers.latex.LUALATEX_DEFAULT_FONTPKG``
- 2.4
- 4.0
- ``sphinx.builders.latex.constants.LUALATEX_DEFAULT_FONTPKG``
* - ``sphinx.writers.latex.PDFLATEX_DEFAULT_FONTPKG``
- 2.4
- 4.0
- ``sphinx.builders.latex.constants.PDFLATEX_DEFAULT_FONTPKG``
* - ``sphinx.writers.latex.XELATEX_DEFAULT_FONTPKG``
- 2.4
- 4.0
- ``sphinx.builders.latex.constants.XELATEX_DEFAULT_FONTPKG``
* - ``sphinx.writers.latex.XELATEX_GREEK_DEFAULT_FONTPKG``
- 2.4
- 4.0
- ``sphinx.builders.latex.constants.XELATEX_GREEK_DEFAULT_FONTPKG``
* - ``sphinx.builders.gettext.POHEADER``
- 2.3
- 4.0
- ``sphinx/templates/gettext/message.pot_t`` (template file)
* - ``sphinx.io.SphinxStandaloneReader.app``
- 2.3
- 4.0
- ``sphinx.io.SphinxStandaloneReader.setup()``
* - ``sphinx.io.SphinxStandaloneReader.env``
- 2.3
- 4.0
- ``sphinx.io.SphinxStandaloneReader.setup()``
* - ``sphinx.util.texescape.tex_escape_map``
- 2.3
- 4.0
- ``sphinx.util.texescape.escape()``
* - ``sphinx.util.texescape.tex_hl_escape_map_new``
- 2.3
- 4.0
- ``sphinx.util.texescape.hlescape()``
* - ``sphinx.writers.latex.LaTeXTranslator.no_contractions``
- 2.3
- 4.0
- N/A
* - ``sphinx.domains.math.MathDomain.add_equation()``
- 2.2
- 4.0

View File

@ -35,25 +35,25 @@ In practice, you have to:
:func:`sphinx.locale.get_translation` function, usually renamed ``_()``,
e.g.:
.. code-block:: python
:caption: src/__init__.py
.. code-block:: python
:caption: src/__init__.py
from sphinx.locale import get_translation
from sphinx.locale import get_translation
MESSAGE_CATALOG_NAME = 'myextension'
_ = get_translation(MESSAGE_CATALOG_NAME)
MESSAGE_CATALOG_NAME = 'myextension'
_ = get_translation(MESSAGE_CATALOG_NAME)
translated_text = _('Hello Sphinx!')
translated_text = _('Hello Sphinx!')
#. Set up your extension to be aware of its dedicated translations:
.. code-block:: python
:caption: src/__init__.py
.. code-block:: python
:caption: src/__init__.py
def setup(app):
package_dir = path.abspath(path.dirname(__file__))
locale_dir = os.path.join(package_dir, 'locales')
app.add_message_catalog(MESSAGE_CATALOG_NAME, locale_dir)
def setup(app):
package_dir = path.abspath(path.dirname(__file__))
locale_dir = os.path.join(package_dir, 'locales')
app.add_message_catalog(MESSAGE_CATALOG_NAME, locale_dir)
#. Generate message catalog template ``*.pot`` file, usually in ``locale/``
source directory, for example via `Babel`_:

View File

@ -27,7 +27,7 @@ Discovery of builders by entry point
.. versionadded:: 1.6
:term:`Builder` extensions can be discovered by means of `entry points`_ so
:term:`builder` extensions can be discovered by means of `entry points`_ so
that they do not have to be listed in the :confval:`extensions` configuration
value.

View File

@ -89,7 +89,7 @@ Google Analytics
{%- block extrahead %}
{{ super() }}
<script type="text/javascript">
<script>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'XXX account number XXX']);
_gaq.push(['_trackPageview']);
@ -101,7 +101,7 @@ Google Analytics
<div class="footer">This page uses <a href="https://analytics.google.com/">
Google Analytics</a> to collect statistics. You can disable it by blocking
the JavaScript coming from www.google-analytics.com.
<script type="text/javascript">
<script>
(function() {
var ga = document.createElement('script');
ga.src = ('https:' == document.location.protocol ?
@ -132,7 +132,6 @@ Google Search
(function() {
var cx = '......';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = 'https://cse.google.com/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];

View File

@ -55,9 +55,9 @@ See the :ref:`pertinent section in the FAQ list <usingwith>`.
Prerequisites
-------------
Sphinx needs at least **Python 3.5** to run, as well as the docutils_ and
Jinja2_ libraries. Sphinx should work with docutils version 0.12 or some (not
broken) SVN trunk snapshot.
Sphinx needs at least **Python 3.5** to run.
It also depends on 3rd party libraries such as docutils_ and jinja2_, but they
are automatically installed when sphinx is installed.
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. _docutils: http://docutils.sourceforge.net/

View File

@ -226,6 +226,25 @@ into the generated ``.tex`` files. Its ``'sphinxsetup'`` key is described
.. versionadded:: 1.5
``'extrapackages'``
Additional LaTeX packages. For example:
.. code-block:: python
latex_elements = {
'packages': r'\usepackage{isodate}'
}
It defaults to empty.
The specified LaTeX packages will be loaded before
hyperref package and packages loaded from Sphinx extensions.
.. hint:: If you'd like to load additional LaTeX packages after hyperref, use
``'preamble'`` key instead.
.. versionadded:: 2.3
``'footer'``
Additional footer content (before the indices), default empty.
@ -289,6 +308,11 @@ into the generated ``.tex`` files. Its ``'sphinxsetup'`` key is described
.. attention::
If Greek is main language, do not use this key. Since Sphinx 2.2.1,
``xelatex`` will be used automatically as :confval:`latex_engine`.
Formerly, Sphinx did not support producing PDF via LaTeX with Greek as
main language.
Prior to 2.0, Unicode Greek letters were escaped to use LaTeX math
mark-up. This is not the case anymore, and the above must be used
(only in case of ``'pdflatex'`` engine) if the source contains such
@ -310,12 +334,19 @@ into the generated ``.tex`` files. Its ``'sphinxsetup'`` key is described
.. versionchanged:: 2.0
``'lualatex'`` executes
``\defaultfontfeatures[\rmfamily,\sffamily]{}`` to disable TeX
ligatures.
ligatures transforming `<<` and `>>` as escaping working with
``pdflatex/xelatex`` failed with ``lualatex``.
.. versionchanged:: 2.0
Detection of ``LGR``, ``T2A``, ``X2`` to trigger support of
occasional Greek or Cyrillic (``'pdflatex'`` only, as this support
is provided natively by ``'platex'`` and only requires suitable
font with ``'xelatex'/'lualatex'``).
.. versionchanged:: 2.3.0
``'xelatex'`` also executes
``\defaultfontfeatures[\rmfamily,\sffamily]{}`` in order to avoid
contractions of ``--`` into en-dash or transforms of straight quotes
into curly ones in PDF (in non-literal text paragraphs) despite
:confval:`smartquotes` being set to ``False``.
``'textgreek'``
The default (``'pdflatex'`` only) is
@ -595,12 +626,15 @@ macros may be significant.
default ``true``. Allows linebreaks inside inline literals: but extra
potential break-points (additionally to those allowed by LaTeX at spaces
or for hyphenation) are currently inserted only after the characters
``. , ; ? ! /``. Due to TeX internals, white space in the line will be
stretched (or shrunk) in order to accomodate the linebreak.
``. , ; ? ! /`` and ``\``. Due to TeX internals, white space in the line
will be stretched (or shrunk) in order to accomodate the linebreak.
.. versionadded:: 1.5
set this option value to ``false`` to recover former behaviour.
.. versionchanged:: 2.3.0
added potential breakpoint at ``\`` characters.
``verbatimvisiblespace``
default ``\textcolor{red}{\textvisiblespace}``. When a long code line is
split, the last space character from the source code line right before the
@ -783,6 +817,8 @@ Macros
multiple paragraphs in header cells of tables.
.. versionadded:: 1.6.3
``\sphinxstylecodecontinued`` and ``\sphinxstylecodecontinues``.
.. versionadded:: 3.0
``\sphinxkeyboard``
- ``\sphinxtableofcontents``: it is a
wrapper (defined differently in :file:`sphinxhowto.cls` and in
:file:`sphinxmanual.cls`) of standard ``\tableofcontents``. The macro

View File

@ -7,7 +7,6 @@ if "%SPHINXBUILD%" == "" (
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=sphinx-doc
if "%1" == "" goto help

View File

@ -5,7 +5,7 @@ Synopsis
--------
**sphinx-apidoc** [*OPTIONS*] -o <*OUTPUT_PATH*> <*MODULE_PATH*>
[*EXCLUDE_PATTERN*, ...]
[*EXCLUDE_PATTERN* ...]
Description
-----------
@ -39,6 +39,11 @@ Options
Directory to place the output files. If it does not exist, it is created.
.. option:: -q
Do not output anything on standard output, only write warnings and errors to
standard error.
.. option:: -f, --force
Force overwriting of any existing generated files.

View File

@ -73,7 +73,7 @@ If you run the following:
.. code-block:: bash
$ PYTHONPATH=. sphinx-autodoc doc/index.rst
$ PYTHONPATH=. sphinx-autogen docs/index.rst
then the following stub files will be created in ``docs``::

View File

@ -121,6 +121,17 @@ The following blocks exist in the ``layout.html`` template:
The contents of the document itself. It contains the block "body" where the
individual content is put by subtemplates like ``page.html``.
.. note::
In order for the built-in JavaScript search to show a page preview on
the results page, the document or body content should be wrapped in an
HTML element containing the ``role="main"`` attribute. For example:
.. sourcecode:: html+jinja
<div role="main">
{% block document %}{% endblock %}
</div>
`sidebar1` / `sidebar2`
A possible location for a sidebar. `sidebar1` appears before the document
and is empty by default, `sidebar2` after the document and contains the
@ -216,6 +227,7 @@ them to generate links or output multiply used elements.
documents.
.. function:: pathto(file, 1)
:noindex:
Return the path to a *file* which is a filename relative to the root of the
generated output. Use this to refer to static files.
@ -402,10 +414,6 @@ are in HTML form), these variables are also available:
nonempty if the :confval:`html_copy_source` value is ``True``.
This has empty value on creating automatically-generated files.
.. data:: title
The page title.
.. data:: toc
The local table of contents for the current page, rendered as HTML bullet
@ -427,5 +435,3 @@ are in HTML form), these variables are also available:
* ``includehidden`` (``False`` by default): if true, the TOC tree will also
contain hidden entries.

View File

@ -63,6 +63,11 @@ Python :mod:`ConfigParser` module) and has the following structure:
highlighting. This can be overridden by the user in the
:confval:`pygments_style` config value.
* The **pygments_dark_style** setting gives the name of a Pygments style to use
for highlighting when the CSS media query ``(prefers-color-scheme: dark)``
evaluates to true. It is injected into the page using
:meth:`~Sphinx.add_css_file()`.
* The **sidebars** setting gives the comma separated list of sidebar templates
for constructing sidebars. This can be overridden by the user in the
:confval:`html_sidebars` config value.

View File

@ -9,11 +9,11 @@ Complementary to translations provided for Sphinx-generated messages such as
navigation bars, Sphinx provides mechanisms facilitating *document* translations
in itself. See the :ref:`intl-options` for details on configuration.
.. figure:: /_static/translation.png
.. figure:: /_static/translation.svg
:width: 100%
Workflow visualization of translations in Sphinx. (The stick-figure is taken
from an `XKCD comic <https://xkcd.com/779/>`_.)
Workflow visualization of translations in Sphinx. (The figure is created by
`plantuml <http://plantuml.com>`_.)
.. contents::
:local:
@ -90,9 +90,9 @@ section describe an easy way to translate with *sphinx-intl*.
locale_dirs = ['locale/'] # path is example but recommended.
gettext_compact = False # optional.
This case-study assumes that :confval:`locale_dirs` is set to ``locale/`` and
:confval:`gettext_compact` is set to ``False`` (the Sphinx document is
already configured as such).
This case-study assumes that BUILDDIR is set to ``_build``,
:confval:`locale_dirs` is set to ``locale/`` and :confval:`gettext_compact`
is set to ``False`` (the Sphinx document is already configured as such).
#. Extract translatable messages into pot files.

View File

@ -57,7 +57,7 @@ Once configured, call this by calling the relevant command on ``setup.py``::
Options for setuptools integration
----------------------------------
.. confval:: fresh-env
.. setuptools-confval:: fresh-env
A boolean that determines whether the saved environment should be discarded
on build. Default is false.
@ -68,7 +68,7 @@ Options for setuptools integration
$ python setup.py build_sphinx -E
.. confval:: all-files
.. setuptools-confval:: all-files
A boolean that determines whether all files should be built from scratch.
Default is false.
@ -79,7 +79,7 @@ Options for setuptools integration
$ python setup.py build_sphinx -a
.. confval:: source-dir
.. setuptools-confval:: source-dir
The target source directory. This can be relative to the ``setup.py`` or
``setup.cfg`` file, or it can be absolute. It defaults to ``./doc`` or
@ -92,12 +92,12 @@ Options for setuptools integration
$ python setup.py build_sphinx -s $SOURCE_DIR
.. confval:: build-dir
.. setuptools-confval:: build-dir
The target build directory. This can be relative to the ``setup.py`` or
``setup.cfg`` file, or it can be absolute. Default is ``./build/sphinx``.
.. confval:: config-dir
.. setuptools-confval:: config-dir
Location of the configuration directory. This can be relative to the
``setup.py`` or ``setup.cfg`` file, or it can be absolute. Default is to use
@ -111,7 +111,7 @@ Options for setuptools integration
.. versionadded:: 1.0
.. confval:: builder
.. setuptools-confval:: builder
The builder or list of builders to use. Default is ``html``.
@ -124,7 +124,7 @@ Options for setuptools integration
.. versionchanged:: 1.6
This can now be a comma- or space-separated list of builders
.. confval:: warning-is-error
.. setuptools-confval:: warning-is-error
A boolean that ensures Sphinx warnings will result in a failed build.
Default is false.
@ -137,32 +137,32 @@ Options for setuptools integration
.. versionadded:: 1.5
.. confval:: project
.. setuptools-confval:: project
The documented project's name. Default is ``''``.
.. versionadded:: 1.0
.. confval:: version
.. setuptools-confval:: version
The short X.Y version. Default is ``''``.
.. versionadded:: 1.0
.. confval:: release
.. setuptools-confval:: release
The full version, including alpha/beta/rc tags. Default is ``''``.
.. versionadded:: 1.0
.. confval:: today
.. setuptools-confval:: today
How to format the current date, used as the replacement for ``|today|``.
Default is ``''``.
.. versionadded:: 1.0
.. confval:: link-index
.. setuptools-confval:: link-index
A boolean that ensures index.html will be linked to the master doc. Default
is false.
@ -175,13 +175,13 @@ Options for setuptools integration
.. versionadded:: 1.0
.. confval:: copyright
.. setuptools-confval:: copyright
The copyright string. Default is ``''``.
.. versionadded:: 1.3
.. confval:: nitpicky
.. setuptools-confval:: nitpicky
Run in nit-picky mode. Currently, this generates warnings for all missing
references. See the config value :confval:`nitpick_ignore` for a way to
@ -189,7 +189,7 @@ Options for setuptools integration
.. versionadded:: 1.8
.. confval:: pdb
.. setuptools-confval:: pdb
A boolean to configure ``pdb`` on exception. Default is false.

View File

@ -313,6 +313,7 @@ General configuration
* ``ref.doc``
* ``ref.python``
* ``misc.highlighting_failure``
* ``toc.circular``
* ``toc.secnum``
* ``epub.unknown_project_files``
* ``autosectionlabel.*``
@ -510,6 +511,14 @@ General configuration
.. versionadded:: 1.6.6
.. confval:: user_agent
A User-Agent of Sphinx. It is used for a header on HTTP access (ex.
linkcheck, intersphinx and so on). Default is ``"Sphinx/X.Y.Z
requests/X.Y.Z python/X.Y.Z"``.
.. versionadded:: 2.3
.. confval:: tls_verify
If true, Sphinx verifies server certifications. Default is ``True``.
@ -530,7 +539,7 @@ General configuration
directory pointed ``REQUESTS_CA_BUNDLE`` environment
variable if ``tls_cacerts`` not set.
.. _requests: http://docs.python-requests.org/en/master/
.. _requests: https://requests.readthedocs.io/en/master/
.. confval:: today
today_fmt
@ -566,7 +575,7 @@ General configuration
A dictionary of options that modify how the lexer specified by
:confval:`highlight_language` generates highlighted source code. These are
lexer-specific; for the options understood by each, see the
`Pygments documentation <http://pygments.org/docs/lexers/>`_.
`Pygments documentation <https://pygments.org/docs/lexers.html>`_.
.. versionadded:: 1.3
@ -626,6 +635,16 @@ General configuration
.. versionchanged:: 1.1
Now also removes ``<BLANKLINE>``.
.. confval:: strip_signature_backslash
Default is ``False``.
When backslash stripping is enabled then every occurrence of ``\\`` in a
domain directive will be changed to ``\``, even within string literals.
This was the behaviour before version 3.0, and setting this variable to
``True`` will reinstate that behaviour.
.. versionadded:: 3.0
.. _intl-options:
@ -654,12 +673,18 @@ documentation on :ref:`intl` for details.
Currently supported languages by Sphinx are:
* ``ar`` -- Arabic
* ``bg`` -- Bulgarian
* ``bn`` -- Bengali
* ``ca`` -- Catalan
* ``cak`` -- Kaqchikel
* ``cs`` -- Czech
* ``cy`` -- Welsh
* ``da`` -- Danish
* ``de`` -- German
* ``el`` -- Greek
* ``en`` -- English
* ``eo`` -- Esperanto
* ``es`` -- Spanish
* ``et`` -- Estonian
* ``eu`` -- Basque
@ -667,6 +692,8 @@ documentation on :ref:`intl` for details.
* ``fi`` -- Finnish
* ``fr`` -- French
* ``he`` -- Hebrew
* ``hi`` -- Hindi
* ``hi_IN`` -- Hindi (India)
* ``hr`` -- Croatian
* ``hu`` -- Hungarian
* ``id`` -- Indonesian
@ -680,15 +707,24 @@ documentation on :ref:`intl` for details.
* ``ne`` -- Nepali
* ``nl`` -- Dutch
* ``pl`` -- Polish
* ``pt`` -- Portuguese
* ``pt_BR`` -- Brazilian Portuguese
* ``pt_PT`` -- European Portuguese
* ``ro`` -- Romanian
* ``ru`` -- Russian
* ``si`` -- Sinhala
* ``sk`` -- Slovak
* ``sl`` -- Slovenian
* ``sq`` -- Albanian
* ``sr`` -- Serbian
* ``sr@latin`` -- Serbian (Latin)
* ``sr_RS`` -- Serbian (Cyrillic)
* ``sv`` -- Swedish
* ``ta`` -- Tamil
* ``te`` -- Telugu
* ``tr`` -- Turkish
* ``uk_UA`` -- Ukrainian
* ``ur`` -- Urdu
* ``vi`` -- Vietnamese
* ``zh_CN`` -- Simplified Chinese
* ``zh_TW`` -- Traditional Chinese
@ -762,7 +798,7 @@ documentation on :ref:`intl` for details.
i18n additionally. You can specify below names:
:index: index terms
:literal-block: literal blocks: ``::`` and ``code-block``.
:literal-block: literal blocks (``::`` annotation and ``code-block`` directive)
:doctest-block: doctest block
:raw: raw content
:image: image/figure uri and alt
@ -930,7 +966,7 @@ that use Sphinx's HTMLWriter class.
Example::
html_css_files = ['custom.css'
html_css_files = ['custom.css',
'https://example.com/css/custom.css',
('print.css', {'media': 'print'})]
@ -1338,8 +1374,21 @@ that use Sphinx's HTMLWriter class.
'target' option or scale related options: 'scale', 'width', 'height'.
The default is ``True``.
Document authors can this feature manually with giving ``no-scaled-link``
class to the image:
.. code-block:: rst
.. image:: sphinx.png
:scale: 50%
:class: no-scaled-link
.. versionadded:: 1.3
.. versionchanged:: 2.4
It is disabled for images having ``no-scaled-link`` class
.. confval:: html_math_renderer
The name of math_renderer extension for HTML output. The default is
@ -1828,6 +1877,7 @@ These options influence LaTeX output.
* ``'xelatex'`` -- XeLaTeX
* ``'lualatex'`` -- LuaLaTeX
* ``'platex'`` -- pLaTeX (default if :confval:`language` is ``'ja'``)
* ``'uplatex'`` -- upLaTeX (experimental)
``'pdflatex'``\ 's support for Unicode characters is limited.
@ -1841,7 +1891,21 @@ These options influence LaTeX output.
``'xelatex'`` or ``'lualatex'`` and making sure to use an OpenType font
with wide-enough glyph coverage is often easier than trying to make
``'pdflatex'`` work with the extra Unicode characters. Since Sphinx 2.0
the default is the GNU FreeFont which covers well Latin, Cyrillic and Greek.
the default is the GNU FreeFont which covers well Latin, Cyrillic and
Greek.
.. versionchanged:: 2.1.0
Use ``xelatex`` (and LaTeX package ``xeCJK``) by default for Chinese
documents.
.. versionchanged:: 2.2.1
Use ``xelatex`` by default for Greek documents.
.. versionchanged:: 2.3
Add ``uplatex`` support.
Contrarily to :ref:`MathJaX math rendering in HTML output <math-support>`,
LaTeX requires some extra configuration to support Unicode literals in
@ -1857,7 +1921,7 @@ These options influence LaTeX output.
This value determines how to group the document tree into LaTeX source files.
It must be a list of tuples ``(startdocname, targetname, title, author,
documentclass, toctree_only)``, where the items are:
theme, toctree_only)``, where the items are:
*startdocname*
String that specifies the :term:`document name` of the LaTeX file's master
@ -1879,13 +1943,8 @@ These options influence LaTeX output.
applies. Use ``\\and`` to separate multiple authors, as in:
``'John \\and Sarah'`` (backslashes must be Python-escaped to reach LaTeX).
*documentclass*
Normally, one of ``'manual'`` or ``'howto'`` (provided by Sphinx and based
on ``'report'``, resp. ``'article'``; Japanese documents use ``'jsbook'``,
resp. ``'jreport'``.) "howto" (non-Japanese) documents will not get
appendices. Also they have a simpler title page. Other document classes
can be given. Independently of the document class, the "sphinx" package is
always loaded in order to define Sphinx's custom LaTeX commands.
*theme*
LaTeX theme. See :confval:`latex_theme`.
*toctree_only*
Must be ``True`` or ``False``. If true, the *startdoc* document itself is
@ -2040,6 +2099,40 @@ These options influence LaTeX output.
This overrides the files which is provided from Sphinx such as
``sphinx.sty``.
.. confval:: latex_theme
The "theme" that the LaTeX output should use. It is a collection of settings
for LaTeX output (ex. document class, top level sectioning unit and so on).
As a built-in LaTeX themes, ``manual`` and ``howto`` are bundled.
``manual``
A LaTeX theme for writing a manual. It imports the ``report`` document
class (Japanese documents use ``jsbook``).
``howto``
A LaTeX theme for writing an article. It imports the ``article`` document
class (Japanese documents use ``jreport`` rather). :confval:`latex_appendices`
is available only for this theme.
It defaults to ``'manual'``.
.. versionadded:: 3.0
.. confval:: latex_theme_options
A dictionary of options that influence the look and feel of the selected
theme.
.. versionadded:: 3.1
.. confval:: latex_theme_path
A list of paths that contain custom LaTeX themes as subdirectories. Relative
paths are taken as relative to the configuration directory.
.. versionadded:: 3.0
.. _text-options:
@ -2346,6 +2439,34 @@ Options for the linkcheck builder
.. versionadded:: 1.5
.. confval:: linkcheck_auth
Pass authentication information when doing a ``linkcheck`` build.
A list of ``(regex_pattern, auth_info)`` tuples where the items are:
*regex_pattern*
A regular expression that matches a URI.
*auth_info*
Authentication information to use for that URI. The value can be anything
that is understood by the ``requests`` library (see `requests
Authentication <requests-auth>`_ for details).
.. _requests-auth: https://requests.readthedocs.io/en/master/user/authentication/
The ``linkcheck`` builder will use the first matching ``auth_info`` value
it can find in the :confval:`linkcheck_auth` list, so values earlier in the
list have higher priority.
Example::
linkcheck_auth = [
('https://foo\.yourcompany\.com/.+', ('johndoe', 'secret')),
('https://.+\.yourcompany\.com/.+', HTTPDigestAuth(...)),
]
.. versionadded:: 2.3
Options for the XML builder
---------------------------
@ -2365,6 +2486,30 @@ Options for the XML builder
match any sequence of characters *including* slashes.
.. _c-config:
Options for the C domain
------------------------
.. confval:: c_id_attributes
A list of strings that the parser additionally should accept as attributes.
This can for example be used when attributes have been ``#define`` d for
portability.
.. versionadded:: 3.0
.. confval:: c_paren_attributes
A list of strings that the parser additionally should accept as attributes
with one argument. That is, if ``my_align_as`` is in the list, then
``my_align_as(X)`` is parsed as an attribute for all strings ``X`` that have
balanced braces (``()``, ``[]``, and ``{}``). This can for example be used
when attributes have been ``#define`` d for portability.
.. versionadded:: 3.0
.. _cpp-config:
Options for the C++ domain

View File

@ -140,6 +140,20 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
.. versionadded:: 1.1
* autodoc considers a member private if its docstring contains
``:meta private:`` in its :ref:`info-field-lists`.
For example:
.. code-block:: rst
def my_function(my_arg, my_other_arg):
"""blah blah blah
:meta private:
"""
.. versionadded:: 3.0
* Python "special" members (that is, those named like ``__special__``) will
be included if the ``special-members`` flag option is given::
@ -157,7 +171,7 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
* For classes and exceptions, members inherited from base classes will be
left out when documenting all members, unless you give the
``inherited-members`` flag option, in addition to ``members``::
``inherited-members`` option, in addition to ``members``::
.. autoclass:: Noodle
:members:
@ -166,11 +180,29 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
This can be combined with ``undoc-members`` to document *all* available
members of the class or module.
It can take an ancestor class not to document inherited members from it.
By default, members of ``object`` class are not documented. To show them
all, give ``None`` to the option.
For example; If your class ``Foo`` is derived from ``list`` class and
you don't want to document ``list.__len__()``, you should specify a
option ``:inherited-members: list`` to avoid special members of list
class.
Another example; If your class Foo has ``__str__`` special method and
autodoc directive has both ``inherited-members`` and ``special-members``,
``__str__`` will be documented as in the past, but other special method
that are not implemented in your class ``Foo``.
Note: this will lead to markup errors if the inherited members come from a
module whose docstrings are not reST formatted.
.. versionadded:: 0.3
.. versionchanged:: 3.0
It takes an anchestor class name as an argument.
* It's possible to override the signature for explicitly documented callable
objects (functions, methods, classes) with the regular syntax that will
override the signature gained from introspection::
@ -308,9 +340,6 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
a decorator replaces the decorated function with another, it must copy the
original ``__doc__`` to the new function.
From Python 2.5, :func:`functools.wraps` can be used to create
well-behaved decorating functions.
Configuration
-------------
@ -437,9 +466,13 @@ There are also config values that you can set:
following values:
* ``'signature'`` -- Show typehints as its signature (default)
* ``'description'`` -- Show typehints as content of function or method
* ``'none'`` -- Do not show typehints
.. versionadded: 2.1
.. versionadded:: 2.1
.. versionadded:: 3.0
New option ``'description'`` is added.
.. confval:: autodoc_warningiserror
@ -494,6 +527,17 @@ autodoc provides the following additional events:
auto directive
:param lines: the lines of the docstring, see above
.. event:: autodoc-before-process-signature (app, obj, bound_method)
.. versionadded:: 2.4
Emitted before autodoc formats a signature for an object. The event handler
can modify an object to change its signature.
:param app: the Sphinx application object
:param obj: the object itself
:param bound_method: a boolean indicates an object is bound method or not
.. event:: autodoc-process-signature (app, what, name, obj, options, signature, return_annotation)
.. versionadded:: 0.5

View File

@ -81,6 +81,12 @@ The :mod:`sphinx.ext.autosummary` extension does this in three parts:
directory. If no argument is given, output is placed in the same directory
as the file that contains the directive.
You can also use ``caption`` option to give a caption to the toctree.
.. versionadded:: 3.1
caption option added.
* If you don't want the :rst:dir:`autosummary` to show function signatures in
the listing, include the ``nosignatures`` option::
@ -162,6 +168,11 @@ also use these config values:
The new files will be placed in the directories specified in the
``:toctree:`` options of the directives.
.. versionchanged:: 2.3
Emits :event:`autodoc-skip-member` event as :mod:`~sphinx.ext.autodoc`
does.
.. confval:: autosummary_generate_overwrite
If true, autosummary already overwrites stub files by generated contents.
@ -300,6 +311,7 @@ Additionally, the following filters are available
replaces the builtin Jinja `escape filter`_ that does html-escaping.
.. function:: underline(s, line='=')
:noindex:
Add a title underline to a piece of text.

View File

@ -11,11 +11,15 @@
pair: testing; snippets
This extension allows you to test snippets in the documentation in a natural
way. It works by collecting specially-marked up code blocks and running them as
doctest tests.
It is often helpful to include snippets of code in your documentation and
demonstrate the results of executing them. But it is important to ensure that
the documentation stays up-to-date with the code.
Within one document, test code is partitioned in *groups*, where each group
This extension allows you to test such code snippets in the documentation in
a natural way. If you mark the code blocks as shown here, the ``doctest``
builder will collect them and run them as doctest tests.
Within each document, you can assign each snippet to a *group*. Each group
consists of:
* zero or more *setup code* blocks (e.g. importing the module to test)

View File

@ -0,0 +1,11 @@
:mod:`sphinx.ext.duration` -- Measure durations of Sphinx processing
====================================================================
.. module:: sphinx.ext.duration
:synopsis: Measure durations of Sphinx processing
.. versionadded:: 2.4
This extension measures durations of Sphinx processing and show its
result at end of the build. It is useful for inspecting what document
is slowly built.

View File

@ -82,6 +82,13 @@ It adds these directives:
.. versionadded:: 1.6
.. rst:directive:option:: class: class names
:type: a list of class names separeted by spaces
The class name of the graph.
.. versionadded:: 2.4
.. rst:directive:: graph
@ -131,6 +138,13 @@ It adds these directives:
.. versionadded:: 1.6
.. rst:directive:option:: class: class names
:type: a list of class names separeted by spaces
The class name of the graph.
.. versionadded:: 2.4
.. rst:directive:: digraph
@ -176,6 +190,13 @@ It adds these directives:
.. versionadded:: 1.6
.. rst:directive:option:: class: class names
:type: a list of class names separeted by spaces
The class name of the graph.
.. versionadded:: 2.4
There are also these config values:

View File

@ -34,7 +34,19 @@ Configuration
A path to :command:`convert` command. By default, the imgconverter uses
the command from search paths.
On windows platform, :command:`magick` command is used by default.
.. versionchanged:: 3.1
Use :command:`magick` command by default on windows
.. confval:: image_converter_args
Additional command-line arguments to give to :command:`convert`, as a list.
The default is an empty list ``[]``.
On windows platform, it defaults to ``["convert"]``.
.. versionchanged:: 3.1
Use ``["convert"]`` by default on windows

View File

@ -23,6 +23,7 @@ These extensions are built in and can be activated by respective entries in the
autosummary
coverage
doctest
duration
extlinks
githubpages
graphviz

View File

@ -148,3 +148,13 @@ project. The following example prints the Intersphinx mapping of the Python 3
documentation::
$ python -msphinx.ext.intersphinx https://docs.python.org/3/objects.inv
Using Intersphinx with inventory file under Basic Authorization
---------------------------------------------------------------
Intersphinx supports Basic Authorization like this::
intersphinx_mapping = {'python': ('https://user:password@docs.python.org/3',
None)}
The user and password will be stripped from the URL when generating the links.

View File

@ -50,7 +50,7 @@ are built:
``preview-latex-style`` on Ubuntu xenial). Therefore, the default for this
option is ``False`` but it is strongly recommended to set it to ``True``.
.. versionchanged:: 2.1
.. versionchanged:: 2.2
This option can be used with the ``'svg'`` :confval:`imgmath_image_format`.
@ -80,6 +80,14 @@ are built:
This value should only contain the path to the latex executable, not further
arguments; use :confval:`imgmath_latex_args` for that purpose.
.. hint::
Some fancy LaTeX mark-up (an example was reported which used TikZ to add
various decorations to the equation) require multiple runs of the LaTeX
executable. To handle this, set this configuration setting to
``'latexmk'`` (or a full path to it) as this Perl script reliably
chooses dynamically how many latex runs are needed.
.. confval:: imgmath_latex_args
Additional arguments to give to latex, as a list. The default is an empty
@ -183,6 +191,8 @@ Sphinx but is set to automatically include it from a third-party site.
The default is empty (``{}``).
.. versionadded:: 1.8
.. confval:: mathjax_config
The inline configuration options for mathjax. The value is used as a
@ -198,6 +208,8 @@ Sphinx but is set to automatically include it from a third-party site.
The default is empty (not configured).
.. versionadded:: 1.8
.. _Using in-line configuration options: https://docs.mathjax.org/en/latest/configuration.html#using-in-line-configuration-options
:mod:`sphinx.ext.jsmath` -- Render math via JavaScript

View File

@ -56,7 +56,7 @@ source code files.
.. _Google:
https://google.github.io/styleguide/pyguide.html#Comments
.. _NumPy:
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
.. _Khan Academy:
https://github.com/Khan/style-guides/blob/master/style/python.md#docstrings

View File

@ -23,8 +23,7 @@ Linux
Debian/Ubuntu
~~~~~~~~~~~~~
Install either ``python3-sphinx`` (Python 3) or ``python-sphinx`` (Python 2)
using :command:`apt-get`:
Install either ``python3-sphinx`` using :command:`apt-get`:
::
@ -77,23 +76,22 @@ __ https://formulae.brew.sh/formula/sphinx-doc
MacPorts
~~~~~~~~
Install either ``python36-sphinx`` (Python 3) or ``python27-sphinx`` (Python 2)
using :command:`port`:
Install either ``python3x-sphinx`` using :command:`port`:
::
$ sudo port install py36-sphinx
$ sudo port install py38-sphinx
To set up the executable paths, use the ``port select`` command:
::
$ sudo port select --set python python36
$ sudo port select --set sphinx py36-sphinx
$ sudo port select --set python python38
$ sudo port select --set sphinx py38-sphinx
For more information, refer to the `package overview`__.
__ https://www.macports.org/ports.php?by=library&substr=py36-sphinx
__ https://www.macports.org/ports.php?by=library&substr=py38-sphinx
Anaconda
~~~~~~~~
@ -161,6 +159,37 @@ the ``--pre`` flag.
$ pip install -U --pre sphinx
Docker
------
Docker images for Sphinx are published on the `Docker Hub <https://hub.docker.com/>`_. There are two kind of images:
- `sphinxdoc/sphinx <https://hub.docker.com/repository/docker/sphinxdoc/sphinx>`_
- `sphinxdoc/sphinx-latexpdf <https://hub.docker.com/repository/docker/sphinxdoc/sphinx-latexpdf>`_
Former one is used for standard usage of Sphinx, and latter one is mainly used for PDF builds using LaTeX.
Please choose one for your purpose.
.. note::
sphinxdoc/sphinx-latexpdf contains TeXLive packages. So the image is very large (over 2GB!).
.. hint::
When using docker images, please use ``docker run`` command to invoke sphinx commands. For example,
you can use following command to create a Sphinx project::
$ docker run --rm -v /path/to/document:/docs sphinxdoc/sphinx sphinx-quickstart
And you can following command this to build HTML document::
$ docker run --rm -v /path/to/document:/docs sphinxdoc/sphinx make html
For more details, please read `README file`__ of docker images.
.. __: https://hub.docker.com/repository/docker/sphinxdoc/sphinx
Installation from source
------------------------

View File

@ -26,9 +26,6 @@ configuration values from a few questions it asks you. To use this, run:
$ sphinx-quickstart
Answer each question asked. Be sure to say "yes" to the ``autodoc`` extension, as
we will use this later.
There is also an automatic "API documentation" generator called
:program:`sphinx-apidoc`; see :doc:`/man/sphinx-apidoc` for details.
@ -37,12 +34,11 @@ Defining document structure
---------------------------
Let's assume you've run :program:`sphinx-quickstart`. It created a source
directory with :file:`conf.py` and a master document, :file:`index.rst` (if you
accepted the defaults). The main function of the :term:`master document` is to
serve as a welcome page, and to contain the root of the "table of contents
tree" (or *toctree*). This is one of the main things that Sphinx adds to
reStructuredText, a way to connect multiple files to a single hierarchy of
documents.
directory with :file:`conf.py` and a master document, :file:`index.rst`. The
main function of the :term:`master document` is to serve as a welcome page, and
to contain the root of the "table of contents tree" (or *toctree*). This is one
of the main things that Sphinx adds to reStructuredText, a way to connect
multiple files to a single hierarchy of documents.
.. sidebar:: reStructuredText directives
@ -233,8 +229,7 @@ customize a config value that is not automatically added by
Keep in mind that the file uses Python syntax for strings, numbers, lists and
so on. The file is saved in UTF-8 by default, as indicated by the encoding
declaration in the first line. If you use non-ASCII characters in any string
value, you need to use Python Unicode strings (like ``project = u'Exposé'``).
declaration in the first line.
|more| See :doc:`/usage/configuration` for documentation of all available
config values.
@ -252,10 +247,12 @@ module that provides additional features for Sphinx projects) called *autodoc*.
In order to use *autodoc*, you need to activate it in :file:`conf.py` by
putting the string ``'sphinx.ext.autodoc'`` into the list assigned to the
:confval:`extensions` config value. Then, you have a few additional directives
at your disposal.
:confval:`extensions` config value::
For example, to document the function ``io.open()``, reading its signature and
extensions = ['sphinx.ext.autodoc']
Then, you have a few additional directives at your disposal. For example, to
document the function ``io.open()``, reading its signature and
docstring from the source file, you'd write this::
.. autofunction:: io.open

View File

@ -372,7 +372,8 @@ Docutils supports the following directives:
* HTML specifics:
- :dudir:`meta` (generation of HTML ``<meta>`` tags)
- :dudir:`meta`
(generation of HTML ``<meta>`` tags, see also :ref:`html-meta` below)
- :dudir:`title <metadata-document-title>` (override document title)
* Influencing markup:
@ -538,6 +539,45 @@ You can indent text after a comment start to form multiline comments::
Still in the comment.
.. _html-meta:
HTML Metadata
-------------
The :rst:dir:`meta` directive (:dudir:`ref <meta>`) allows specifying the HTML
`metadata element`_ of a Sphinx documentation page. For example, the
directive::
.. meta::
:description: The Sphinx documentation builder
:keywords: Sphinx, documentation, builder
will generate the following HTML output:
.. code:: html
<meta name="description" content="The Sphinx documentation builder">
<meta name="keywords" content="Sphinx, documentation, builder">
Also, Sphinx will add the keywords as specified in the meta directive to the
search index. Thereby, the ``lang`` attribute of the meta element is
considered. For example, the directive::
.. meta::
:keywords: backup
:keywords lang=en: pleasefindthiskey pleasefindthiskeytoo
:keywords lang=de: bittediesenkeyfinden
adds the following words to the search indices of builds with different language
configurations:
* ``pleasefindthiskey``, ``pleasefindthiskeytoo`` to *English* builds;
* ``bittediesenkeyfinden`` to *German* builds;
* ``backup`` to builds in all languages.
.. _metadata element: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
Source encoding
---------------

View File

@ -48,6 +48,12 @@ tables of contents. The ``toctree`` directive is the central element.
to the source directory. A numeric ``maxdepth`` option may be given to
indicate the depth of the tree; by default, all levels are included. [#]_
The representation of "TOC tree" is changed in each output format. The
builders that output multiple files (ex. HTML) treat it as a collection of
hyperlinks. On the other hand, the builders that output a single file (ex.
LaTeX, man page, etc.) replace it with the content of the documents on the
TOC tree.
Consider this example (taken from the Python docs' library reference index)::
.. toctree::
@ -441,7 +447,7 @@ If highlighting with the selected language fails (i.e. Pygments emits an
want to ensure consistent highlighting, you should fix your version of
Pygments.
__ http://pygments.org/docs/lexers/
__ http://pygments.org/docs/lexers
.. rst:directive:: .. highlight:: language
@ -453,21 +459,29 @@ __ http://pygments.org/docs/lexers/
As discussed previously, *language* can be any lexer alias supported by
Pygments.
**Additional options**
.. rubric:: options
Pygments can generate line numbers for code blocks. To enable this, use the
``linenothreshold`` option. ::
.. rst:directive:option:: linenothreshold: threshold
:type: number (optional)
.. highlight:: python
:linenothreshold: 5
Enable to generate line numbers for code blocks.
This will produce line numbers for all code blocks longer than five lines.
This option takes an optional number as threshold parameter. If any
threshold given, the directive will produce line numbers only for the code
blocks longer than N lines. If not given, line numbers will be produced
for all of code blocks.
To ignore minor errors on highlighting, you can specifiy ``:force:`` option.
Example::
.. versionchanged:: 2.1
.. highlight:: python
:linenothreshold: 5
``:force:`` option.
.. rst:directive:option:: force
:type: no value
If given, minor errors on highlighting are ignored.
.. versionadded:: 2.1
.. rst:directive:: .. code-block:: [language]
@ -483,72 +497,98 @@ __ http://pygments.org/docs/lexers/
:rst:dir:`highlight` directive will be used. If not set,
:confval:`highlight_language` will be used.
**Additional options**
Pygments can generate line numbers for code blocks. To enable this for, use
the ``linenos`` flag option. ::
.. code-block:: ruby
:linenos:
Some more Ruby code.
The first line number can be selected with the ``lineno-start`` option. If
present, ``linenos`` flag is automatically activated::
.. code-block:: ruby
:lineno-start: 10
Some more Ruby code, with line numbering starting at 10.
Additionally, an ``emphasize-lines`` option can be given to have Pygments
emphasize particular lines::
.. code-block:: python
:emphasize-lines: 3,5
def some_function():
interesting = False
print 'This line is highlighted.'
print 'This one is not...'
print '...but this one is.'
A ``caption`` option can be given to show that name before the code block.
A ``name`` option can be provided implicit target name that can be
referenced by using :rst:role:`ref`. For example::
.. code-block:: python
:caption: this.py
:name: this-py
print 'Explicit is better than implicit.'
A ``dedent`` option can be given to strip indentation characters from the
code block. For example::
.. code-block:: ruby
:dedent: 4
some ruby code
A ``force`` option can ignore minor errors on highlighting.
.. versionchanged:: 1.1
The ``emphasize-lines`` option has been added.
.. versionchanged:: 1.3
The ``lineno-start``, ``caption``, ``name`` and ``dedent`` options have
been added.
.. versionchanged:: 1.6.6
LaTeX supports the ``emphasize-lines`` option.
.. versionchanged:: 2.0
The ``language`` argument becomes optional.
.. versionchanged:: 2.1
.. rubric:: options
``:force:`` option has been added.
.. rst:directive:option:: linenos
:type: no value
Enable to generate line numbers for the code block::
.. code-block:: ruby
:linenos:
Some more Ruby code.
.. rst:directive:option:: lineno-start: number
:type: number
Set the first line number of the code block. If present, ``linenos``
option is also automatically activated::
.. code-block:: ruby
:lineno-start: 10
Some more Ruby code, with line numbering starting at 10.
.. versionadded:: 1.3
.. rst:directive:option:: emphasize-lines: line numbers
:type: comma separated numbers
Emphasize particular lines of the code block::
.. code-block:: python
:emphasize-lines: 3,5
def some_function():
interesting = False
print 'This line is highlighted.'
print 'This one is not...'
print '...but this one is.'
.. versionadded:: 1.1
.. versionchanged:: 1.6.6
LaTeX supports the ``emphasize-lines`` option.
.. rst:directive:option: force
:type: no value
Ignore minor errors on highlighting
.. versionchanged:: 2.1
.. rst:directive:option:: caption: caption of code block
:type: text
Set a caption to the code block.
.. versionadded:: 1.3
.. rst:directive:option:: name: a label for hyperlink
:type: text
Define implicit target name that can be referenced by using
:rst:role:`ref`. For example::
.. code-block:: python
:caption: this.py
:name: this-py
print 'Explicit is better than implicit.'
.. versionadded:: 1.3
.. rst:directive:option:: dedent: number
:type: number
Strip indentation characters from the code block. For example::
.. code-block:: ruby
:dedent: 4
some ruby code
.. versionadded:: 1.3
.. rst:directive:option:: force
:type: no value
If given, minor errors on highlighting are ignored.
.. versionadded:: 2.1
.. rst:directive:: .. literalinclude:: filename
@ -840,6 +880,19 @@ mainly contained in information units, such as the language reference.
.. versionchanged:: 1.1
Added ``see`` and ``seealso`` types, as well as marking main entries.
.. rubric:: options
.. rst:directive:option:: name: a label for hyperlink
:type: text
Define implicit target name that can be referenced by using
:rst:role:`ref`. For example::
.. index:: Python
:name: py-index
.. versionadded:: 3.0
.. rst:role:: index
While the :rst:dir:`index` directive is a block-level markup and links to the
@ -1017,7 +1070,7 @@ this reason, the following directive exists:
cells.
Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``,
``Y{f}`` and tabulary's columns.
``\Y{f}`` and tabulary's columns.
.. note::
@ -1105,7 +1158,7 @@ derived forms), but provides enough to allow context-free grammars to be
displayed in a way that causes uses of a symbol to be rendered as hyperlinks to
the definition of the symbol. There is this directive:
.. rst:directive:: .. productionlist:: [name]
.. rst:directive:: .. productionlist:: [productionGroup]
This directive is used to enclose a group of productions. Each production
is given on a single line and consists of a name, separated by a colon from
@ -1113,16 +1166,24 @@ the definition of the symbol. There is this directive:
continuation line must begin with a colon placed at the same column as in
the first line.
The argument to :rst:dir:`productionlist` serves to distinguish different
sets of production lists that belong to different grammars.
The *productionGroup* argument to :rst:dir:`productionlist` serves to
distinguish different sets of production lists that belong to different
grammars. Multiple production lists with the same *productionGroup* thus
define rules in the same scope.
Blank lines are not allowed within ``productionlist`` directive arguments.
The definition can contain token names which are marked as interpreted text
(e.g. ``sum ::= `integer` "+" `integer```) -- this generates
(e.g. "``sum ::= `integer` "+" `integer```") -- this generates
cross-references to the productions of these tokens. Outside of the
production list, you can reference to token productions using
:rst:role:`token`.
However, if you have given a *productionGroup* argument you must prefix the
token name in the cross-reference with the group name and a colon,
e.g., "``myGroup:sum``" instead of just "``sum``".
If the group should not be shown in the title of the link either
an explicit title can be given (e.g., "``myTitle <myGroup:sum>``"),
or the target can be prefixed with a tilde (e.g., "``~myGroup:sum``").
Note that no further reST parsing is done in the production, so that you
don't have to escape ``*`` or ``|`` characters.

View File

@ -195,6 +195,18 @@ The following directives are provided for module and class contents:
as "defined constants." Class and object attributes are not documented
using this environment.
.. rubric:: options
.. rst:directive:option:: type: type of the variable
:type: text
.. versionadded:: 2.4
.. rst:directive:option:: value: initial value of the variable
:type: text
.. versionadded:: 2.4
.. rst:directive:: .. py:exception:: name
Describes an exception class. The signature can, but need not include
@ -229,6 +241,18 @@ The following directives are provided for module and class contents:
information about the type of the data to be expected and whether it may be
changed directly.
.. rubric:: options
.. rst:directive:option:: type: type of the attribute
:type: text
.. versionadded:: 2.4
.. rst:directive:option:: value: initial value of the attribute
:type: text
.. versionadded:: 2.4
.. rst:directive:: .. py:method:: name(parameters)
Describes an object method. The parameters should not include the ``self``
@ -354,6 +378,9 @@ Info field lists
~~~~~~~~~~~~~~~~
.. versionadded:: 0.4
.. versionchanged:: 3.0
meta fields are added.
Inside Python object description directives, reST field lists with these fields
are recognized and formatted nicely:
@ -367,6 +394,10 @@ are recognized and formatted nicely:
* ``vartype``: Type of a variable. Creates a link if possible.
* ``returns``, ``return``: Description of the return value.
* ``rtype``: Return type. Creates a link if possible.
* ``meta``: Add metadata to description of the python object. The metadata will
not be shown on output document. For example, ``:meta private:`` indicates
the python object is private member. It is used in
:py:mod:`sphinx.ext.autodoc` for filtering members.
.. note::
@ -521,47 +552,62 @@ The C Domain
The C domain (name **c**) is suited for documentation of C API.
.. rst:directive:: .. c:member:: declaration
.. c:var:: declaration
Describes a C struct member or variable. Example signature::
.. c:member:: PyObject *PyTypeObject.tp_bases
The difference between the two directives is only cosmetic.
.. rst:directive:: .. c:function:: function prototype
Describes a C function. The signature should be given as in C, e.g.::
.. c:function:: PyObject* PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
This is also used to describe function-like preprocessor macros. The names
of the arguments should be given so they may be used in the description.
.. c:function:: PyObject *PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
Note that you don't have to backslash-escape asterisks in the signature, as
it is not parsed by the reST inliner.
.. rst:directive:: .. c:member:: declaration
Describes a C struct member. Example signature::
.. c:member:: PyObject* PyTypeObject.tp_bases
The text of the description should include the range of values allowed, how
the value should be interpreted, and whether the value can be changed.
References to structure members in text should use the ``member`` role.
.. rst:directive:: .. c:macro:: name
.. c:macro:: name(arg list)
Describes a "simple" C macro. Simple macros are macros which are used for
code expansion, but which do not take arguments so cannot be described as
functions. This is a simple C-language ``#define``. Examples of its use in
the Python documentation include :c:macro:`PyObject_HEAD` and
:c:macro:`Py_BEGIN_ALLOW_THREADS`.
Describes a C macro, i.e., a C-language ``#define``, without the replacement
text.
.. rst:directive:: .. c:type:: name
.. versionadded:: 3.0
The function style variant.
Describes a C type (whether defined by a typedef or struct). The signature
should just be the type name.
.. rst:directive:: .. c:struct:: name
.. rst:directive:: .. c:var:: declaration
Describes a C struct.
Describes a global C variable. The signature should include the type, such
as::
.. versionadded:: 3.0
.. c:var:: PyObject* PyClass_Type
.. rst:directive:: .. c:union:: name
Describes a C union.
.. versionadded:: 3.0
.. rst:directive:: .. c:enum:: name
Describes a C enum.
.. versionadded:: 3.0
.. rst:directive:: .. c:enumerator:: name
Describes a C enumerator.
.. versionadded:: 3.0
.. rst:directive:: .. c:type:: typedef-like declaration
.. c:type:: name
Describes a C type, either as a typedef, or the alias for an unspecified
type.
.. _c-roles:
@ -571,25 +617,164 @@ Cross-referencing C constructs
The following roles create cross-references to C-language constructs if they
are defined in the documentation:
.. rst:role:: c:func
Reference a C-language function. Should include trailing parentheses.
.. rst:role:: c:member
c:data
c:var
c:func
c:macro
c:struct
c:union
c:enum
c:enumerator
c:type
Reference a C-language member of a struct.
Reference a C declaration, as defined above.
Note that :rst:role:`c:member`, :rst:role:`c:data`, and
:rst:role:`c:var` are equivalent.
.. rst:role:: c:macro
.. versionadded:: 3.0
The var, struct, union, enum, and enumerator roles.
Reference a "simple" C macro, as defined above.
.. rst:role:: c:type
Anonymous Entities
~~~~~~~~~~~~~~~~~~
Reference a C-language type.
C supports anonymous structs, enums, and unions.
For the sake of documentation they must be given some name that starts with
``@``, e.g., ``@42`` or ``@data``.
These names can also be used in cross-references,
though nested symbols will be found even when omitted.
The ``@...`` name will always be rendered as **[anonymous]** (possibly as a
link).
.. rst:role:: c:data
Example::
Reference a C-language variable.
.. c:struct:: Data
.. c:union:: @data
.. c:var:: int a
.. c:var:: double b
Explicit ref: :c:var:`Data.@data.a`. Short-hand ref: :c:var:`Data.a`.
This will be rendered as:
.. c:struct:: Data
.. c:union:: @data
.. c:var:: int a
.. c:var:: double b
Explicit ref: :c:var:`Data.@data.a`. Short-hand ref: :c:var:`Data.a`.
.. versionadded:: 3.0
Inline Expressions and Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. rst:role:: c:expr
c:texpr
Insert a C expression or type either as inline code (``cpp:expr``)
or inline text (``cpp:texpr``). For example::
.. c:var:: int a = 42
.. c:function:: int f(int i)
An expression: :c:expr:`a * f(a)` (or as text: :c:texpr:`a * f(a)`).
A type: :c:expr:`const Data*`
(or as text :c:texpr:`const Data*`).
will be rendered as follows:
.. c:var:: int a = 42
.. c:function:: int f(int i)
An expression: :c:expr:`a * f(a)` (or as text: :c:texpr:`a * f(a)`).
A type: :c:expr:`const Data*`
(or as text :c:texpr:`const Data*`).
.. versionadded:: 3.0
Namespacing
~~~~~~~~~~~
.. versionadded:: 3.1
The C language it self does not support namespacing, but it can sometimes be
useful to emulate it in documentation, e.g., to show alternate declarations.
The feature may also be used to document members of structs/unions/enums
separate from their parent declaration.
The current scope can be changed using three namespace directives. They manage
a stack declarations where ``c:namespace`` resets the stack and changes a given
scope.
The ``c:namespace-push`` directive changes the scope to a given inner scope
of the current one.
The ``c:namespace-pop`` directive undoes the most recent
``c:namespace-push`` directive.
.. rst:directive:: .. c:namespace:: scope specification
Changes the current scope for the subsequent objects to the given scope, and
resets the namespace directive stack. Note that nested scopes can be
specified by separating with a dot, e.g.::
.. c:namespace:: Namespace1.Namespace2.SomeStruct.AnInnerStruct
All subsequent objects will be defined as if their name were declared with
the scope prepended. The subsequent cross-references will be searched for
starting in the current scope.
Using ``NULL`` or ``0`` as the scope will change to global scope.
.. rst:directive:: .. c:namespace-push:: scope specification
Change the scope relatively to the current scope. For example, after::
.. c:namespace:: A.B
.. c:namespace-push:: C.D
the current scope will be ``A.B.C.D``.
.. rst:directive:: .. c:namespace-pop::
Undo the previous ``c:namespace-push`` directive (*not* just pop a scope).
For example, after::
.. c:namespace:: A.B
.. c:namespace-push:: C.D
.. c:namespace-pop::
the current scope will be ``A.B`` (*not* ``A.B.C``).
If no previous ``c:namespace-push`` directive has been used, but only a
``c:namespace`` directive, then the current scope will be reset to global
scope. That is, ``.. c:namespace:: A.B`` is equivalent to::
.. c:namespace:: NULL
.. c:namespace-push:: A.B
Configuration Variables
~~~~~~~~~~~~~~~~~~~~~~~
See :ref:`c-config`.
.. _cpp-domain:
@ -1530,7 +1715,7 @@ These roles are provided to refer to the described objects:
The Math Domain
---------------
The math domain (name **math**) provides the following roles::
The math domain (name **math**) provides the following roles:
.. rst:role:: math:numref

View File

@ -30,6 +30,12 @@ At the moment, these metadata fields are recognized:
:tocdepth: 2
.. note::
This metadata effects to the depth of local toctree. But it does not
effect to the depth of *global* toctree. So this would not be change
the sidebar of some themes which uses global one.
.. versionadded:: 0.4
``nocomments``
@ -45,3 +51,12 @@ At the moment, these metadata fields are recognized:
:orphan:
.. versionadded:: 1.0
``nosearch``
If set, full text search for this file is disabled. ::
:nosearch:
.. note:: object search is still available even if `nosearch` option is set.
.. versionadded:: 3.0

View File

@ -189,8 +189,8 @@ Referencing downloadable files
When you use this role, the referenced file is automatically marked for
inclusion in the output when building (obviously, for HTML output only).
All downloadable files are put into the ``_downloads`` subdirectory of the
output directory; duplicate filenames are handled.
All downloadable files are put into a ``_downloads/<unique hash>/``
subdirectory of the output directory; duplicate filenames are handled.
An example::

View File

@ -151,6 +151,25 @@ These themes are:
dimension string such as '70em' or '50%'. Use 'none' if you don't
want a width limit. Defaults may depend on the theme (often 800px).
- **navigation_with_keys** (true or false): Allow navigating to the
previous/next page using the keyboard's left and right arrows. Defaults to
``False``.
- **globaltoc_collapse** (true or false): Only expand subsections
of the current document in ``globaltoc.html``
(see :confval:`html_sidebars`).
Defaults to ``True``.
.. versionadded:: 3.1
- **globaltoc_includehidden** (true or false): Show even those
subsections in ``globaltoc.html`` (see :confval:`html_sidebars`)
which have been included with the ``:hidden:`` flag of the
:rst:dir:`toctree` directive.
Defaults to ``False``.
.. versionadded:: 3.1
**alabaster**
`Alabaster theme`_ is a modified "Kr" Sphinx theme from @kennethreitz
(especially as used in his Requests project), which was itself originally
@ -237,6 +256,8 @@ These themes are:
- **documentwidth** (CSS length): Width of the document (without sidebar),
default 50em.
- **sidebarwidth** (CSS length): Width of the sidebar, default 20em.
- **rightsidebar** (true or false): Put the sidebar on the right side.
Defaults to ``True``.
- **bgcolor** (CSS color): Background color.
- **headerbg** (CSS value for "background"): background for the header area,
default a grayish gradient.

2323
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,10 +11,10 @@
"url": "https://github.com/sphinx-doc/sphinx/issues"
},
"devDependencies": {
"jasmine-core": "^3.1.0",
"karma": "^3.0.0",
"karma-chrome-launcher": "^2.2.0",
"jasmine-core": "^3.4.0",
"karma": "^4.0.0",
"karma-chrome-launcher": "^3.0.0",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^1.1.2"
"karma-jasmine": "^2.0.0"
}
}

View File

@ -40,6 +40,8 @@ paths =
.
[mypy]
python_version = 3.5
disallow_incomplete_defs = True
show_column_numbers = True
show_error_context = True
ignore_missing_imports = True
@ -57,9 +59,11 @@ markers =
apidoc
setup_command
test_params
testpaths = tests
[coverage:run]
branch = True
parallel = True
source = sphinx
[coverage:report]

View File

@ -25,7 +25,7 @@ install_requires = [
'Pygments>=2.0',
'docutils>=0.12',
'snowballstemmer>=1.1',
'babel>=1.3,!=2.0',
'babel>=1.3',
'alabaster>=0.7,<0.8',
'imagesize',
'requests>=2.5.0',
@ -41,14 +41,18 @@ extras_require = {
'docs': [
'sphinxcontrib-websupport',
],
'lint': [
'flake8>=3.5.0',
'flake8-import-order',
'mypy>=0.770',
'docutils-stubs',
],
'test': [
'pytest',
'pytest-cov',
'html5lib',
'flake8>=3.5.0',
'flake8-import-order',
'mypy>=0.711',
'docutils-stubs',
'typed_ast', # for py35-37
'cython',
],
}
@ -176,6 +180,10 @@ setup(
description='Python documentation generator',
long_description=long_desc,
long_description_content_type='text/x-rst',
project_urls={
"Code": "https://github.com/sphinx-doc/sphinx",
"Issue tracker": "https://github.com/sphinx-doc/sphinx/issues",
},
zip_safe=False,
classifiers=[
'Development Status :: 5 - Production/Stable',
@ -216,6 +224,9 @@ setup(
],
platforms='any',
packages=find_packages(exclude=['tests', 'utils']),
package_data = {
'sphinx': ['py.typed'],
},
include_package_data=True,
entry_points={
'console_scripts': [

View File

@ -4,7 +4,7 @@
The Sphinx documentation toolchain.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -32,8 +32,8 @@ if 'PYTHONWARNINGS' not in os.environ:
warnings.filterwarnings('ignore', "'U' mode is deprecated",
DeprecationWarning, module='docutils.io')
__version__ = '3.0.0+'
__released__ = '3.0.0' # used when Sphinx builds its own docs
__version__ = '3.1.0+'
__released__ = '3.1.0' # used when Sphinx builds its own docs
#: Version info for better programmatic use.
#:
@ -43,7 +43,7 @@ __released__ = '3.0.0' # used when Sphinx builds its own docs
#:
#: .. versionadded:: 1.2
#: Before version 1.2, check the string ``sphinx.__version__``.
version_info = (3, 0, 0, 'beta', 0)
version_info = (3, 1, 0, 'beta', 0)
package_dir = path.abspath(path.dirname(__file__))
@ -56,8 +56,9 @@ if __version__.endswith('+'):
__version__ = __version__[:-1] # remove '+' for PEP-440 version spec.
try:
ret = subprocess.run(['git', 'show', '-s', '--pretty=format:%h'],
stdout=PIPE, stderr=PIPE, encoding='ascii')
cwd=package_dir,
stdout=PIPE, stderr=PIPE)
if ret.stdout:
__display_version__ += '/' + ret.stdout.strip()
__display_version__ += '/' + ret.stdout.decode('ascii').strip()
except Exception:
pass

View File

@ -4,7 +4,7 @@
The Sphinx documentation toolchain.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -4,20 +4,21 @@
Additional docutils nodes.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import warnings
from typing import Any, Dict, List, Sequence
from docutils import nodes
from docutils.nodes import Element, Node
from sphinx.deprecation import RemovedInSphinx40Warning
if False:
# For type annotation
from typing import Any, Dict, List, Sequence # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.application import Sphinx
class translatable(nodes.Node):
@ -34,18 +35,15 @@ class translatable(nodes.Node):
Because they are used at final step; extraction.
"""
def preserve_original_messages(self):
# type: () -> None
def preserve_original_messages(self) -> None:
"""Preserve original translatable messages."""
raise NotImplementedError
def apply_translated_message(self, original_message, translated_message):
# type: (str, str) -> None
def apply_translated_message(self, original_message: str, translated_message: str) -> None:
"""Apply translated message."""
raise NotImplementedError
def extract_original_messages(self):
# type: () -> Sequence[str]
def extract_original_messages(self) -> Sequence[str]:
"""Extract translation messages.
:returns: list of extracted messages or messages generator
@ -61,22 +59,37 @@ class not_smartquotable:
class toctree(nodes.General, nodes.Element, translatable):
"""Node for inserting a "TOC tree"."""
def preserve_original_messages(self):
# type: () -> None
def preserve_original_messages(self) -> None:
# toctree entries
rawentries = self.setdefault('rawentries', [])
for title, docname in self['entries']:
if title:
rawentries.append(title)
# :caption: option
if self.get('caption'):
self['rawcaption'] = self['caption']
def apply_translated_message(self, original_message, translated_message):
# type: (str, str) -> None
def apply_translated_message(self, original_message: str, translated_message: str) -> None:
# toctree entries
for i, (title, docname) in enumerate(self['entries']):
if title == original_message:
self['entries'][i] = (translated_message, docname)
# :caption: option
if self.get('rawcaption') == original_message:
self['caption'] = translated_message
def extract_original_messages(self):
# type: () -> List[str]
def extract_original_messages(self) -> List[str]:
messages = [] # type: List[str]
# toctree entries
messages.extend(self.get('rawentries', []))
# :caption: option
if 'rawcaption' in self:
return [self['rawcaption']]
else:
return []
messages.append(self['rawcaption'])
return messages
# domain-specific object descriptions (class, function etc.)
@ -106,7 +119,7 @@ class desc_signature_line(nodes.Part, nodes.Inline, nodes.FixedTextElement):
It should only be used in a ``desc_signature`` with ``is_multiline`` set.
Set ``add_permalink = True`` for the line that should get the permalink.
"""
sphinx_cpp_tagname = ''
sphinx_line_type = ''
# nodes to use within a desc_signature or desc_signature_line
@ -125,8 +138,7 @@ class desc_type(nodes.Part, nodes.Inline, nodes.FixedTextElement):
class desc_returns(desc_type):
"""Node for a "returns" annotation (a la -> in Python)."""
def astext(self):
# type: () -> str
def astext(self) -> str:
return ' -> ' + super().astext()
@ -147,8 +159,7 @@ class desc_optional(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for marking optional parts of the parameter list."""
child_text_separator = ', '
def astext(self):
# type: () -> str
def astext(self) -> str:
return '[' + super().astext() + ']'
@ -163,6 +174,31 @@ class desc_content(nodes.General, nodes.Element):
"""
class desc_sig_element(nodes.inline):
"""Common parent class of nodes for inline text of a signature."""
classes = [] # type: List[str]
def __init__(self, rawsource: str = '', text: str = '',
*children: Element, **attributes: Any) -> None:
super().__init__(rawsource, text, *children, **attributes)
self['classes'].extend(self.classes)
class desc_sig_name(desc_sig_element):
"""Node for a name in a signature."""
classes = ["n"]
class desc_sig_operator(desc_sig_element):
"""Node for an operator in a signature."""
classes = ["o"]
class desc_sig_punctuation(desc_sig_element):
"""Node for a punctuation in a signature."""
classes = ["p"]
# new admonition-like constructs
class versionmodified(nodes.Admonition, nodes.TextElement):
@ -295,8 +331,8 @@ class abbreviation(nodes.abbreviation):
.. deprecated:: 2.0
"""
def __init__(self, rawsource='', text='', *children, **attributes):
# type: (str, str, *nodes.Node, **Any) -> None
def __init__(self, rawsource: str = '', text: str = '',
*children: Node, **attributes: Any) -> None:
warnings.warn("abbrevition node for Sphinx was replaced by docutils'.",
RemovedInSphinx40Warning, stacklevel=2)
@ -307,8 +343,7 @@ class manpage(nodes.Inline, nodes.FixedTextElement):
"""Node for references to manpages."""
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_node(toctree)
app.add_node(desc)
app.add_node(desc_signature)
@ -322,6 +357,9 @@ def setup(app):
app.add_node(desc_optional)
app.add_node(desc_annotation)
app.add_node(desc_content)
app.add_node(desc_sig_name)
app.add_node(desc_sig_operator)
app.add_node(desc_sig_punctuation)
app.add_node(versionmodified)
app.add_node(seealso)
app.add_node(productionlist)

View File

@ -6,32 +6,42 @@
Gracefully adapted from the TextPress system by Armin.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os
import pickle
import platform
import sys
import warnings
from collections import deque
from io import StringIO
from os import path
from typing import Any, Callable, Dict, IO, List, Tuple, Union
from docutils import nodes
from docutils.nodes import Element, TextElement
from docutils.parsers.rst import Directive, roles
from docutils.transforms import Transform
from pygments.lexer import Lexer
import sphinx
from sphinx import package_dir, locale
from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.domains import Domain, Index
from sphinx.environment import BuildEnvironment
from sphinx.environment.collectors import EnvironmentCollector
from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError
from sphinx.events import EventManager
from sphinx.extension import Extension
from sphinx.highlighting import lexer_classes, lexers
from sphinx.locale import __
from sphinx.project import Project
from sphinx.registry import SphinxComponentRegistry
from sphinx.roles import XRefRole
from sphinx.theming import Theme
from sphinx.util import docutils
from sphinx.util import logging
from sphinx.util import progress_message
@ -41,20 +51,14 @@ from sphinx.util.i18n import CatalogRepository
from sphinx.util.logging import prefixed_warnings
from sphinx.util.osutil import abspath, ensuredir, relpath
from sphinx.util.tags import Tags
from sphinx.util.typing import RoleFunction, TitleGetter
if False:
# For type annotation
from typing import Any, Callable, Dict, IO, Iterable, Iterator, List, Tuple, Type, Union # NOQA
from docutils import nodes # NOQA
from docutils.parsers import Parser # NOQA
from docutils.transforms import Transform # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.domains import Domain, Index # NOQA
from sphinx.environment.collectors import EnvironmentCollector # NOQA
from sphinx.extension import Extension # NOQA
from sphinx.roles import XRefRole # NOQA
from sphinx.theming import Theme # NOQA
from sphinx.util.typing import RoleFunction, TitleGetter # NOQA
from docutils.nodes import Node # NOQA
from typing import Type # for python3.5.1
from sphinx.builders import Builder
builtin_extensions = (
'sphinx.addnodes',
@ -76,6 +80,7 @@ builtin_extensions = (
'sphinx.domains.changeset',
'sphinx.domains.citation',
'sphinx.domains.cpp',
'sphinx.domains.index',
'sphinx.domains.javascript',
'sphinx.domains.math',
'sphinx.domains.python',
@ -104,7 +109,6 @@ builtin_extensions = (
'sphinx.environment.collectors.metadata',
'sphinx.environment.collectors.title',
'sphinx.environment.collectors.toctree',
'sphinx.environment.collectors.indexentries',
# 1st party extensions
'sphinxcontrib.applehelp',
'sphinxcontrib.devhelp',
@ -130,11 +134,11 @@ class Sphinx:
:ivar outdir: Directory for storing build documents.
"""
def __init__(self, srcdir, confdir, outdir, doctreedir, buildername,
confoverrides=None, status=sys.stdout, warning=sys.stderr,
freshenv=False, warningiserror=False, tags=None, verbosity=0,
parallel=0, keep_going=False):
# type: (str, str, str, str, str, Dict, IO, IO, bool, bool, List[str], int, int, bool) -> None # NOQA
def __init__(self, srcdir: str, confdir: str, outdir: str, doctreedir: str,
buildername: str, confoverrides: Dict = None,
status: IO = sys.stdout, warning: IO = sys.stderr,
freshenv: bool = False, warningiserror: bool = False, tags: List[str] = None,
verbosity: int = 0, parallel: int = 0, keep_going: bool = False) -> None:
self.phase = BuildPhase.INITIALIZATION
self.verbosity = verbosity
self.extensions = {} # type: Dict[str, Extension]
@ -159,6 +163,10 @@ class Sphinx:
raise ApplicationError(__('Cannot find source directory (%s)') %
self.srcdir)
if path.exists(self.outdir) and not path.isdir(self.outdir):
raise ApplicationError(__('Output directory (%s) is not a directory') %
self.srcdir)
if self.srcdir == self.outdir:
raise ApplicationError(__('Source directory and destination '
'directory cannot be identical'))
@ -193,6 +201,12 @@ class Sphinx:
# say hello to the world
logger.info(bold(__('Running Sphinx v%s') % sphinx.__display_version__))
# notice for parallel build on macOS and py38+
if sys.version_info > (3, 8) and platform.system() == 'Darwin' and parallel > 1:
logger.info(bold(__("For security reason, parallel mode is disabled on macOS and "
"python3.8 and above. For more details, please read "
"https://github.com/sphinx-doc/sphinx/issues/6803")))
# status code for command-line application
self.statuscode = 0
@ -262,8 +276,7 @@ class Sphinx:
# set up the builder
self._init_builder()
def _init_i18n(self):
# type: () -> None
def _init_i18n(self) -> None:
"""Load translated strings from the configured localedirs if enabled in
the configuration.
"""
@ -288,8 +301,7 @@ class Sphinx:
else:
logger.info(__('not available for built-in messages'))
def _init_env(self, freshenv):
# type: (bool) -> None
def _init_env(self, freshenv: bool) -> None:
filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
if freshenv or not os.path.exists(filename):
self.env = BuildEnvironment()
@ -305,28 +317,24 @@ class Sphinx:
logger.info(__('failed: %s'), err)
self._init_env(freshenv=True)
def preload_builder(self, name):
# type: (str) -> None
def preload_builder(self, name: str) -> None:
self.registry.preload_builder(self, name)
def create_builder(self, name):
# type: (str) -> Builder
def create_builder(self, name: str) -> "Builder":
if name is None:
logger.info(__('No builder selected, using default: html'))
name = 'html'
return self.registry.create_builder(self, name)
def _init_builder(self):
# type: () -> None
def _init_builder(self) -> None:
self.builder.set_environment(self.env)
self.builder.init()
self.events.emit('builder-inited')
# ---- main "build" method -------------------------------------------------
def build(self, force_all=False, filenames=None):
# type: (bool, List[str]) -> None
def build(self, force_all: bool = False, filenames: List[str] = None) -> None:
self.phase = BuildPhase.READING
try:
if force_all:
@ -342,17 +350,19 @@ class Sphinx:
if self._warncount and self.keep_going:
self.statuscode = 1
status = (self.statuscode == 0 and
__('succeeded') or __('finished with problems'))
status = (__('succeeded') if self.statuscode == 0
else __('finished with problems'))
if self._warncount:
if self.warningiserror:
msg = __('build %s, %s warning (with warnings treated as errors).',
'build %s, %s warnings (with warnings treated as errors).',
self._warncount)
if self._warncount == 1:
msg = __('build %s, %s warning (with warnings treated as errors).')
else:
msg = __('build %s, %s warnings (with warnings treated as errors).')
else:
msg = __('build %s, %s warning.',
'build %s, %s warnings.',
self._warncount)
if self._warncount == 1:
msg = __('build %s, %s warning.')
else:
msg = __('build %s, %s warnings.')
logger.info(bold(msg % (status, self._warncount)))
else:
@ -377,8 +387,7 @@ class Sphinx:
# ---- general extensibility interface -------------------------------------
def setup_extension(self, extname):
# type: (str) -> None
def setup_extension(self, extname: str) -> None:
"""Import and setup a Sphinx extension module.
Load the extension given by the module *name*. Use this if your
@ -388,8 +397,7 @@ class Sphinx:
logger.debug('[app] setting up extension: %r', extname)
self.registry.load_extension(self, extname)
def require_sphinx(self, version):
# type: (str) -> None
def require_sphinx(self, version: str) -> None:
"""Check the Sphinx version if requested.
Compare *version* (which must be a ``major.minor`` version string, e.g.
@ -402,28 +410,33 @@ class Sphinx:
raise VersionRequirementError(version)
# event interface
def connect(self, event, callback):
# type: (str, Callable) -> int
def connect(self, event: str, callback: Callable, priority: int = 500) -> int:
"""Register *callback* to be called when *event* is emitted.
For details on available core events and the arguments of callback
functions, please see :ref:`events`.
Registered callbacks will be invoked on event in the order of *priority* and
registration. The priority is ascending order.
The method returns a "listener ID" that can be used as an argument to
:meth:`disconnect`.
.. versionchanged:: 3.0
Support *priority*
"""
listener_id = self.events.connect(event, callback)
logger.debug('[app] connecting event %r: %r [id=%s]', event, callback, listener_id)
listener_id = self.events.connect(event, callback, priority)
logger.debug('[app] connecting event %r (%d): %r [id=%s]',
event, priority, callback, listener_id)
return listener_id
def disconnect(self, listener_id):
# type: (int) -> None
def disconnect(self, listener_id: int) -> None:
"""Unregister callback by *listener_id*."""
logger.debug('[app] disconnecting event: [id=%s]', listener_id)
self.events.disconnect(listener_id)
def emit(self, event, *args):
# type: (str, Any) -> List
def emit(self, event: str, *args: Any) -> List:
"""Emit *event* and pass *arguments* to the callback functions.
Return the return values of all callbacks as a list. Do not emit core
@ -431,8 +444,7 @@ class Sphinx:
"""
return self.events.emit(event, *args)
def emit_firstresult(self, event, *args):
# type: (str, Any) -> Any
def emit_firstresult(self, event: str, *args: Any) -> Any:
"""Emit *event* and pass *arguments* to the callback functions.
Return the result of the first callback that doesn't return ``None``.
@ -443,8 +455,7 @@ class Sphinx:
# registering addon parts
def add_builder(self, builder, override=False):
# type: (Type[Builder], bool) -> None
def add_builder(self, builder: "Type[Builder]", override: bool = False) -> None:
"""Register a new builder.
*builder* must be a class that inherits from
@ -456,8 +467,8 @@ class Sphinx:
self.registry.add_builder(builder, override=override)
# TODO(stephenfin): Describe 'types' parameter
def add_config_value(self, name, default, rebuild, types=()):
# type: (str, Any, Union[bool, str], Any) -> None
def add_config_value(self, name: str, default: Any, rebuild: Union[bool, str],
types: Any = ()) -> None:
"""Register a configuration value.
This is necessary for Sphinx to recognize new values and set default
@ -484,13 +495,12 @@ class Sphinx:
other values.
"""
logger.debug('[app] adding config value: %r',
(name, default, rebuild) + ((types,) if types else ())) # type: ignore
(name, default, rebuild) + ((types,) if types else ()))
if rebuild in (False, True):
rebuild = rebuild and 'env' or ''
rebuild = 'env' if rebuild else ''
self.config.add(name, default, rebuild, types)
def add_event(self, name):
# type: (str) -> None
def add_event(self, name: str) -> None:
"""Register an event called *name*.
This is needed to be able to emit it.
@ -498,8 +508,8 @@ class Sphinx:
logger.debug('[app] adding event: %r', name)
self.events.add(name)
def set_translator(self, name, translator_class, override=False):
# type: (str, Type[nodes.NodeVisitor], bool) -> None
def set_translator(self, name: str, translator_class: "Type[nodes.NodeVisitor]",
override: bool = False) -> None:
"""Register or override a Docutils translator class.
This is used to register a custom output translator or to replace a
@ -512,8 +522,8 @@ class Sphinx:
"""
self.registry.add_translator(name, translator_class, override=override)
def add_node(self, node, override=False, **kwds):
# type: (Type[nodes.Element], bool, Any) -> None
def add_node(self, node: "Type[Element]", override: bool = False,
**kwargs: Tuple[Callable, Callable]) -> None:
"""Register a Docutils node class.
This is necessary for Docutils internals. It may also be used in the
@ -543,16 +553,17 @@ class Sphinx:
.. versionchanged:: 0.5
Added the support for keyword arguments giving visit functions.
"""
logger.debug('[app] adding node: %r', (node, kwds))
logger.debug('[app] adding node: %r', (node, kwargs))
if not override and docutils.is_node_registered(node):
logger.warning(__('node class %r is already registered, '
'its visitors will be overridden'),
node.__name__, type='app', subtype='add_node')
docutils.register_node(node)
self.registry.add_translation_handlers(node, **kwds)
self.registry.add_translation_handlers(node, **kwargs)
def add_enumerable_node(self, node, figtype, title_getter=None, override=False, **kwds):
# type: (Type[nodes.Element], str, TitleGetter, bool, Any) -> None
def add_enumerable_node(self, node: "Type[Element]", figtype: str,
title_getter: TitleGetter = None, override: bool = False,
**kwargs: Tuple[Callable, Callable]) -> None:
"""Register a Docutils node class as a numfig target.
Sphinx numbers the node automatically. And then the users can refer it
@ -577,10 +588,9 @@ class Sphinx:
.. versionadded:: 1.4
"""
self.registry.add_enumerable_node(node, figtype, title_getter, override=override)
self.add_node(node, override=override, **kwds)
self.add_node(node, override=override, **kwargs)
def add_directive(self, name, cls, override=False):
# type: (str, Type[Directive], bool) -> None
def add_directive(self, name: str, cls: "Type[Directive]", override: bool = False) -> None:
"""Register a Docutils directive.
*name* must be the prospective directive name. *cls* is a directive
@ -624,8 +634,7 @@ class Sphinx:
docutils.register_directive(name, cls)
def add_role(self, name, role, override=False):
# type: (str, Any, bool) -> None
def add_role(self, name: str, role: Any, override: bool = False) -> None:
"""Register a Docutils role.
*name* must be the role name that occurs in the source, *role* the role
@ -642,8 +651,7 @@ class Sphinx:
name, type='app', subtype='add_role')
docutils.register_role(name, role)
def add_generic_role(self, name, nodeclass, override=False):
# type: (str, Any, bool) -> None
def add_generic_role(self, name: str, nodeclass: Any, override: bool = False) -> None:
"""Register a generic Docutils role.
Register a Docutils role that does nothing but wrap its contents in the
@ -662,8 +670,7 @@ class Sphinx:
role = roles.GenericRole(name, nodeclass)
docutils.register_role(name, role)
def add_domain(self, domain, override=False):
# type: (Type[Domain], bool) -> None
def add_domain(self, domain: "Type[Domain]", override: bool = False) -> None:
"""Register a domain.
Make the given *domain* (which must be a class; more precisely, a
@ -675,8 +682,8 @@ class Sphinx:
"""
self.registry.add_domain(domain, override=override)
def add_directive_to_domain(self, domain, name, cls, override=False):
# type: (str, str, Type[Directive], bool) -> None
def add_directive_to_domain(self, domain: str, name: str,
cls: "Type[Directive]", override: bool = False) -> None:
"""Register a Docutils directive in a domain.
Like :meth:`add_directive`, but the directive is added to the domain
@ -688,8 +695,8 @@ class Sphinx:
"""
self.registry.add_directive_to_domain(domain, name, cls, override=override)
def add_role_to_domain(self, domain, name, role, override=False):
# type: (str, str, Union[RoleFunction, XRefRole], bool) -> None
def add_role_to_domain(self, domain: str, name: str, role: Union[RoleFunction, XRefRole],
override: bool = False) -> None:
"""Register a Docutils role in a domain.
Like :meth:`add_role`, but the role is added to the domain named
@ -701,8 +708,8 @@ class Sphinx:
"""
self.registry.add_role_to_domain(domain, name, role, override=override)
def add_index_to_domain(self, domain, index, override=False):
# type: (str, Type[Index], bool) -> None
def add_index_to_domain(self, domain: str, index: "Type[Index]", override: bool = False
) -> None:
"""Register a custom index for a domain.
Add a custom *index* class to the domain named *domain*. *index* must
@ -714,10 +721,10 @@ class Sphinx:
"""
self.registry.add_index_to_domain(domain, index)
def add_object_type(self, directivename, rolename, indextemplate='',
parse_node=None, ref_nodeclass=None, objname='',
doc_field_types=[], override=False):
# type: (str, str, str, Callable, Type[nodes.TextElement], str, List, bool) -> None
def add_object_type(self, directivename: str, rolename: str, indextemplate: str = '',
parse_node: Callable = None, ref_nodeclass: "Type[TextElement]" = None,
objname: str = '', doc_field_types: List = [], override: bool = False
) -> None:
"""Register a new object type.
This method is a very convenient way to add a new :term:`object` type
@ -778,9 +785,9 @@ class Sphinx:
ref_nodeclass, objname, doc_field_types,
override=override)
def add_crossref_type(self, directivename, rolename, indextemplate='',
ref_nodeclass=None, objname='', override=False):
# type: (str, str, str, Type[nodes.TextElement], str, bool) -> None
def add_crossref_type(self, directivename: str, rolename: str, indextemplate: str = '',
ref_nodeclass: "Type[TextElement]" = None, objname: str = '',
override: bool = False) -> None:
"""Register a new crossref object type.
This method is very similar to :meth:`add_object_type` except that the
@ -814,8 +821,7 @@ class Sphinx:
indextemplate, ref_nodeclass, objname,
override=override)
def add_transform(self, transform):
# type: (Type[Transform]) -> None
def add_transform(self, transform: "Type[Transform]") -> None:
"""Register a Docutils transform to be applied after parsing.
Add the standard docutils :class:`Transform` subclass *transform* to
@ -848,8 +854,7 @@ class Sphinx:
""" # NOQA
self.registry.add_transform(transform)
def add_post_transform(self, transform):
# type: (Type[Transform]) -> None
def add_post_transform(self, transform: "Type[Transform]") -> None:
"""Register a Docutils transform to be applied before writing.
Add the standard docutils :class:`Transform` subclass *transform* to
@ -858,22 +863,22 @@ class Sphinx:
"""
self.registry.add_post_transform(transform)
def add_javascript(self, filename, **kwargs):
# type: (str, **str) -> None
def add_javascript(self, filename: str, **kwargs: str) -> None:
"""An alias of :meth:`add_js_file`."""
warnings.warn('The app.add_javascript() is deprecated. '
'Please use app.add_js_file() instead.',
RemovedInSphinx40Warning, stacklevel=2)
self.add_js_file(filename, **kwargs)
def add_js_file(self, filename, **kwargs):
# type: (str, **str) -> None
def add_js_file(self, filename: str, **kwargs: str) -> None:
"""Register a JavaScript file to include in the HTML output.
Add *filename* to the list of JavaScript files that the default HTML
template will include. The filename must be relative to the HTML
static path , or a full URI with scheme. The keyword arguments are
also accepted for attributes of ``<script>`` tag.
static path , or a full URI with scheme. If the keyword argument
``body`` is given, its value will be added between the
``<script>`` tags. Extra keyword arguments are included as
attributes of the ``<script>`` tag.
Example::
@ -883,6 +888,9 @@ class Sphinx:
app.add_js_file('example.js', async="async")
# => <script src="_static/example.js" async="async"></script>
app.add_js_file(None, body="var myVariable = 'foo';")
# => <script>var myVariable = 'foo';</script>
.. versionadded:: 0.5
.. versionchanged:: 1.8
@ -893,8 +901,7 @@ class Sphinx:
if hasattr(self.builder, 'add_js_file'):
self.builder.add_js_file(filename, **kwargs) # type: ignore
def add_css_file(self, filename, **kwargs):
# type: (str, **str) -> None
def add_css_file(self, filename: str, **kwargs: str) -> None:
"""Register a stylesheet to include in the HTML output.
Add *filename* to the list of CSS files that the default HTML template
@ -933,8 +940,8 @@ class Sphinx:
if hasattr(self.builder, 'add_css_file'):
self.builder.add_css_file(filename, **kwargs) # type: ignore
def add_stylesheet(self, filename, alternate=False, title=None):
# type: (str, bool, str) -> None
def add_stylesheet(self, filename: str, alternate: bool = False, title: str = None
) -> None:
"""An alias of :meth:`add_css_file`."""
warnings.warn('The app.add_stylesheet() is deprecated. '
'Please use app.add_css_file() instead.',
@ -951,8 +958,7 @@ class Sphinx:
self.add_css_file(filename, **attributes)
def add_latex_package(self, packagename, options=None):
# type: (str, str) -> None
def add_latex_package(self, packagename: str, options: str = None) -> None:
r"""Register a package to include in the LaTeX source code.
Add *packagename* to the list of packages that LaTeX source code will
@ -970,8 +976,7 @@ class Sphinx:
"""
self.registry.add_latex_package(packagename, options)
def add_lexer(self, alias, lexer):
# type: (str, Union[Lexer, Type[Lexer]]) -> None
def add_lexer(self, alias: str, lexer: Union[Lexer, "Type[Lexer]"]) -> None:
"""Register a new lexer for source code.
Use *lexer* to highlight code blocks with the given language *alias*.
@ -990,8 +995,7 @@ class Sphinx:
else:
lexer_classes[alias] = lexer
def add_autodocumenter(self, cls, override=False):
# type: (Any, bool) -> None
def add_autodocumenter(self, cls: Any, override: bool = False) -> None:
"""Register a new documenter class for the autodoc extension.
Add *cls* as a new documenter class for the :mod:`sphinx.ext.autodoc`
@ -1011,8 +1015,8 @@ class Sphinx:
self.registry.add_documenter(cls.objtype, cls)
self.add_directive('auto' + cls.objtype, AutodocDirective, override=override)
def add_autodoc_attrgetter(self, typ, getter):
# type: (Type, Callable[[Any, str, Any], Any]) -> None
def add_autodoc_attrgetter(self, typ: "Type", getter: Callable[[Any, str, Any], Any]
) -> None:
"""Register a new ``getattr``-like function for the autodoc extension.
Add *getter*, which must be a function with an interface compatible to
@ -1026,8 +1030,7 @@ class Sphinx:
logger.debug('[app] adding autodoc attrgetter: %r', (typ, getter))
self.registry.add_autodoc_attrgetter(typ, getter)
def add_search_language(self, cls):
# type: (Any) -> None
def add_search_language(self, cls: Any) -> None:
"""Register a new language for the HTML search index.
Add *cls*, which must be a subclass of
@ -1043,8 +1046,7 @@ class Sphinx:
assert issubclass(cls, SearchLanguage)
languages[cls.lang] = cls
def add_source_suffix(self, suffix, filetype, override=False):
# type: (str, str, bool) -> None
def add_source_suffix(self, suffix: str, filetype: str, override: bool = False) -> None:
"""Register a suffix of source files.
Same as :confval:`source_suffix`. The users can override this
@ -1054,8 +1056,7 @@ class Sphinx:
"""
self.registry.add_source_suffix(suffix, filetype, override=override)
def add_source_parser(self, *args, **kwargs):
# type: (Any, Any) -> None
def add_source_parser(self, *args: Any, **kwargs: Any) -> None:
"""Register a parser class.
.. versionadded:: 1.4
@ -1067,8 +1068,7 @@ class Sphinx:
"""
self.registry.add_source_parser(*args, **kwargs)
def add_env_collector(self, collector):
# type: (Type[EnvironmentCollector]) -> None
def add_env_collector(self, collector: "Type[EnvironmentCollector]") -> None:
"""Register an environment collector class.
Refer to :ref:`collector-api`.
@ -1078,8 +1078,7 @@ class Sphinx:
logger.debug('[app] adding environment collector: %r', collector)
collector().enable(self)
def add_html_theme(self, name, theme_path):
# type: (str, str) -> None
def add_html_theme(self, name: str, theme_path: str) -> None:
"""Register a HTML Theme.
The *name* is a name of theme, and *path* is a full path to the theme
@ -1090,8 +1089,9 @@ class Sphinx:
logger.debug('[app] adding HTML theme: %r, %r', name, theme_path)
self.html_themes[name] = theme_path
def add_html_math_renderer(self, name, inline_renderers=None, block_renderers=None):
# type: (str, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
def add_html_math_renderer(self, name: str,
inline_renderers: Tuple[Callable, Callable] = None,
block_renderers: Tuple[Callable, Callable] = None) -> None:
"""Register a math renderer for HTML.
The *name* is a name of math renderer. Both *inline_renderers* and
@ -1105,8 +1105,7 @@ class Sphinx:
"""
self.registry.add_html_math_renderer(name, inline_renderers, block_renderers)
def add_message_catalog(self, catalog, locale_dir):
# type: (str, str) -> None
def add_message_catalog(self, catalog: str, locale_dir: str) -> None:
"""Register a message catalog.
The *catalog* is a name of catalog, and *locale_dir* is a base path
@ -1119,34 +1118,37 @@ class Sphinx:
locale.init_console(locale_dir, catalog)
# ---- other methods -------------------------------------------------
def is_parallel_allowed(self, typ):
# type: (str) -> bool
def is_parallel_allowed(self, typ: str) -> bool:
"""Check parallel processing is allowed or not.
``typ`` is a type of processing; ``'read'`` or ``'write'``.
"""
if typ == 'read':
attrname = 'parallel_read_safe'
message = __("the %s extension does not declare if it is safe "
"for parallel reading, assuming it isn't - please "
"ask the extension author to check and make it "
"explicit")
message_not_declared = __("the %s extension does not declare if it "
"is safe for parallel reading, assuming "
"it isn't - please ask the extension author "
"to check and make it explicit")
message_not_safe = __("the %s extension is not safe for parallel reading")
elif typ == 'write':
attrname = 'parallel_write_safe'
message = __("the %s extension does not declare if it is safe "
"for parallel writing, assuming it isn't - please "
"ask the extension author to check and make it "
"explicit")
message_not_declared = __("the %s extension does not declare if it "
"is safe for parallel writing, assuming "
"it isn't - please ask the extension author "
"to check and make it explicit")
message_not_safe = __("the %s extension is not safe for parallel writing")
else:
raise ValueError('parallel type %s is not supported' % typ)
for ext in self.extensions.values():
allowed = getattr(ext, attrname, None)
if allowed is None:
logger.warning(message, ext.name)
logger.warning(message_not_declared, ext.name)
logger.warning(__('doing serial %s'), typ)
return False
elif not allowed:
logger.warning(message_not_safe, ext.name)
logger.warning(__('doing serial %s'), typ)
return False
return True
@ -1158,8 +1160,7 @@ class TemplateBridge:
that renders templates given a template name and a context.
"""
def init(self, builder, theme=None, dirs=None):
# type: (Builder, Theme, List[str]) -> None
def init(self, builder: "Builder", theme: Theme = None, dirs: List[str] = None) -> None:
"""Called by the builder to initialize the template system.
*builder* is the builder object; you'll probably want to look at the
@ -1170,23 +1171,20 @@ class TemplateBridge:
"""
raise NotImplementedError('must be implemented in subclasses')
def newest_template_mtime(self):
# type: () -> float
def newest_template_mtime(self) -> float:
"""Called by the builder to determine if output files are outdated
because of template changes. Return the mtime of the newest template
file that was changed. The default implementation returns ``0``.
"""
return 0
def render(self, template, context):
# type: (str, Dict) -> None
def render(self, template: str, context: Dict) -> None:
"""Called by the builder to render a template given as a filename with
a specified context (a Python dictionary).
"""
raise NotImplementedError('must be implemented in subclasses')
def render_string(self, template, context):
# type: (str, Dict) -> str
def render_string(self, template: str, context: Dict) -> str:
"""Called by the builder to render a template given as a string with a
specified context (a Python dictionary).
"""

View File

@ -4,14 +4,14 @@
Builder superclass for all builders.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import pickle
import time
from os import path
from typing import Any, Dict, Iterable, List, Sequence, Set, Tuple, Type, Union
from typing import Any, Dict, Iterable, List, Sequence, Set, Tuple, Union
from docutils import nodes
from docutils.nodes import Node
@ -44,6 +44,7 @@ except ImportError:
if False:
# For type annotation
from typing import Type # for python3.5.1
from sphinx.application import Sphinx
@ -117,11 +118,11 @@ class Builder:
self.env.set_versioning_method(self.versioning_method,
self.versioning_compare)
def get_translator_class(self, *args) -> Type[nodes.NodeVisitor]:
def get_translator_class(self, *args: Any) -> "Type[nodes.NodeVisitor]":
"""Return a class of translator."""
return self.app.registry.get_translator_class(self)
def create_translator(self, *args) -> nodes.NodeVisitor:
def create_translator(self, *args: Any) -> nodes.NodeVisitor:
"""Return an instance of translator.
This method returns an instance of ``default_translator_class`` by default.
@ -303,7 +304,7 @@ class Builder:
First updates the environment, and then calls :meth:`write`.
"""
if summary:
logger.info(bold(__('building [%s]') % self.name) + ': ' + summary)
logger.info(bold(__('building [%s]: ') % self.name) + summary)
# while reading, collect all warnings from docutils
with logging.pending_warnings():
@ -378,7 +379,7 @@ class Builder:
added, changed, removed = self.env.get_outdated_files(updated)
# allow user intervention as well
for docs in self.events.emit('env-get-outdated', self, added, changed, removed):
for docs in self.events.emit('env-get-outdated', self.env, added, changed, removed):
changed.update(set(docs) & self.env.found_docs)
# if files were added or removed, all documents with globbed toctrees
@ -387,9 +388,11 @@ class Builder:
# ... but not those that already were removed
changed.update(self.env.glob_toctrees & self.env.found_docs)
if changed:
reason = CONFIG_CHANGED_REASON.get(self.env.config_status, '')
if updated: # explain the change iff build config status was not ok
reason = (CONFIG_CHANGED_REASON.get(self.env.config_status, '') +
(self.env.config_status_extra or ''))
logger.info('[%s] ', reason, nonl=True)
logger.info(__('%s added, %s changed, %s removed'),
len(added), len(changed), len(removed))

View File

@ -4,7 +4,7 @@
Base class of epub2/epub3 builders.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -259,6 +259,15 @@ class EpubBuilder(StandaloneHTMLBuilder):
Some readers crash because they interpret the part as a
transport protocol specification.
"""
def update_node_id(node: Element) -> None:
"""Update IDs of given *node*."""
new_ids = []
for node_id in node['ids']:
new_id = self.fix_fragment('', node_id)
if new_id not in new_ids:
new_ids.append(new_id)
node['ids'] = new_ids
for reference in tree.traverse(nodes.reference):
if 'refuri' in reference:
m = self.refuri_re.match(reference['refuri'])
@ -268,22 +277,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
reference['refid'] = self.fix_fragment('', reference['refid'])
for target in tree.traverse(nodes.target):
for i, node_id in enumerate(target['ids']):
if ':' in node_id:
target['ids'][i] = self.fix_fragment('', node_id)
update_node_id(target)
next_node = target.next_node(siblings=True) # type: Node
next_node = target.next_node(ascend=True) # type: Node
if isinstance(next_node, nodes.Element):
for i, node_id in enumerate(next_node['ids']):
if ':' in node_id:
next_node['ids'][i] = self.fix_fragment('', node_id)
update_node_id(next_node)
for desc_signature in tree.traverse(addnodes.desc_signature):
ids = desc_signature.attributes['ids']
newids = []
for id in ids:
newids.append(self.fix_fragment('', id))
desc_signature.attributes['ids'] = newids
update_node_id(desc_signature)
def add_visible_links(self, tree: nodes.document, show_urls: str = 'inline') -> None:
"""Add visible link targets for external links"""

View File

@ -4,7 +4,7 @@
Build Apple help books.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -4,7 +4,7 @@
Changelog builder.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -50,7 +50,7 @@ class ChangesBuilder(Builder):
'deprecated': 'deprecated',
}
def write(self, *ignored) -> None:
def write(self, *ignored: Any) -> None:
version = self.config.version
domain = cast(ChangeSetDomain, self.env.get_domain('changeset'))
libchanges = {} # type: Dict[str, List[Tuple[str, str, int]]]

View File

@ -6,7 +6,7 @@
.. _Devhelp: https://wiki.gnome.org/Apps/Devhelp
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -4,12 +4,12 @@
Directory HTML builders.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from os import path
from typing import Any, Dict, Set
from typing import Any, Dict
from sphinx.application import Sphinx
from sphinx.builders.html import StandaloneHTMLBuilder
@ -45,10 +45,6 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
return outfilename
def prepare_writing(self, docnames: Set[str]) -> None:
super().prepare_writing(docnames)
self.globalcontext['no_search_suffix'] = True
# for compatibility
deprecated_alias('sphinx.builders.html',

View File

@ -282,7 +282,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
ENUM('horizontal', 'vertical'))
# event handlers
app.connect('config-inited', convert_epub_css_files)
app.connect('config-inited', convert_epub_css_files, priority=800)
app.connect('builder-inited', validate_config_values)
return {

View File

@ -4,23 +4,23 @@
The MessageCatalogBuilder class.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from codecs import open
from collections import defaultdict, OrderedDict
from datetime import datetime, tzinfo, timedelta
from io import StringIO
from os import path, walk, getenv
from time import time
from typing import Any, DefaultDict, Dict, Iterable, List, Set, Tuple, Union
from typing import Any, Dict, Iterable, Generator, List, Set, Tuple, Union
from uuid import uuid4
from docutils import nodes
from docutils.nodes import Element
from sphinx import addnodes
from sphinx import package_dir
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.domains.python import pairindextypes
@ -30,9 +30,13 @@ from sphinx.util import split_index_msg, logging, status_iterator
from sphinx.util.console import bold # type: ignore
from sphinx.util.i18n import CatalogInfo, docname_to_domain
from sphinx.util.nodes import extract_messages, traverse_translatable_index
from sphinx.util.osutil import relpath, ensuredir, canon_path
from sphinx.util.osutil import ensuredir, canon_path, relpath
from sphinx.util.tags import Tags
from sphinx.util.template import SphinxRenderer
if False:
# For type annotation
from typing import DefaultDict # for python3.5.1
logger = logging.getLogger(__name__)
@ -55,7 +59,15 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"""[1:]
"""[1:] # RemovedInSphinx40Warning
class Message:
"""An entry of translatable message."""
def __init__(self, text: str, locations: List[Tuple[str, int]], uuids: List[str]):
self.text = text
self.locations = locations
self.uuids = uuids
class Catalog:
@ -77,6 +89,12 @@ class Catalog:
self.metadata[msg] = []
self.metadata[msg].append((origin.source, origin.line, origin.uid)) # type: ignore
def __iter__(self) -> Generator[Message, None, None]:
for message in self.messages:
positions = [(source, line) for source, line, uuid in self.metadata[message]]
uuids = [uuid for source, line, uuid in self.metadata[message]]
yield Message(message, positions, uuids)
class MsgOrigin:
"""
@ -89,6 +107,30 @@ class MsgOrigin:
self.uid = uuid4().hex
class GettextRenderer(SphinxRenderer):
def __init__(self, template_path: str = None, outdir: str = None) -> None:
self.outdir = outdir
if template_path is None:
template_path = path.join(package_dir, 'templates', 'gettext')
super().__init__(template_path)
def escape(s: str) -> str:
s = s.replace('\\', r'\\')
s = s.replace('"', r'\"')
return s.replace('\n', '\\n"\n"')
# use texescape as escape filter
self.env.filters['e'] = escape
self.env.filters['escape'] = escape
def render(self, filename: str, context: Dict) -> str:
def _relpath(s: str) -> str:
return canon_path(relpath(s, self.outdir))
context['relpath'] = _relpath
return super().render(filename, context)
class I18nTags(Tags):
"""Dummy tags module for I18nBuilder.
@ -164,8 +206,8 @@ if source_date_epoch is not None:
class LocalTimeZone(tzinfo):
def __init__(self, *args, **kw) -> None:
super().__init__(*args, **kw) # type: ignore
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs) # type: ignore
self.tzdelta = tzdelta
def utcoffset(self, dt: datetime) -> timedelta:
@ -178,7 +220,7 @@ class LocalTimeZone(tzinfo):
ltz = LocalTimeZone()
def should_write(filepath: str, new_content: str):
def should_write(filepath: str, new_content: str) -> bool:
if not path.exists(filepath):
return True
try:
@ -244,12 +286,15 @@ class MessageCatalogBuilder(I18nBuilder):
def finish(self) -> None:
super().finish()
data = {
context = {
'version': self.config.version,
'copyright': self.config.copyright,
'project': self.config.project,
'ctime': datetime.fromtimestamp(
timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
'last_translator': self.config.gettext_last_translator,
'language_team': self.config.gettext_language_team,
'ctime': datetime.fromtimestamp(timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
'display_location': self.config.gettext_location,
'display_uuid': self.config.gettext_uuid,
}
for textdomain, catalog in status_iterator(self.catalogs.items(),
__("writing message catalogs... "),
@ -259,30 +304,10 @@ class MessageCatalogBuilder(I18nBuilder):
# noop if config.gettext_compact is set
ensuredir(path.join(self.outdir, path.dirname(textdomain)))
context['messages'] = list(catalog)
content = GettextRenderer(outdir=self.outdir).render('message.pot_t', context)
pofn = path.join(self.outdir, textdomain + '.pot')
output = StringIO()
output.write(POHEADER % data)
for message in catalog.messages:
positions = catalog.metadata[message]
if self.config.gettext_location:
# generate "#: file1:line1\n#: file2:line2 ..."
output.write("#: %s\n" % "\n#: ".join(
"%s:%s" % (canon_path(relpath(source, self.outdir)), line)
for source, line, _ in positions))
if self.config.gettext_uuid:
# generate "# uuid1\n# uuid2\n ..."
output.write("# %s\n" % "\n# ".join(uid for _, _, uid in positions))
# message contains *one* line of text ready for translation
message = message.replace('\\', r'\\'). \
replace('"', r'\"'). \
replace('\n', '\\n"\n"')
output.write('msgid "%s"\nmsgstr ""\n\n' % message)
content = output.getvalue()
if should_write(pofn, content):
with open(pofn, 'w', encoding='utf-8') as pofile:
pofile.write(content)
@ -296,6 +321,8 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('gettext_uuid', False, 'gettext')
app.add_config_value('gettext_auto_build', True, 'env')
app.add_config_value('gettext_additional_targets', [], 'env')
app.add_config_value('gettext_last_translator', 'FULL NAME <EMAIL@ADDRESS>', 'gettext')
app.add_config_value('gettext_language_team', 'LANGUAGE <LL@li.org>', 'gettext')
return {
'version': 'builtin',

View File

@ -4,7 +4,7 @@
Several HTML builders.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -15,7 +15,7 @@ import sys
import warnings
from hashlib import md5
from os import path
from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Type, Tuple
from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Tuple
from docutils import nodes
from docutils.core import publish_parts
@ -48,6 +48,11 @@ from sphinx.util.osutil import os_path, relative_uri, ensuredir, movefile, copyf
from sphinx.util.tags import Tags
from sphinx.writers.html import HTMLWriter, HTMLTranslator
if False:
# For type annotation
from typing import Type # for python3.5.1
# HTML5 Writer is available or not
if is_html5_writer_available():
from sphinx.writers.html5 import HTML5Translator
@ -85,7 +90,7 @@ class Stylesheet(str):
attributes = None # type: Dict[str, str]
filename = None # type: str
def __new__(cls, filename: str, *args: str, **attributes: str) -> None:
def __new__(cls, filename: str, *args: str, **attributes: str) -> "Stylesheet":
self = str.__new__(cls, filename) # type: ignore
self.filename = filename
self.attributes = attributes
@ -108,11 +113,10 @@ class JavaScript(str):
attributes = None # type: Dict[str, str]
filename = None # type: str
def __new__(cls, filename: str, **attributes: str) -> None:
def __new__(cls, filename: str, **attributes: str) -> "JavaScript":
self = str.__new__(cls, filename) # type: ignore
self.filename = filename
self.attributes = attributes
self.attributes.setdefault('type', 'text/javascript')
return self
@ -267,6 +271,19 @@ class StandaloneHTMLBuilder(Builder):
style = 'sphinx'
self.highlighter = PygmentsBridge('html', style)
if self.theme:
dark_style = self.theme.get_config('theme', 'pygments_dark_style', None)
else:
dark_style = None
if dark_style is not None:
self.dark_highlighter = PygmentsBridge('html', dark_style)
self.add_css_file('pygments_dark.css',
media='(prefers-color-scheme: dark)',
id='pygments_dark_css')
else:
self.dark_highlighter = None
def init_css_files(self) -> None:
for filename, attrs in self.app.registry.css_files:
self.add_css_file(filename, **attrs)
@ -302,7 +319,7 @@ class StandaloneHTMLBuilder(Builder):
self.script_files.append(JavaScript(filename, **kwargs))
@property
def default_translator_class(self) -> Type[nodes.NodeVisitor]: # type: ignore
def default_translator_class(self) -> "Type[nodes.NodeVisitor]": # type: ignore
if not html5_ready or self.config.html4_writer:
return HTMLTranslator
else:
@ -428,11 +445,8 @@ class StandaloneHTMLBuilder(Builder):
else:
self.last_updated = None
logo = self.config.html_logo and \
path.basename(self.config.html_logo) or ''
favicon = self.config.html_favicon and \
path.basename(self.config.html_favicon) or ''
logo = path.basename(self.config.html_logo) if self.config.html_logo else ''
favicon = path.basename(self.config.html_favicon) if self.config.html_favicon else ''
if not isinstance(self.config.html_use_opensearch, str):
logger.warning(__('html_use_opensearch config value must now be a string'))
@ -472,6 +486,7 @@ class StandaloneHTMLBuilder(Builder):
'show_source': self.config.html_show_sourcelink,
'sourcelink_suffix': self.config.html_sourcelink_suffix,
'file_suffix': self.out_suffix,
'link_suffix': self.link_suffix,
'script_files': self.script_files,
'language': self.config.language,
'css_files': self.css_files,
@ -482,7 +497,7 @@ class StandaloneHTMLBuilder(Builder):
'parents': [],
'logo': logo,
'favicon': favicon,
'html5_doctype': html5_ready and not self.config.html4_writer
'html5_doctype': html5_ready and not self.config.html4_writer,
}
if self.theme:
self.globalcontext.update(
@ -534,10 +549,10 @@ class StandaloneHTMLBuilder(Builder):
# title rendered as HTML
title_node = self.env.longtitles.get(docname)
title = title_node and self.render_partial(title_node)['title'] or ''
title = self.render_partial(title_node)['title'] if title_node else ''
# Suffix for the document
source_suffix = path.splitext(self.env.doc2path(docname))[1]
source_suffix = self.env.doc2path(docname, False)[len(docname):]
# the name for the copied source
if self.config.html_copy_source:
@ -591,7 +606,7 @@ class StandaloneHTMLBuilder(Builder):
self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir)
self.post_process_images(doctree)
title_node = self.env.longtitles.get(docname)
title = title_node and self.render_partial(title_node)['title'] or ''
title = self.render_partial(title_node)['title'] if title_node else ''
self.index_page(docname, doctree, title)
def finish(self) -> None:
@ -717,6 +732,10 @@ class StandaloneHTMLBuilder(Builder):
with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f:
f.write(self.highlighter.get_stylesheet())
if self.dark_highlighter:
with open(path.join(self.outdir, '_static', 'pygments_dark.css'), 'w') as f:
f.write(self.dark_highlighter.get_stylesheet())
def copy_translation_js(self) -> None:
"""Copy a JavaScript file for translations."""
if self.config.language is not None:
@ -806,13 +825,17 @@ class StandaloneHTMLBuilder(Builder):
if self.config.html_scaled_image_link and self.html_scaled_image_link:
for node in doctree.traverse(nodes.image):
scale_keys = ('scale', 'width', 'height')
if not any((key in node) for key in scale_keys) or \
isinstance(node.parent, nodes.reference):
# docutils does unfortunately not preserve the
# ``target`` attribute on images, so we need to check
# the parent node here.
if not any((key in node) for key in ['scale', 'width', 'height']):
# resizing options are not given. scaled image link is available
# only for resized images.
continue
elif isinstance(node.parent, nodes.reference):
# A image having hyperlink target
continue
elif 'no-scaled-link' in node['classes']:
# scaled image link is disabled for this node
continue
uri = node['uri']
reference = nodes.reference('', '', internal=True)
if uri in self.images:
@ -846,7 +869,11 @@ class StandaloneHTMLBuilder(Builder):
if self.indexer is not None and title:
filename = self.env.doc2path(pagename, base=None)
try:
self.indexer.feed(pagename, filename, title, doctree)
metadata = self.env.metadata.get(pagename, {})
if 'nosearch' in metadata:
self.indexer.feed(pagename, filename, '', new_document(''))
else:
self.indexer.feed(pagename, filename, title, doctree)
except TypeError:
# fallback for old search-adapters
self.indexer.feed(pagename, title, doctree) # type: ignore
@ -857,11 +884,11 @@ class StandaloneHTMLBuilder(Builder):
indexer_name, indexer_name),
RemovedInSphinx40Warning)
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwds) -> str:
if 'includehidden' not in kwds:
kwds['includehidden'] = False
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwargs: Any) -> str:
if 'includehidden' not in kwargs:
kwargs['includehidden'] = False
return self.render_partial(TocTree(self.env).get_toctree_for(
docname, self, collapse, **kwds))['fragment']
docname, self, collapse, **kwargs))['fragment']
def get_outfilename(self, pagename: str) -> str:
return path.join(self.outdir, os_path(pagename) + self.out_suffix)
@ -970,7 +997,7 @@ class StandaloneHTMLBuilder(Builder):
return False
ctx['hasdoc'] = hasdoc
ctx['toctree'] = lambda **kw: self._get_local_toctree(pagename, **kw)
ctx['toctree'] = lambda **kwargs: self._get_local_toctree(pagename, **kwargs)
self.add_sidebars(pagename, ctx)
ctx.update(addctx)
@ -1093,7 +1120,6 @@ def setup_js_tag_helper(app: Sphinx, pagename: str, templatexname: str,
attrs.append('src="%s"' % pathto(js.filename, resource=True))
else:
# str value (old styled)
attrs.append('type="text/javascript"')
attrs.append('src="%s"' % pathto(js, resource=True))
return '<script %s>%s</script>' % (' '.join(attrs), body)
@ -1119,7 +1145,8 @@ def validate_html_extra_path(app: Sphinx, config: Config) -> None:
if not path.exists(extra_path):
logger.warning(__('html_extra_path entry %r does not exist'), entry)
config.html_extra_path.remove(entry)
elif path.commonpath([app.outdir, extra_path]) == app.outdir:
elif (path.splitdrive(app.outdir)[0] == path.splitdrive(extra_path)[0] and
path.commonpath([app.outdir, extra_path]) == app.outdir):
logger.warning(__('html_extra_path entry %r is placed inside outdir'), entry)
config.html_extra_path.remove(entry)
@ -1131,7 +1158,8 @@ def validate_html_static_path(app: Sphinx, config: Config) -> None:
if not path.exists(static_path):
logger.warning(__('html_static_path entry %r does not exist'), entry)
config.html_static_path.remove(entry)
elif path.commonpath([app.outdir, static_path]) == app.outdir:
elif (path.splitdrive(app.outdir)[0] == path.splitdrive(static_path)[0] and
path.commonpath([app.outdir, static_path]) == app.outdir):
logger.warning(__('html_static_path entry %r is placed inside outdir'), entry)
config.html_static_path.remove(entry)
@ -1203,12 +1231,12 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('html4_writer', False, 'html')
# event handlers
app.connect('config-inited', convert_html_css_files)
app.connect('config-inited', convert_html_js_files)
app.connect('config-inited', validate_html_extra_path)
app.connect('config-inited', validate_html_static_path)
app.connect('config-inited', validate_html_logo)
app.connect('config-inited', validate_html_favicon)
app.connect('config-inited', convert_html_css_files, priority=800)
app.connect('config-inited', convert_html_js_files, priority=800)
app.connect('config-inited', validate_html_extra_path, priority=800)
app.connect('config-inited', validate_html_static_path, priority=800)
app.connect('config-inited', validate_html_logo, priority=800)
app.connect('config-inited', validate_html_favicon, priority=800)
app.connect('builder-inited', validate_math_renderer)
app.connect('html-page-context', setup_js_tag_helper)

View File

@ -5,7 +5,7 @@
Build HTML help support files.
Parts adapted from Python's Doc/tools/prechm.py.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -4,7 +4,7 @@
LaTeX builder.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -20,6 +20,8 @@ import sphinx.builders.latex.nodes # NOQA # Workaround: import this before wri
from sphinx import package_dir, addnodes, highlighting
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.builders.latex.constants import ADDITIONAL_SETTINGS, DEFAULT_SETTINGS, SHORTHANDOFF
from sphinx.builders.latex.theming import Theme, ThemeFactory
from sphinx.builders.latex.util import ExtBabel
from sphinx.config import Config, ENUM
from sphinx.deprecation import RemovedInSphinx40Warning
@ -34,9 +36,7 @@ from sphinx.util.i18n import format_date
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import SEP, make_filename_from_project
from sphinx.util.template import LaTeXRenderer
from sphinx.writers.latex import (
ADDITIONAL_SETTINGS, DEFAULT_SETTINGS, LaTeXWriter, LaTeXTranslator
)
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
# load docutils.nodes after loading sphinx.builders.latex.nodes
from docutils import nodes # NOQA
@ -54,13 +54,13 @@ XINDY_LANG_OPTIONS = {
'hr': '-L croatian -C utf8 ',
'cs': '-L czech -C utf8 ',
'da': '-L danish -C utf8 ',
'nl': '-L dutch -C ij-as-ij-utf8 ',
'nl': '-L dutch-ij-as-ij -C utf8 ',
'en': '-L english -C utf8 ',
'eo': '-L esperanto -C utf8 ',
'et': '-L estonian -C utf8 ',
'fi': '-L finnish -C utf8 ',
'fr': '-L french -C utf8 ',
'de': '-L german -C din5007-utf8 ',
'de': '-L german-din5007 -C utf8 ',
'is': '-L icelandic -C utf8 ',
'it': '-L italian -C utf8 ',
'la': '-L latin -C utf8 ',
@ -73,9 +73,9 @@ XINDY_LANG_OPTIONS = {
'pl': '-L polish -C utf8 ',
'pt': '-L portuguese -C utf8 ',
'ro': '-L romanian -C utf8 ',
'sk': '-L slovak -C small-utf8 ', # there is also slovak-large
'sk': '-L slovak-small -C utf8 ', # there is also slovak-large
'sl': '-L slovenian -C utf8 ',
'es': '-L spanish -C modern-utf8 ', # there is also spanish-traditional
'es': '-L spanish-modern -C utf8 ', # there is also spanish-traditional
'sv': '-L swedish -C utf8 ',
'tr': '-L turkish -C utf8 ',
'hsb': '-L upper-sorbian -C utf8 ',
@ -86,7 +86,7 @@ XINDY_LANG_OPTIONS = {
'be': '-L belarusian -C utf8 ',
'bg': '-L bulgarian -C utf8 ',
'mk': '-L macedonian -C utf8 ',
'mn': '-L mongolian -C cyrillic-utf8 ',
'mn': '-L mongolian-cyrillic -C utf8 ',
'ru': '-L russian -C utf8 ',
'sr': '-L serbian -C utf8 ',
'sh-cyrl': '-L serbian -C utf8 ',
@ -96,7 +96,7 @@ XINDY_LANG_OPTIONS = {
# can work only with xelatex/lualatex, not supported by texindy+pdflatex
'el': '-L greek -C utf8 ',
# FIXME, not compatible with [:2] slice but does Sphinx support Greek ?
'el-polyton': '-L greek -C polytonic-utf8 ',
'el-polyton': '-L greek-polytonic -C utf8 ',
}
XINDY_CYRILLIC_SCRIPTS = [
@ -127,18 +127,20 @@ class LaTeXBuilder(Builder):
self.context = {} # type: Dict[str, Any]
self.docnames = [] # type: Iterable[str]
self.document_data = [] # type: List[Tuple[str, str, str, str, str, bool]]
self.themes = ThemeFactory(self.app)
self.usepackages = self.app.registry.latex_packages
texescape.init()
self.init_context()
self.init_babel()
self.init_multilingual()
def get_outdated_docs(self) -> Union[str, List[str]]:
return 'all documents' # for now
def get_target_uri(self, docname: str, typ: str = None) -> str:
if docname not in self.docnames:
raise NoUri
raise NoUri(docname, typ)
else:
return '%' + docname
@ -207,6 +209,41 @@ class LaTeXBuilder(Builder):
logger.warning(__('no Babel option known for language %r'),
self.config.language)
def init_multilingual(self) -> None:
if self.context['latex_engine'] == 'pdflatex':
if not self.babel.uses_cyrillic():
if 'X2' in self.context['fontenc']:
self.context['substitutefont'] = '\\usepackage{substitutefont}'
self.context['textcyrillic'] = '\\usepackage[Xtwo]{sphinxcyrillic}'
elif 'T2A' in self.context['fontenc']:
self.context['substitutefont'] = '\\usepackage{substitutefont}'
self.context['textcyrillic'] = '\\usepackage[TtwoA]{sphinxcyrillic}'
if 'LGR' in self.context['fontenc']:
self.context['substitutefont'] = '\\usepackage{substitutefont}'
else:
self.context['textgreek'] = ''
# 'babel' key is public and user setting must be obeyed
if self.context['babel']:
self.context['classoptions'] += ',' + self.babel.get_language()
# this branch is not taken for xelatex/lualatex if default settings
self.context['multilingual'] = self.context['babel']
if self.config.language:
self.context['shorthandoff'] = SHORTHANDOFF
# Times fonts don't work with Cyrillic languages
if self.babel.uses_cyrillic() and 'fontpkg' not in self.config.latex_elements:
self.context['fontpkg'] = ''
elif self.context['polyglossia']:
self.context['classoptions'] += ',' + self.babel.get_language()
options = self.babel.get_mainlanguage_options()
if options:
language = r'\setmainlanguage[%s]{%s}' % (options, self.babel.get_language())
else:
language = r'\setmainlanguage{%s}' % self.babel.get_language()
self.context['multilingual'] = '%s\n%s' % (self.context['polyglossia'], language)
def write_stylesheet(self) -> None:
highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
stylesheet = path.join(self.outdir, 'sphinxhighlight.sty')
@ -216,47 +253,51 @@ class LaTeXBuilder(Builder):
'[2016/05/29 stylesheet for highlighting with pygments]\n\n')
f.write(highlighter.get_stylesheet())
def write(self, *ignored) -> None:
def write(self, *ignored: Any) -> None:
docwriter = LaTeXWriter(self)
docsettings = OptionParser(
defaults=self.env.settings,
components=(docwriter,),
read_config_files=True).get_default_values() # type: Any
patch_settings(docsettings)
self.init_document_data()
self.write_stylesheet()
for entry in self.document_data:
docname, targetname, title, author, docclass = entry[:5]
docname, targetname, title, author, themename = entry[:5]
theme = self.themes.get(themename)
toctree_only = False
if len(entry) > 5:
toctree_only = entry[5]
destination = SphinxFileOutput(destination_path=path.join(self.outdir, targetname),
encoding='utf-8', overwrite_if_changed=True)
with progress_message(__("processing %s") % targetname):
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
doctree = self.env.get_doctree(docname)
toctree = next(iter(doctree.traverse(addnodes.toctree)), None)
if toctree and toctree.get('maxdepth') > 0:
tocdepth = toctree.get('maxdepth')
else:
tocdepth = None
doctree = self.assemble_doctree(
docname, toctree_only,
appendices=((docclass != 'howto') and self.config.latex_appendices or []))
appendices=(self.config.latex_appendices if theme.name != 'howto' else []))
doctree['docclass'] = theme.docclass
doctree['contentsname'] = self.get_contentsname(docname)
doctree['tocdepth'] = tocdepth
self.post_process_images(doctree)
self.update_doc_context(title, author)
self.update_doc_context(title, author, theme)
with progress_message(__("writing")):
docsettings.author = author
docsettings.title = title
docsettings.contentsname = self.get_contentsname(docname)
docsettings.docname = docname
docsettings.docclass = docclass
docsettings._author = author
docsettings._title = title
docsettings._contentsname = doctree['contentsname']
docsettings._docname = docname
docsettings._docclass = theme.name
doctree.settings = docsettings
docwriter.theme = theme
docwriter.write(doctree, destination)
def get_contentsname(self, indexfile: str) -> str:
@ -269,9 +310,13 @@ class LaTeXBuilder(Builder):
return contentsname
def update_doc_context(self, title: str, author: str) -> None:
def update_doc_context(self, title: str, author: str, theme: Theme) -> None:
self.context['title'] = title
self.context['author'] = author
self.context['docclass'] = theme.docclass
self.context['papersize'] = theme.papersize
self.context['pointsize'] = theme.pointsize
self.context['wrapperclass'] = theme.wrapperclass
def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[str]) -> nodes.document: # NOQA
self.docnames = set([indexfile] + appendices)
@ -361,13 +406,6 @@ class LaTeXBuilder(Builder):
copy_asset_file(path.join(staticdirname, 'Makefile_t'),
self.outdir, context=context)
# the logo is handled differently
if self.config.latex_logo:
if not path.isfile(path.join(self.confdir, self.config.latex_logo)):
raise SphinxError(__('logo file %r does not exist') % self.config.latex_logo)
else:
copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir)
@progress_message(__('copying additional files'))
def copy_latex_additional_files(self) -> None:
for filename in self.config.latex_additional_files:
@ -387,6 +425,11 @@ class LaTeXBuilder(Builder):
except Exception as err:
logger.warning(__('cannot copy image file %r: %s'),
path.join(self.srcdir, src), err)
if self.config.latex_logo:
if not path.isfile(path.join(self.confdir, self.config.latex_logo)):
raise SphinxError(__('logo file %r does not exist') % self.config.latex_logo)
else:
copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir)
def write_message_catalog(self) -> None:
formats = self.config.numfig_format
@ -404,20 +447,68 @@ class LaTeXBuilder(Builder):
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
def patch_settings(settings: Any) -> Any:
"""Make settings object to show deprecation messages."""
class Values(type(settings)): # type: ignore
@property
def author(self) -> str:
warnings.warn('settings.author is deprecated',
RemovedInSphinx40Warning, stacklevel=2)
return self._author
@property
def title(self) -> str:
warnings.warn('settings.title is deprecated',
RemovedInSphinx40Warning, stacklevel=2)
return self._title
@property
def contentsname(self) -> str:
warnings.warn('settings.contentsname is deprecated',
RemovedInSphinx40Warning, stacklevel=2)
return self._contentsname
@property
def docname(self) -> str:
warnings.warn('settings.docname is deprecated',
RemovedInSphinx40Warning, stacklevel=2)
return self._docname
@property
def docclass(self) -> str:
warnings.warn('settings.docclass is deprecated',
RemovedInSphinx40Warning, stacklevel=2)
return self._docclass
# dynamic subclassing
settings.__class__ = Values
def validate_config_values(app: Sphinx, config: Config) -> None:
for key in list(config.latex_elements):
if key not in DEFAULT_SETTINGS:
msg = __("Unknown configure key: latex_elements[%r]. ignored.")
msg = __("Unknown configure key: latex_elements[%r], ignored.")
logger.warning(msg % (key,))
config.latex_elements.pop(key)
def validate_latex_theme_options(app: Sphinx, config: Config) -> None:
for key in list(config.latex_theme_options):
if key not in Theme.UPDATABLE_KEYS:
msg = __("Unknown theme option: latex_theme_options[%r], ignored.")
logger.warning(msg % (key,))
config.latex_theme_options.pop(key)
def default_latex_engine(config: Config) -> str:
""" Better default latex_engine settings for specific languages. """
if config.language == 'ja':
return 'platex'
elif (config.language or '').startswith('zh'):
return 'xelatex'
elif config.language == 'el':
return 'xelatex'
else:
return 'pdflatex'
@ -425,8 +516,12 @@ def default_latex_engine(config: Config) -> str:
def default_latex_docclass(config: Config) -> Dict[str, str]:
""" Better default latex_docclass settings for specific languages. """
if config.language == 'ja':
return {'manual': 'jsbook',
'howto': 'jreport'}
if config.latex_engine == 'uplatex':
return {'manual': 'ujbook',
'howto': 'ujreport'}
else:
return {'manual': 'jsbook',
'howto': 'jreport'}
else:
return {}
@ -438,26 +533,29 @@ def default_latex_use_xindy(config: Config) -> bool:
def default_latex_documents(config: Config) -> List[Tuple[str, str, str, str, str]]:
""" Better default latex_documents settings. """
project = texescape.escape(config.project, config.latex_engine)
author = texescape.escape(config.author, config.latex_engine)
return [(config.master_doc,
make_filename_from_project(config.project) + '.tex',
texescape.escape_abbr(texescape.escape(config.project)),
texescape.escape_abbr(texescape.escape(config.author)),
'manual')]
texescape.escape_abbr(project),
texescape.escape_abbr(author),
config.latex_theme)]
def setup(app: Sphinx) -> Dict[str, Any]:
app.setup_extension('sphinx.builders.latex.transforms')
app.add_builder(LaTeXBuilder)
app.connect('config-inited', validate_config_values)
app.connect('config-inited', validate_config_values, priority=800)
app.connect('config-inited', validate_latex_theme_options, priority=800)
app.add_config_value('latex_engine', default_latex_engine, None,
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex'))
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex'))
app.add_config_value('latex_documents', default_latex_documents, None)
app.add_config_value('latex_logo', None, None, [str])
app.add_config_value('latex_appendices', [], None)
app.add_config_value('latex_use_latex_multicolumn', False, None)
app.add_config_value('latex_use_xindy', default_latex_use_xindy, None)
app.add_config_value('latex_use_xindy', default_latex_use_xindy, None, [bool])
app.add_config_value('latex_toplevel_sectioning', None, None,
ENUM(None, 'part', 'chapter', 'section'))
app.add_config_value('latex_domain_indices', True, None, [list])
@ -465,6 +563,9 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('latex_show_pagerefs', False, None)
app.add_config_value('latex_elements', {}, None)
app.add_config_value('latex_additional_files', [], None)
app.add_config_value('latex_theme', 'manual', None, [str])
app.add_config_value('latex_theme_options', {}, None)
app.add_config_value('latex_theme_path', [], None, [list])
app.add_config_value('latex_docclass', default_latex_docclass, None)

View File

@ -0,0 +1,202 @@
"""
sphinx.builders.latex.constants
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
consntants for LaTeX builder.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict
PDFLATEX_DEFAULT_FONTPKG = r'''
\usepackage{times}
\expandafter\ifx\csname T@LGR\endcsname\relax
\else
% LGR was declared as font encoding
\substitutefont{LGR}{\rmdefault}{cmr}
\substitutefont{LGR}{\sfdefault}{cmss}
\substitutefont{LGR}{\ttdefault}{cmtt}
\fi
\expandafter\ifx\csname T@X2\endcsname\relax
\expandafter\ifx\csname T@T2A\endcsname\relax
\else
% T2A was declared as font encoding
\substitutefont{T2A}{\rmdefault}{cmr}
\substitutefont{T2A}{\sfdefault}{cmss}
\substitutefont{T2A}{\ttdefault}{cmtt}
\fi
\else
% X2 was declared as font encoding
\substitutefont{X2}{\rmdefault}{cmr}
\substitutefont{X2}{\sfdefault}{cmss}
\substitutefont{X2}{\ttdefault}{cmtt}
\fi
'''
XELATEX_DEFAULT_FONTPKG = r'''
\setmainfont{FreeSerif}[
Extension = .otf,
UprightFont = *,
ItalicFont = *Italic,
BoldFont = *Bold,
BoldItalicFont = *BoldItalic
]
\setsansfont{FreeSans}[
Extension = .otf,
UprightFont = *,
ItalicFont = *Oblique,
BoldFont = *Bold,
BoldItalicFont = *BoldOblique,
]
\setmonofont{FreeMono}[
Extension = .otf,
UprightFont = *,
ItalicFont = *Oblique,
BoldFont = *Bold,
BoldItalicFont = *BoldOblique,
]
'''
XELATEX_GREEK_DEFAULT_FONTPKG = (XELATEX_DEFAULT_FONTPKG +
'\n\\newfontfamily\\greekfont{FreeSerif}' +
'\n\\newfontfamily\\greekfontsf{FreeSans}' +
'\n\\newfontfamily\\greekfonttt{FreeMono}')
LUALATEX_DEFAULT_FONTPKG = XELATEX_DEFAULT_FONTPKG
DEFAULT_SETTINGS = {
'latex_engine': 'pdflatex',
'papersize': '',
'pointsize': '',
'pxunit': '.75bp',
'classoptions': '',
'extraclassoptions': '',
'maxlistdepth': '',
'sphinxpkgoptions': '',
'sphinxsetup': '',
'fvset': '\\fvset{fontsize=\\small}',
'passoptionstopackages': '',
'geometry': '\\usepackage{geometry}',
'inputenc': '',
'utf8extra': '',
'cmappkg': '\\usepackage{cmap}',
'fontenc': '\\usepackage[T1]{fontenc}',
'amsmath': '\\usepackage{amsmath,amssymb,amstext}',
'multilingual': '',
'babel': '\\usepackage{babel}',
'polyglossia': '',
'fontpkg': PDFLATEX_DEFAULT_FONTPKG,
'substitutefont': '',
'textcyrillic': '',
'textgreek': '\\usepackage{textalpha}',
'fncychap': '\\usepackage[Bjarne]{fncychap}',
'hyperref': ('% Include hyperref last.\n'
'\\usepackage{hyperref}\n'
'% Fix anchor placement for figures with captions.\n'
'\\usepackage{hypcap}% it must be loaded after hyperref.\n'
'% Set up styles of URL: it should be placed after hyperref.\n'
'\\urlstyle{same}'),
'contentsname': '',
'extrapackages': '',
'preamble': '',
'title': '',
'release': '',
'author': '',
'releasename': '',
'makeindex': '\\makeindex',
'shorthandoff': '',
'maketitle': '\\sphinxmaketitle',
'tableofcontents': '\\sphinxtableofcontents',
'atendofbody': '',
'printindex': '\\printindex',
'transition': '\n\n\\bigskip\\hrule\\bigskip\n\n',
'figure_align': 'htbp',
'tocdepth': '',
'secnumdepth': '',
} # type: Dict[str, Any]
ADDITIONAL_SETTINGS = {
'pdflatex': {
'inputenc': '\\usepackage[utf8]{inputenc}',
'utf8extra': ('\\ifdefined\\DeclareUnicodeCharacter\n'
'% support both utf8 and utf8x syntaxes\n'
' \\ifdefined\\DeclareUnicodeCharacterAsOptional\n'
' \\def\\sphinxDUC#1{\\DeclareUnicodeCharacter{"#1}}\n'
' \\else\n'
' \\let\\sphinxDUC\\DeclareUnicodeCharacter\n'
' \\fi\n'
' \\sphinxDUC{00A0}{\\nobreakspace}\n'
' \\sphinxDUC{2500}{\\sphinxunichar{2500}}\n'
' \\sphinxDUC{2502}{\\sphinxunichar{2502}}\n'
' \\sphinxDUC{2514}{\\sphinxunichar{2514}}\n'
' \\sphinxDUC{251C}{\\sphinxunichar{251C}}\n'
' \\sphinxDUC{2572}{\\textbackslash}\n'
'\\fi'),
},
'xelatex': {
'latex_engine': 'xelatex',
'polyglossia': '\\usepackage{polyglossia}',
'babel': '',
'fontenc': ('\\usepackage{fontspec}\n'
'\\defaultfontfeatures[\\rmfamily,\\sffamily,\\ttfamily]{}'),
'fontpkg': XELATEX_DEFAULT_FONTPKG,
'textgreek': '',
'utf8extra': ('\\catcode`^^^^00a0\\active\\protected\\def^^^^00a0'
'{\\leavevmode\\nobreak\\ }'),
},
'lualatex': {
'latex_engine': 'lualatex',
'polyglossia': '\\usepackage{polyglossia}',
'babel': '',
'fontenc': ('\\usepackage{fontspec}\n'
'\\defaultfontfeatures[\\rmfamily,\\sffamily,\\ttfamily]{}'),
'fontpkg': LUALATEX_DEFAULT_FONTPKG,
'textgreek': '',
'utf8extra': ('\\catcode`^^^^00a0\\active\\protected\\def^^^^00a0'
'{\\leavevmode\\nobreak\\ }'),
},
'platex': {
'latex_engine': 'platex',
'babel': '',
'classoptions': ',dvipdfmx',
'fontpkg': '\\usepackage{times}',
'textgreek': '',
'fncychap': '',
'geometry': '\\usepackage[dvipdfm]{geometry}',
},
'uplatex': {
'latex_engine': 'uplatex',
'babel': '',
'classoptions': ',dvipdfmx',
'fontpkg': '\\usepackage{times}',
'textgreek': '',
'fncychap': '',
'geometry': '\\usepackage[dvipdfm]{geometry}',
},
# special settings for latex_engine + language_code
('xelatex', 'fr'): {
# use babel instead of polyglossia by default
'polyglossia': '',
'babel': '\\usepackage{babel}',
},
('xelatex', 'zh'): {
'polyglossia': '',
'babel': '\\usepackage{babel}',
'fontenc': '\\usepackage{xeCJK}',
},
('xelatex', 'el'): {
'fontpkg': XELATEX_GREEK_DEFAULT_FONTPKG,
},
} # type: Dict[Any, Dict[str, Any]]
SHORTHANDOFF = r'''
\ifdefined\shorthandoff
\ifnum\catcode`\=\string=\active\shorthandoff{=}\fi
\ifnum\catcode`\"=\active\shorthandoff{"}\fi
\fi
'''

View File

@ -4,7 +4,7 @@
Additional nodes for LaTeX writer.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -0,0 +1,139 @@
"""
sphinx.builders.latex.theming
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Theming support for LaTeX builder.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import configparser
from os import path
from typing import Dict
from sphinx.application import Sphinx
from sphinx.config import Config
from sphinx.errors import ThemeError
from sphinx.locale import __
from sphinx.util import logging
logger = logging.getLogger(__name__)
class Theme:
"""A set of LaTeX configurations."""
LATEX_ELEMENTS_KEYS = ['papersize', 'pointsize']
UPDATABLE_KEYS = ['papersize', 'pointsize']
def __init__(self, name: str) -> None:
self.name = name
self.docclass = name
self.wrapperclass = name
self.papersize = 'letterpaper'
self.pointsize = '10pt'
self.toplevel_sectioning = 'chapter'
def update(self, config: Config) -> None:
"""Override theme settings by user's configuration."""
for key in self.LATEX_ELEMENTS_KEYS:
if config.latex_elements.get(key):
value = config.latex_elements[key]
setattr(self, key, value)
for key in self.UPDATABLE_KEYS:
if key in config.latex_theme_options:
value = config.latex_theme_options[key]
setattr(self, key, value)
class BuiltInTheme(Theme):
"""A built-in LaTeX theme."""
def __init__(self, name: str, config: Config) -> None:
super().__init__(name)
if name == 'howto':
self.docclass = config.latex_docclass.get('howto', 'article')
else:
self.docclass = config.latex_docclass.get('manual', 'report')
if name in ('manual', 'howto'):
self.wrapperclass = 'sphinx' + name
else:
self.wrapperclass = name
# we assume LaTeX class provides \chapter command except in case
# of non-Japanese 'howto' case
if name == 'howto' and not self.docclass.startswith('j'):
self.toplevel_sectioning = 'section'
else:
self.toplevel_sectioning = 'chapter'
class UserTheme(Theme):
"""A user defined LaTeX theme."""
REQUIRED_CONFIG_KEYS = ['docclass', 'wrapperclass']
OPTIONAL_CONFIG_KEYS = ['papersize', 'pointsize', 'toplevel_sectioning']
def __init__(self, name: str, filename: str) -> None:
super().__init__(name)
self.config = configparser.RawConfigParser()
self.config.read(path.join(filename))
for key in self.REQUIRED_CONFIG_KEYS:
try:
value = self.config.get('theme', key)
setattr(self, key, value)
except configparser.NoSectionError:
raise ThemeError(__('%r doesn\'t have "theme" setting') % filename)
except configparser.NoOptionError as exc:
raise ThemeError(__('%r doesn\'t have "%s" setting') % (filename, exc.args[0]))
for key in self.OPTIONAL_CONFIG_KEYS:
try:
value = self.config.get('theme', key)
setattr(self, key, value)
except configparser.NoOptionError:
pass
class ThemeFactory:
"""A factory class for LaTeX Themes."""
def __init__(self, app: Sphinx) -> None:
self.themes = {} # type: Dict[str, Theme]
self.theme_paths = [path.join(app.srcdir, p) for p in app.config.latex_theme_path]
self.config = app.config
self.load_builtin_themes(app.config)
def load_builtin_themes(self, config: Config) -> None:
"""Load built-in themes."""
self.themes['manual'] = BuiltInTheme('manual', config)
self.themes['howto'] = BuiltInTheme('howto', config)
def get(self, name: str) -> Theme:
"""Get a theme for given *name*."""
if name in self.themes:
theme = self.themes[name]
else:
theme = self.find_user_theme(name)
if not theme:
theme = Theme(name)
theme.update(self.config)
return theme
def find_user_theme(self, name: str) -> Theme:
"""Find a theme named as *name* from latex_theme_path."""
for theme_path in self.theme_paths:
config_path = path.join(theme_path, name, 'theme.conf')
if path.isfile(config_path):
try:
return UserTheme(name, config_path)
except ThemeError as exc:
logger.warning(exc)
return None

View File

@ -4,7 +4,7 @@
Transforms for LaTeX builder.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -32,7 +32,7 @@ class FootnoteDocnameUpdater(SphinxTransform):
default_priority = 700
TARGET_NODES = (nodes.footnote, nodes.footnote_reference)
def apply(self, **kwargs) -> None:
def apply(self, **kwargs: Any) -> None:
matcher = NodeMatcher(*self.TARGET_NODES)
for node in self.document.traverse(matcher): # type: nodes.Element
node['docname'] = self.env.docname
@ -51,7 +51,7 @@ class ShowUrlsTransform(SphinxPostTransform):
# references are expanded to footnotes (or not)
expanded = False
def run(self, **kwargs) -> None:
def run(self, **kwargs: Any) -> None:
try:
# replace id_prefix temporarily
settings = self.document.settings # type: Any
@ -338,7 +338,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
default_priority = 600
builders = ('latex',)
def run(self, **kwargs) -> None:
def run(self, **kwargs: Any) -> None:
footnotes = list(self.document.traverse(nodes.footnote))
for node in footnotes:
node.parent.remove(node)
@ -490,7 +490,7 @@ class BibliographyTransform(SphinxPostTransform):
default_priority = 750
builders = ('latex',)
def run(self, **kwargs) -> None:
def run(self, **kwargs: Any) -> None:
citations = thebibliography()
for node in self.document.traverse(nodes.citation):
node.parent.remove(node)
@ -509,7 +509,7 @@ class CitationReferenceTransform(SphinxPostTransform):
default_priority = 5 # before ReferencesResolver
builders = ('latex',)
def run(self, **kwargs) -> None:
def run(self, **kwargs: Any) -> None:
domain = cast(CitationDomain, self.env.get_domain('citation'))
matcher = NodeMatcher(addnodes.pending_xref, refdomain='citation', reftype='ref')
for node in self.document.traverse(matcher): # type: addnodes.pending_xref
@ -529,7 +529,7 @@ class MathReferenceTransform(SphinxPostTransform):
default_priority = 5 # before ReferencesResolver
builders = ('latex',)
def run(self, **kwargs) -> None:
def run(self, **kwargs: Any) -> None:
equations = self.env.get_domain('math').data['objects']
for node in self.document.traverse(addnodes.pending_xref):
if node['refdomain'] == 'math' and node['reftype'] in ('eq', 'numref'):
@ -544,7 +544,7 @@ class LiteralBlockTransform(SphinxPostTransform):
default_priority = 400
builders = ('latex',)
def run(self, **kwargs) -> None:
def run(self, **kwargs: Any) -> None:
matcher = NodeMatcher(nodes.container, literal_block=True)
for node in self.document.traverse(matcher): # type: nodes.container
newnode = captioned_literal_block('', *node.children, **node.attributes)
@ -556,7 +556,7 @@ class DocumentTargetTransform(SphinxPostTransform):
default_priority = 400
builders = ('latex',)
def run(self, **kwargs) -> None:
def run(self, **kwargs: Any) -> None:
for node in self.document.traverse(addnodes.start_of_file):
section = node.next_node(nodes.section)
if section:
@ -591,7 +591,7 @@ class IndexInSectionTitleTransform(SphinxTransform):
"""
default_priority = 400
def apply(self):
def apply(self, **kwargs: Any) -> None:
for node in self.document.traverse(nodes.title):
if isinstance(node.parent, nodes.section):
for i, index in enumerate(node.traverse(addnodes.index)):

View File

@ -8,6 +8,8 @@
:license: BSD, see LICENSE for details.
"""
from typing import Optional
from docutils.writers.latex2e import Babel
@ -40,7 +42,7 @@ class ExtBabel(Babel):
self.supported = False
return 'english' # fallback to english
def get_mainlanguage_options(self) -> str:
def get_mainlanguage_options(self) -> Optional[str]:
"""Return options for polyglossia's ``\\setmainlanguage``."""
if self.use_polyglossia is False:
return None

View File

@ -4,10 +4,11 @@
The CheckExternalLinksBuilder class.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import json
import queue
import re
import socket
@ -26,7 +27,7 @@ from sphinx.builders import Builder
from sphinx.locale import __
from sphinx.util import encode_uri, requests, logging
from sphinx.util.console import ( # type: ignore
purple, red, darkgreen, darkgray, darkred, turquoise
purple, red, darkgreen, darkgray, turquoise
)
from sphinx.util.nodes import get_node_line
from sphinx.util.requests import is_ssl_error
@ -59,6 +60,9 @@ def check_anchor(response: requests.requests.Response, anchor: str) -> bool:
# Read file in chunks. If we find a matching anchor, we break
# the loop early in hopes not to have to download the whole thing.
for chunk in response.iter_content(chunk_size=4096, decode_unicode=True):
if isinstance(chunk, bytes): # requests failed to decode
chunk = chunk.decode() # manually try to decode it
parser.feed(chunk)
if parser.found:
break
@ -78,6 +82,8 @@ class CheckExternalLinksBuilder(Builder):
self.to_ignore = [re.compile(x) for x in self.app.config.linkcheck_ignore]
self.anchors_ignore = [re.compile(x)
for x in self.app.config.linkcheck_anchors_ignore]
self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info
in self.app.config.linkcheck_auth]
self.good = set() # type: Set[str]
self.broken = {} # type: Dict[str, str]
self.redirected = {} # type: Dict[str, Tuple[str, int]]
@ -85,6 +91,8 @@ class CheckExternalLinksBuilder(Builder):
socket.setdefaulttimeout(5.0)
# create output file
open(path.join(self.outdir, 'output.txt'), 'w').close()
# create JSON output file
open(path.join(self.outdir, 'output.json'), 'w').close()
# create queues and worker threads
self.wqueue = queue.Queue() # type: queue.Queue
@ -101,7 +109,6 @@ class CheckExternalLinksBuilder(Builder):
'allow_redirects': True,
'headers': {
'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8',
'User-Agent': requests.useragent_header[0][1],
},
}
if self.app.config.linkcheck_timeout:
@ -125,11 +132,18 @@ class CheckExternalLinksBuilder(Builder):
except UnicodeError:
req_url = encode_uri(req_url)
# Get auth info, if any
for pattern, auth_info in self.auth:
if pattern.match(uri):
break
else:
auth_info = None
try:
if anchor and self.app.config.linkcheck_anchors:
# Read the whole document and see if #anchor exists
response = requests.get(req_url, stream=True, config=self.app.config,
**kwargs)
auth=auth_info, **kwargs)
found = check_anchor(response, unquote(anchor))
if not found:
@ -138,13 +152,14 @@ class CheckExternalLinksBuilder(Builder):
try:
# try a HEAD request first, which should be easier on
# the server and the network
response = requests.head(req_url, config=self.app.config, **kwargs)
response = requests.head(req_url, config=self.app.config,
auth=auth_info, **kwargs)
response.raise_for_status()
except HTTPError:
# retry with GET request if that fails, some servers
# don't like HEAD requests.
response = requests.get(req_url, stream=True, config=self.app.config,
**kwargs)
auth=auth_info, **kwargs)
response.raise_for_status()
except HTTPError as err:
if err.response.status_code == 401:
@ -213,9 +228,16 @@ class CheckExternalLinksBuilder(Builder):
def process_result(self, result: Tuple[str, str, int, str, str, int]) -> None:
uri, docname, lineno, status, info, code = result
filename = self.env.doc2path(docname, None)
linkstat = dict(filename=filename, lineno=lineno,
status=status, code=code, uri=uri,
info=info)
if status == 'unchecked':
self.write_linkstat(linkstat)
return
if status == 'working' and info == 'old':
self.write_linkstat(linkstat)
return
if lineno:
logger.info('(line %4d) ', lineno, nonl=True)
@ -224,29 +246,38 @@ class CheckExternalLinksBuilder(Builder):
logger.info(darkgray('-ignored- ') + uri + ': ' + info)
else:
logger.info(darkgray('-ignored- ') + uri)
self.write_linkstat(linkstat)
elif status == 'local':
logger.info(darkgray('-local- ') + uri)
self.write_entry('local', docname, lineno, uri)
self.write_entry('local', docname, filename, lineno, uri)
self.write_linkstat(linkstat)
elif status == 'working':
logger.info(darkgreen('ok ') + uri + info)
self.write_linkstat(linkstat)
elif status == 'broken':
self.write_entry('broken', docname, lineno, uri + ': ' + info)
if self.app.quiet or self.app.warningiserror:
logger.warning(__('broken link: %s (%s)'), uri, info,
location=(self.env.doc2path(docname), lineno))
location=(filename, lineno))
else:
logger.info(red('broken ') + uri + red(' - ' + info))
self.write_entry('broken', docname, filename, lineno, uri + ': ' + info)
self.write_linkstat(linkstat)
elif status == 'redirected':
text, color = {
301: ('permanently', darkred),
302: ('with Found', purple),
303: ('with See Other', purple),
307: ('temporarily', turquoise),
0: ('with unknown code', purple),
}[code]
self.write_entry('redirected ' + text, docname, lineno,
uri + ' to ' + info)
try:
text, color = {
301: ('permanently', purple),
302: ('with Found', purple),
303: ('with See Other', purple),
307: ('temporarily', turquoise),
308: ('permanently', purple),
}[code]
except KeyError:
text, color = ('with unknown code', purple)
linkstat['text'] = text
logger.info(color('redirect ') + uri + color(' - ' + text + ' to ' + info))
self.write_entry('redirected ' + text, docname, filename,
lineno, uri + ' to ' + info)
self.write_linkstat(linkstat)
def get_target_uri(self, docname: str, typ: str = None) -> str:
return ''
@ -286,10 +317,15 @@ class CheckExternalLinksBuilder(Builder):
if self.broken:
self.app.statuscode = 1
def write_entry(self, what: str, docname: str, line: int, uri: str) -> None:
with open(path.join(self.outdir, 'output.txt'), 'a', encoding='utf-8') as output:
output.write("%s:%s: [%s] %s\n" % (self.env.doc2path(docname, None),
line, what, uri))
def write_entry(self, what: str, docname: str, filename: str, line: int,
uri: str) -> None:
with open(path.join(self.outdir, 'output.txt'), 'a') as output:
output.write("%s:%s: [%s] %s\n" % (filename, line, what, uri))
def write_linkstat(self, data: dict) -> None:
with open(path.join(self.outdir, 'output.json'), 'a') as output:
output.write(json.dumps(data))
output.write('\n')
def finish(self) -> None:
for worker in self.workers:
@ -300,6 +336,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(CheckExternalLinksBuilder)
app.add_config_value('linkcheck_ignore', [], None)
app.add_config_value('linkcheck_auth', [], None)
app.add_config_value('linkcheck_retries', 1, None)
app.add_config_value('linkcheck_timeout', None, None, [int])
app.add_config_value('linkcheck_workers', 5, None)

View File

@ -4,7 +4,7 @@
Manual pages builder.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -53,10 +53,10 @@ class ManualPageBuilder(Builder):
def get_target_uri(self, docname: str, typ: str = None) -> str:
if typ == 'token':
return ''
raise NoUri
raise NoUri(docname, typ)
@progress_message(__('writing'))
def write(self, *ignored) -> None:
def write(self, *ignored: Any) -> None:
docwriter = ManualPageWriter(self)
docsettings = OptionParser(
defaults=self.env.settings,

View File

@ -4,7 +4,7 @@
Build input files for the Qt collection generator.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -4,7 +4,7 @@
Single HTML builders.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -67,10 +67,10 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
if hashindex >= 0:
refnode['refuri'] = fname + refuri[hashindex:]
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwds) -> str:
if 'includehidden' not in kwds:
kwds['includehidden'] = False
toctree = TocTree(self.env).get_toctree_for(docname, self, collapse, **kwds)
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwargs: Any) -> str:
if 'includehidden' not in kwargs:
kwargs['includehidden'] = False
toctree = TocTree(self.env).get_toctree_for(docname, self, collapse, **kwargs)
if toctree is not None:
self.fix_refuris(toctree)
return self.render_partial(toctree)['fragment']
@ -149,7 +149,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
'display_toc': display_toc,
}
def write(self, *ignored) -> None:
def write(self, *ignored: Any) -> None:
docnames = self.env.all_docs
with progress_message(__('preparing documents')):

View File

@ -4,7 +4,7 @@
Texinfo builder.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -63,7 +63,7 @@ class TexinfoBuilder(Builder):
def get_target_uri(self, docname: str, typ: str = None) -> str:
if docname not in self.docnames:
raise NoUri
raise NoUri(docname, typ)
else:
return '%' + docname
@ -90,7 +90,7 @@ class TexinfoBuilder(Builder):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
def write(self, *ignored) -> None:
def write(self, *ignored: Any) -> None:
self.init_document_data()
for entry in self.document_data:
docname, targetname, title, author = entry[:4]

View File

@ -4,7 +4,7 @@
Plain-text Sphinx builder.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -4,12 +4,12 @@
Docutils-native XML and pseudo-XML builders.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from os import path
from typing import Any, Dict, Iterator, Set, Type, Union
from typing import Any, Dict, Iterator, Set, Union
from docutils import nodes
from docutils.io import StringOutput
@ -23,6 +23,11 @@ from sphinx.util import logging
from sphinx.util.osutil import ensuredir, os_path
from sphinx.writers.xml import XMLWriter, PseudoXMLWriter
if False:
# For type annotation
from typing import Type # for python3.5.1
logger = logging.getLogger(__name__)

View File

@ -4,6 +4,6 @@
Modules for command line executables.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -4,14 +4,16 @@
Build documentation from a provided source.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import argparse
import bdb
import locale
import multiprocessing
import os
import pdb
import sys
import traceback
from typing import Any, IO, List
@ -29,8 +31,10 @@ from sphinx.util.docutils import docutils_namespace, patch_docutils
def handle_exception(app: Sphinx, args: Any, exception: BaseException, stderr: IO = sys.stderr) -> None: # NOQA
if isinstance(exception, bdb.BdbQuit):
return
if args.pdb:
import pdb
print(red(__('Exception occurred while building, starting debugger:')),
file=stderr)
traceback.print_exc()
@ -47,7 +51,7 @@ def handle_exception(app: Sphinx, args: Any, exception: BaseException, stderr: I
print(terminal_safe(exception.args[0]), file=stderr)
elif isinstance(exception, SphinxError):
print(red('%s:' % exception.category), file=stderr)
print(terminal_safe(str(exception)), file=stderr)
print(str(exception), file=stderr)
elif isinstance(exception, UnicodeError):
print(red(__('Encoding error:')), file=stderr)
print(terminal_safe(str(exception)), file=stderr)
@ -180,7 +184,7 @@ files can be built by specifying individual filenames.
group.add_argument('-W', action='store_true', dest='warningiserror',
help=__('turn warnings into errors'))
group.add_argument('--keep-going', action='store_true', dest='keep_going',
help=__("With -W, keep going when getting warnings"))
help=__("with -W, keep going when getting warnings"))
group.add_argument('-T', action='store_true', dest='traceback',
help=__('show full traceback on exception'))
group.add_argument('-P', action='store_true', dest='pdb',

View File

@ -10,7 +10,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-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -88,7 +88,7 @@ class Make:
nocolor()
print(bold("Sphinx v%s" % sphinx.__display_version__))
print("Please use `make %s' where %s is one of" % ((blue('target'),) * 2)) # type: ignore # NOQA
print("Please use `make %s' where %s is one of" % ((blue('target'),) * 2))
for osname, bname, description in BUILDERS:
if not osname or os.name == osname:
print(' %s %s' % (blue(bname.ljust(10)), description))

View File

@ -4,7 +4,7 @@
Quickly setup documentation source to work with Sphinx.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -359,7 +359,7 @@ def generate(d: Dict, overwrite: bool = True, silent: bool = False, templatedir:
ensuredir(d['path'])
srcdir = d['sep'] and path.join(d['path'], 'source') or d['path']
srcdir = path.join(d['path'], 'source') if d['sep'] else d['path']
ensuredir(srcdir)
if d['sep']:
@ -405,15 +405,15 @@ def generate(d: Dict, overwrite: bool = True, silent: bool = False, templatedir:
batchfile_template = 'quickstart/make.bat_t'
if d['makefile'] is True:
d['rsrcdir'] = d['sep'] and 'source' or '.'
d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build'
d['rsrcdir'] = 'source' if d['sep'] else '.'
d['rbuilddir'] = 'build' if d['sep'] else d['dot'] + 'build'
# use binary mode, to avoid writing \r\n on Windows
write_file(path.join(d['path'], 'Makefile'),
template.render(makefile_template, d), '\n')
if d['batchfile'] is True:
d['rsrcdir'] = d['sep'] and 'source' or '.'
d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build'
d['rsrcdir'] = 'source' if d['sep'] else '.'
d['rbuilddir'] = 'build' if d['sep'] else d['dot'] + 'build'
write_file(path.join(d['path'], 'make.bat'),
template.render(batchfile_template, d), '\r\n')

View File

@ -4,7 +4,7 @@
Build configuration file handling.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -14,7 +14,9 @@ import types
import warnings
from collections import OrderedDict
from os import path, getenv
from typing import Any, NamedTuple, Union
from typing import (
Any, Callable, Dict, Generator, Iterator, List, NamedTuple, Set, Tuple, Union
)
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.errors import ConfigError, ExtensionError
@ -23,14 +25,13 @@ from sphinx.util import logging
from sphinx.util.i18n import format_date
from sphinx.util.osutil import cd
from sphinx.util.pycompat import execfile_
from sphinx.util.tags import Tags
from sphinx.util.typing import NoneType
if False:
# For type annotation
from typing import Callable, Dict, Generator, Iterator, List, Set, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.util.tags import Tags # NOQA
from sphinx.application import Sphinx
from sphinx.environment import BuildEnvironment
logger = logging.getLogger(__name__)
@ -43,8 +44,7 @@ ConfigValue = NamedTuple('ConfigValue', [('name', str),
('rebuild', Union[bool, str])])
def is_serializable(obj):
# type: (Any) -> bool
def is_serializable(obj: Any) -> bool:
"""Check if object is serializable or not."""
if isinstance(obj, UNSERIALIZABLE_TYPES):
return False
@ -64,12 +64,10 @@ class ENUM:
Example:
app.add_config_value('latex_show_urls', 'no', None, ENUM('no', 'footnote', 'inline'))
"""
def __init__(self, *candidates):
# type: (str) -> None
def __init__(self, *candidates: str) -> None:
self.candidates = candidates
def match(self, value):
# type: (Union[str, List, Tuple]) -> bool
def match(self, value: Union[str, List, Tuple]) -> bool:
if isinstance(value, (list, tuple)):
return all(item in self.candidates for item in value)
else:
@ -148,6 +146,7 @@ class Config:
'math_numfig': (True, 'env', []),
'tls_verify': (True, 'env', []),
'tls_cacerts': (None, 'env', []),
'user_agent': (None, 'env', [str]),
'smartquotes': (True, 'env', []),
'smartquotes_action': ('qDe', 'env', []),
'smartquotes_excludes': ({'languages': ['ja'],
@ -155,36 +154,39 @@ class Config:
'env', []),
} # type: Dict[str, Tuple]
def __init__(self, config={}, overrides={}):
# type: (Dict[str, Any], Dict[str, Any]) -> None
self.overrides = overrides
def __init__(self, config: Dict[str, Any] = {}, overrides: Dict[str, Any] = {}) -> None:
self.overrides = dict(overrides)
self.values = Config.config_values.copy()
self._raw_config = config
self.setup = config.get('setup', None) # type: Callable
if 'extensions' in overrides:
if isinstance(overrides['extensions'], str):
config['extensions'] = overrides.pop('extensions').split(',')
if 'extensions' in self.overrides:
if isinstance(self.overrides['extensions'], str):
config['extensions'] = self.overrides.pop('extensions').split(',')
else:
config['extensions'] = overrides.pop('extensions')
config['extensions'] = self.overrides.pop('extensions')
self.extensions = config.get('extensions', []) # type: List[str]
@classmethod
def read(cls, confdir, overrides=None, tags=None):
# type: (str, Dict, Tags) -> Config
def read(cls, confdir: str, overrides: Dict = None, tags: Tags = None) -> "Config":
"""Create a Config object from configuration file."""
filename = path.join(confdir, CONFIG_FILENAME)
namespace = eval_config_file(filename, tags)
return cls(namespace, overrides or {})
def convert_overrides(self, name, value):
# type: (str, Any) -> Any
def convert_overrides(self, name: str, value: Any) -> Any:
if not isinstance(value, str):
return value
else:
defvalue = self.values[name][0]
if self.values[name][2] == Any:
return value
elif type(defvalue) is bool or self.values[name][2] == [bool]:
if value == '0':
# given falsy string from command line option
return False
else:
return bool(value)
elif isinstance(defvalue, dict):
raise ValueError(__('cannot override dictionary config setting %r, '
'ignoring (use %r to set individual elements)') %
@ -205,8 +207,7 @@ class Config:
else:
return value
def pre_init_values(self):
# type: () -> None
def pre_init_values(self) -> None:
"""
Initialize some limited config variables before initialize i18n and loading extensions
"""
@ -220,8 +221,7 @@ class Config:
except ValueError as exc:
logger.warning("%s", exc)
def init_values(self):
# type: () -> None
def init_values(self) -> None:
config = self._raw_config
for valname, value in self.overrides.items():
try:
@ -243,8 +243,7 @@ class Config:
if name in self.values:
self.__dict__[name] = config[name]
def __getattr__(self, name):
# type: (str) -> Any
def __getattr__(self, name: str) -> Any:
if name.startswith('_'):
raise AttributeError(name)
if name not in self.values:
@ -254,42 +253,34 @@ class Config:
return default(self)
return default
def __getitem__(self, name):
# type: (str) -> str
def __getitem__(self, name: str) -> str:
return getattr(self, name)
def __setitem__(self, name, value):
# type: (str, Any) -> None
def __setitem__(self, name: str, value: Any) -> None:
setattr(self, name, value)
def __delitem__(self, name):
# type: (str) -> None
def __delitem__(self, name: str) -> None:
delattr(self, name)
def __contains__(self, name):
# type: (str) -> bool
def __contains__(self, name: str) -> bool:
return name in self.values
def __iter__(self):
# type: () -> Generator[ConfigValue, None, None]
def __iter__(self) -> Generator[ConfigValue, None, None]:
for name, value in self.values.items():
yield ConfigValue(name, getattr(self, name), value[1])
def add(self, name, default, rebuild, types):
# type: (str, Any, Union[bool, str], Any) -> None
def add(self, name: str, default: Any, rebuild: Union[bool, str], types: Any) -> None:
if name in self.values:
raise ExtensionError(__('Config value %r already present') % name)
else:
self.values[name] = (default, rebuild, types)
def filter(self, rebuild):
# type: (Union[str, List[str]]) -> Iterator[ConfigValue]
def filter(self, rebuild: Union[str, List[str]]) -> Iterator[ConfigValue]:
if isinstance(rebuild, str):
rebuild = [rebuild]
return (value for value in self if value.rebuild in rebuild)
def __getstate__(self):
# type: () -> Dict
def __getstate__(self) -> Dict:
"""Obtains serializable data for pickling."""
# remove potentially pickling-problematic values from config
__dict__ = {}
@ -312,13 +303,11 @@ class Config:
return __dict__
def __setstate__(self, state):
# type: (Dict) -> None
def __setstate__(self, state: Dict) -> None:
self.__dict__.update(state)
def eval_config_file(filename, tags):
# type: (str, Tags) -> Dict[str, Any]
def eval_config_file(filename: str, tags: Tags) -> Dict[str, Any]:
"""Evaluate a config file."""
namespace = {} # type: Dict[str, Any]
namespace['__file__'] = filename
@ -335,6 +324,9 @@ def eval_config_file(filename, tags):
msg = __("The configuration file (or one of the modules it imports) "
"called sys.exit()")
raise ConfigError(msg)
except ConfigError:
# pass through ConfigError from conf.py as is. It will be shown in console.
raise
except Exception:
msg = __("There is a programmable error in your configuration file:\n\n%s")
raise ConfigError(msg % traceback.format_exc())
@ -342,8 +334,7 @@ def eval_config_file(filename, tags):
return namespace
def convert_source_suffix(app, config):
# type: (Sphinx, Config) -> None
def convert_source_suffix(app: "Sphinx", config: Config) -> None:
"""This converts old styled source_suffix to new styled one.
* old style: str or list
@ -368,8 +359,7 @@ def convert_source_suffix(app, config):
"But `%r' is given." % source_suffix))
def init_numfig_format(app, config):
# type: (Sphinx, Config) -> None
def init_numfig_format(app: "Sphinx", config: Config) -> None:
"""Initialize :confval:`numfig_format`."""
numfig_format = {'section': _('Section %s'),
'figure': _('Fig. %s'),
@ -381,8 +371,7 @@ def init_numfig_format(app, config):
config.numfig_format = numfig_format # type: ignore
def correct_copyright_year(app, config):
# type: (Sphinx, Config) -> None
def correct_copyright_year(app: "Sphinx", config: Config) -> None:
"""correct values of copyright year that are not coherent with
the SOURCE_DATE_EPOCH environment variable (if set)
@ -395,8 +384,7 @@ def correct_copyright_year(app, config):
config[k] = copyright_year_re.sub(replace, config[k])
def check_confval_types(app, config):
# type: (Sphinx, Config) -> None
def check_confval_types(app: "Sphinx", config: Config) -> None:
"""check all values for deviation from the default value's type, since
that can result in TypeErrors all over the place NB.
"""
@ -451,8 +439,7 @@ def check_confval_types(app, config):
default=type(default)))
def check_unicode(config):
# type: (Config) -> None
def check_unicode(config: Config) -> None:
"""check all string values for non-ASCII characters in bytestrings,
since that can result in UnicodeErrors all over the place
"""
@ -468,16 +455,15 @@ def check_unicode(config):
'Please use Unicode strings, e.g. %r.'), name, 'Content')
def check_primary_domain(app, config):
# type: (Sphinx, Config) -> None
def check_primary_domain(app: "Sphinx", config: Config) -> None:
primary_domain = config.primary_domain
if primary_domain and not app.registry.has_domain(primary_domain):
logger.warning(__('primary_domain %r not found, ignored.'), primary_domain)
config.primary_domain = None # type: ignore
def check_master_doc(app, env, added, changed, removed):
# type: (Sphinx, BuildEnvironment, Set[str], Set[str], Set[str]) -> Set[str]
def check_master_doc(app: "Sphinx", env: "BuildEnvironment", added: Set[str],
changed: Set[str], removed: Set[str]) -> Set[str]:
"""Adjust master_doc to 'contents' to support an old project which does not have
no master_doc setting.
"""
@ -491,13 +477,12 @@ def check_master_doc(app, env, added, changed, removed):
return changed
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
app.connect('config-inited', convert_source_suffix)
app.connect('config-inited', init_numfig_format)
app.connect('config-inited', correct_copyright_year)
app.connect('config-inited', check_confval_types)
app.connect('config-inited', check_primary_domain)
def setup(app: "Sphinx") -> Dict[str, Any]:
app.connect('config-inited', convert_source_suffix, priority=800)
app.connect('config-inited', init_numfig_format, priority=800)
app.connect('config-inited', correct_copyright_year, priority=800)
app.connect('config-inited', check_confval_types, priority=800)
app.connect('config-inited', check_primary_domain, priority=800)
app.connect('env-get-outdated', check_master_doc)
return {

View File

@ -4,17 +4,18 @@
Sphinx deprecation classes and utilities.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys
import warnings
from importlib import import_module
from typing import Any, Dict
if False:
# For type annotation
from typing import Any, Dict, Type # NOQA
from typing import Type # for python3.5.1
class RemovedInSphinx40Warning(DeprecationWarning):
@ -28,25 +29,20 @@ class RemovedInSphinx50Warning(PendingDeprecationWarning):
RemovedInNextVersionWarning = RemovedInSphinx40Warning
def deprecated_alias(modname, objects, warning):
# type: (str, Dict, Type[Warning]) -> None
module = sys.modules.get(modname)
if module is None:
module = import_module(modname)
def deprecated_alias(modname: str, objects: Dict, warning: "Type[Warning]") -> None:
module = import_module(modname)
sys.modules[modname] = _ModuleWrapper(module, modname, objects, warning) # type: ignore
class _ModuleWrapper:
def __init__(self, module, modname, objects, warning):
# type: (Any, str, Dict, Type[Warning]) -> None
def __init__(self, module: Any, modname: str, objects: Dict, warning: "Type[Warning]"
) -> None:
self._module = module
self._modname = modname
self._objects = objects
self._warning = warning
def __getattr__(self, name):
# type: (str) -> Any
def __getattr__(self, name: str) -> Any:
if name in self._objects:
warnings.warn("%s.%s is deprecated. Check CHANGES for Sphinx "
"API modifications." % (self._modname, name),
@ -59,33 +55,27 @@ class _ModuleWrapper:
class DeprecatedDict(dict):
"""A deprecated dict which warns on each access."""
def __init__(self, data, message, warning):
# type: (Dict, str, Type[Warning]) -> None
def __init__(self, data: Dict, message: str, warning: "Type[Warning]") -> None:
self.message = message
self.warning = warning
super().__init__(data)
def __setitem__(self, key, value):
# type: (str, Any) -> None
def __setitem__(self, key: str, value: Any) -> None:
warnings.warn(self.message, self.warning, stacklevel=2)
super().__setitem__(key, value)
def setdefault(self, key, default=None):
# type: (str, Any) -> None
def setdefault(self, key: str, default: Any = None) -> Any:
warnings.warn(self.message, self.warning, stacklevel=2)
return super().setdefault(key, default)
def __getitem__(self, key):
# type: (str) -> None
def __getitem__(self, key: str) -> None:
warnings.warn(self.message, self.warning, stacklevel=2)
return super().__getitem__(key)
def get(self, key, default=None):
# type: (str, Any) -> None
def get(self, key: str, default: Any = None) -> Any:
warnings.warn(self.message, self.warning, stacklevel=2)
return super().get(key, default)
def update(self, other=None): # type: ignore
# type: (Dict) -> None
def update(self, other: Dict) -> None: # type: ignore
warnings.warn(self.message, self.warning, stacklevel=2)
super().update(other)

Some files were not shown because too many files have changed in this diff Show More