Merge remote-tracking branch 'upstream/master'

Conflicts:
	sphinx/application.py
	sphinx/builders/html.py
This commit is contained in:
Jellby 2016-12-06 19:04:58 +01:00
commit 6ce1bb1f00
347 changed files with 21676 additions and 10771 deletions

2
.gitignore vendored
View File

@ -4,6 +4,7 @@
*.swp
.dir-locals.el
.mypy_cache/
.ropeproject/
TAGS
.tags
@ -19,3 +20,4 @@ Sphinx.egg-info/
doc/_build/
tests/.coverage
tests/build/
utils/regression_test.js

View File

@ -7,11 +7,13 @@ python:
- "2.7"
- "3.4"
- "3.5"
- "3.5-dev"
- "nightly"
- "pypy"
env:
global:
- TEST='-v --with-timer --timer-top-n 25'
- PYTHONFAULTHANDLER=x
- PYTHONWARNINGS=all
matrix:
- DOCUTILS=0.11
- DOCUTILS=0.12
@ -23,6 +25,8 @@ addons:
- texlive-latex-extra
- texlive-fonts-recommended
- texlive-fonts-extra
- texlive-xetex
- lmodern
install:
- pip install -U pip setuptools
- pip install docutils==$DOCUTILS

View File

@ -20,6 +20,7 @@ Other contributors, listed alphabetically, are:
* Jakob Lykke Andersen -- Rewritten C++ domain
* Henrique Bastos -- SVG support for graphviz extension
* Daniel Bültmann -- todo extension
* Jean-François Burnol -- LaTeX improvements
* Etienne Desautels -- apidoc module
* Michael Droettboom -- inheritance_diagram extension
* Charles Duffy -- original graphviz extension
@ -44,10 +45,11 @@ Other contributors, listed alphabetically, are:
* Glenn Matthews -- python domain signature improvements
* Roland Meister -- epub builder
* Ezio Melotti -- collapsible sidebar JavaScript
* Bruce Mitchener -- Minor epub improvement
* Daniel Neuhäuser -- JavaScript domain, Python 3 support (GSOC)
* Christopher Perkins -- autosummary integration
* Benjamin Peterson -- unittests
* T. Powers -- HTML output improvements
* \T. Powers -- HTML output improvements
* Jeppe Pihl -- literalinclude improvements
* Rob Ruana -- napoleon extension
* Stefan Seefeld -- toctree improvements
@ -65,7 +67,6 @@ Other contributors, listed alphabetically, are:
* Michael Wilson -- Intersphinx HTTP basic auth support
* Joel Wurtz -- cellspanning support in LaTeX
* Hong Xu -- svg support in imgmath extension and various bug fixes
* Bruce Mitchener -- Minor epub improvement
Many thanks for all contributions!

192
CHANGES
View File

@ -1,5 +1,5 @@
Release 1.5 alpha2 (in development)
===================================
Release 1.6 (in development)
============================
Incompatible changes
--------------------
@ -7,19 +7,19 @@ Incompatible changes
Features added
--------------
* #3136: Add ``:name:`` option to the directives in ``sphinx.ext.graphviz``
Bugs fixed
----------
Documentation
-------------
Release 1.5 alpha1 (released Sep 21, 2016)
==========================================
Release 1.5 (released Dec 5, 2016)
==================================
Incompatible changes
--------------------
1.5a1
* latex, package fancybox is not longer a dependency of sphinx.sty
* Use ``'locales'`` as a default value of `locale_dirs`
* latex, package ifthen is not any longer a dependency of sphinx.sty
@ -65,11 +65,49 @@ Incompatible changes
* Drop python 2.6 and 3.3 support
* Drop epub3 builder's ``epub3_page_progression_direction`` option (use ``epub3_writing_mode``).
* #2877: Rename ``latex_elements['footer']`` to
``latex_elements['postpreamble']``
``latex_elements['atendofbody']``
1.5a2
* #2983: Rename ``epub3_description`` and ``epub3_contributor`` to
``epub_description`` and ``epub_contributor``.
* Remove themes/basic/defindex.html; no longer used
* Sphinx does not ship anymore (but still uses) LaTeX style file ``fncychap``
* #2435: Slim down quickstarted conf.py
* The ``sphinx.sty`` latex package does not load itself "hyperref", as this
is done later in the preamble of the latex output via ``'hyperref'`` key.
* Sphinx does not ship anymore a custom modified LaTeX style file ``tabulary``.
The non-modified package is used.
* #3057: By default, footnote marks in latex PDF output are not preceded by a
space anymore, ``\sphinxBeforeFootnote`` allows user customization if needed.
1.5 final
* #2986: ``themes/basic/defindex.html`` is now deprecated
* Emit warnings that will be deprecated in Sphinx 1.6 by default.
Users can change the behavior by setting the environment variable
PYTHONWARNINGS. Please refer :ref:`when-deprecation-warnings-are-displayed`.
Deprecated
----------
These features are removed in Sphinx-1.6:
* LDML format support in i18n feature
* ``sphinx.addnodes.termsep``
* Some functions and classes in ``sphinx.util.pycompat``:
``zip_longest``, ``product``, ``all``, ``any``, ``next``, ``open``,
``class_types``, ``base_exception``, ``relpath``, ``StringIO``, ``BytesIO``.
Please use the standard library version instead;
If any deprecation warning like ``RemovedInSphinxXXXWarning`` are displayed,
please refer :ref:`when-deprecation-warnings-are-displayed`.
Features added
--------------
1.5a1
* #2951: Add ``--implicit-namespaces`` PEP-0420 support to apidoc.
* Add ``:caption:`` option for sphinx.ext.inheritance_diagram.
* #2471: Add config variable for default doctest flags.
@ -139,9 +177,52 @@ Features added
* #326: `numref` role can also refer sections
* #2916: `numref` role can also refer caption as an its linktext
1.5a2
* #3008: ``linkcheck`` builder ignores self-signed certificate URL
* #3020: new ``'geometry'`` key to ``latex_elements`` whose default uses
LaTeX style file ``geometry.sty`` to set page layout
* #2843: Add :start-at: and :end-at: options to literalinclude directive
* #2527: Add ``:reversed:`` option to toctree directive
* Add ``-t`` and ``-d`` option to ``sphinx-quickstart`` to support templating
generated sphinx project.
* #3028: Add ``{path}`` and ``{basename}`` to the format of
``figure_language_filename``
* new ``'hyperref'`` key in the ``latex_elements`` dictionary (ref #3030)
* #3022: Allow code-blocks in footnotes for LaTeX PDF output
1.5b1
* #2513: A better default settings for XeLaTeX
* #3096: ``'maxlistdepth'`` key to work around LaTeX list limitations
* #3060: autodoc supports documentation for attributes of Enum class. Now autodoc render
just the value of Enum attributes instead of Enum attribute representation.
* Add ``--extensions`` to ``sphinx-quickstart`` to support enable arbitrary
extensions from command line (ref: #2904)
* #3104, #3122: ``'sphinxsetup'`` for key=value styling of Sphinx LaTeX
* #3071: Autodoc: Allow mocked module decorators to pass-through functions
unchanged
* #2495: linkcheck: Allow skipping anchor checking using
:confval:`linkcheck_anchors_ignore`
* #3083: let Unicode no-break space act like LaTeX ``~`` (fixed #3019)
* #3116: allow word wrap in PDF output for inline literals (ref #3110)
* #930: sphinx-apidoc allow wildcards for excluding paths. Thanks to Nick Coghlan.
* #3121: add ``inlineliteralwraps`` option to control if inline literal
word-wraps in latex
1.5 final
* #3095: Add :confval:`tls_verify` and :confval:`tls_cacerts` to support
self-signed HTTPS servers in linkcheck and intersphinx
* #2215: make.bat generated by sphinx-quickstart can be called from another dir.
Thanks to Timotheus Kampik.
* #3185: Add new warning type ``misc.highlighting_failure``
Bugs fixed
----------
1.5a1
* #2707: (latex) the column width is badly computed for tabular
* #2799: Sphinx installs roles and directives automatically on importing sphinx
module. Now Sphinx installs them on running application.
@ -159,8 +240,97 @@ Bugs fixed
* #2550: external links are opened in help viewer
* #2687: Running Sphinx multiple times produces 'already registered' warnings
Release 1.4.7 (in development)
==============================
1.5a2
* #2810: Problems with pdflatex in an Italian document
* Use ``latex_elements.papersize`` to specify papersize of LaTeX in Makefile
* #2988: linkcheck: retry with GET request if denied HEAD request
* #2990: linkcheck raises "Can't convert 'bytes' object to str implicitly" error
if linkcheck_anchors enabled
* #3004: Invalid link types "top" and "up" are used
* #3009: Bad rendering of parsed-literals in LaTeX since Sphinx 1.4.4
* #3000: ``option`` directive generates invalid HTML anchors
* #2984: Invalid HTML has been generated if `html_split_index` enabled
* #2986: themes/basic/defindex.html should be changed for html5 friendly
* #2987: Invalid HTML has been generated if multiple IDs are assigned to a list
* #2891: HTML search does not provide all the results
* #1986: Title in PDF Output
* #147: Problem with latex chapter style
* #3018: LaTeX problem with page layout dimensions and chapter titles
* Fix an issue with ``\pysigline`` in LaTeX style file (ref #3023)
* #3038: ``sphinx.ext.math*`` raises TypeError if labels are duplicated
* #3031: incompatibility with LaTeX package ``tocloft``
* #3003: literal blocks in footnotes are not supported by Latex
* #3047: spacing before footnote in pdf output is not coherent and allows breaks
* #3045: HTML search index creator should ignore "raw" content if now html
* #3039: English stemmer returns wrong word if the word is capitalized
* Fix make-mode Makefile template (ref #3056, #2936)
1.5b1
* #2432: Fix unwanted * between varargs and keyword only args. Thanks to Alex Grönholm.
* #3062: Failed to build PDF using 1.5a2 (undefined ``\hypersetup`` for
Japanese documents since PR#3030)
* Better rendering of multiline signatures in html.
* #777: LaTeX output "too deeply nested" (ref #3096)
* Let LaTeX image inclusion obey ``scale`` before textwidth fit (ref #2865, #3059)
* #3019: LaTeX fails on description of C function with arguments (ref #3083)
* fix latex inline literals where ``< > -`` gobbled a space
1.5 final
* #3069: Even if ``'babel'`` key is set to empty string, LaTeX output contains
one ``\addto\captions...``
* #3123: user ``'babel'`` key setting is not obeyed anymore
* #3155: Fix JavaScript for `html_sourcelink_suffix` fails with IE and Opera
* #3085: keep current directory after breaking build documentation. Thanks to
Timotheus Kampik.
* #3181: pLaTeX crashes with a section contains endash
* #3180: latex: add stretch/shrink between successive singleline or
multipleline cpp signatures (ref #3072)
* #3128: globing images does not support .svgz file
* #3015: fix a broken test on Windows.
* #1843: Fix documentation of descriptor classes that have a custom metaclass.
Thanks to Erik Bray.
* #3190: util.split_docinfo fails to parse multi-line field bodies
* #3024, #3037: In Python3, application.Sphinx._log crushed when the log message cannot
be encoded into console encoding.
Testing
--------
* To simplify, sphinx uses external mock package even if unittest.mock exists.
Release 1.4.9 (released Nov 23, 2016)
=====================================
Bugs fixed
----------
* #2936: Fix doc/Makefile that can't build man because doc/man exists
* #3058: Using the same 'caption' attribute in multiple 'toctree' directives
results in warning / error
* #3068: Allow the '=' character in the -D option of sphinx-build.py
* #3074: ``add_source_parser()`` crashes in debug mode
* #3135: ``sphinx.ext.autodoc`` crashes with plain Callable
* #3150: Fix query word splitter in JavaScript. It behaves as same as Python's regular expression.
* #3093: gettext build broken on substituted images.
* #3093: gettext build broken on image node under ``note`` directive.
* imgmath: crashes on showing error messages if image generation failed
* #3117: LaTeX writer crashes if admonition is placed before first section title
* #3164: Change search order of ``sphinx.ext.inheritance_diagram``
Release 1.4.8 (released Oct 1, 2016)
====================================
Bugs fixed
----------
* #2996: The wheel package of Sphinx got crash with ImportError
Release 1.4.7 (released Oct 1, 2016)
====================================
Bugs fixed
----------

View File

@ -94,6 +94,7 @@ Documentation using a customized version of the classic theme
* NumPy: http://docs.scipy.org/doc/numpy/reference/
* OpenCV: http://docs.opencv.org/
* Peach^3: http://peach3.nl/doc/latest/userdoc/
* Pygame: http://www.pygame.org/docs/
* Sage: http://www.sagemath.org/doc/
* SciPy: http://docs.scipy.org/doc/scipy/reference/
* simuPOP: http://simupop.sourceforge.net/manual_release/build/userGuide.html
@ -134,6 +135,7 @@ Documentation using another builtin theme
* jsFiddle: http://doc.jsfiddle.net/ (nature)
* libLAS: http://www.liblas.org/ (nature)
* Linguistica: http://linguistica-uchicago.github.io/lxa5/ (sphinx_rtd_theme)
* MoinMoin: https://moin-20.readthedocs.io/en/latest/ (sphinx_rtd_theme)
* MPipe: http://vmlaker.github.io/mpipe/ (sphinx13)
* pip: https://pip.pypa.io/en/latest/ (sphinx_rtd_theme)
* Pyramid web framework:

View File

@ -1,6 +1,6 @@
PYTHON ?= python
.PHONY: all style-check clean clean-pyc clean-patchfiles clean-backupfiles \
.PHONY: all style-check type-check clean clean-pyc clean-patchfiles clean-backupfiles \
clean-generated pylint reindent test covertest build
DONT_CHECK = -i build -i dist -i sphinx/style/jquery.js \
@ -30,12 +30,15 @@ DONT_CHECK = -i build -i dist -i sphinx/style/jquery.js \
-i sphinx/search/tr.py \
-i .tox
all: clean-pyc clean-backupfiles style-check test
all: clean-pyc clean-backupfiles style-check type-check test
style-check:
@$(PYTHON) utils/check_sources.py $(DONT_CHECK) .
clean: clean-pyc clean-pycache clean-patchfiles clean-backupfiles clean-generated clean-testfiles
type-check:
mypy sphinx/
clean: clean-pyc clean-pycache clean-patchfiles clean-backupfiles clean-generated clean-testfiles clean-buildfiles
clean-pyc:
find . -name '*.pyc' -exec rm -f {} +
@ -59,6 +62,9 @@ clean-testfiles:
rm -rf tests/build
rm -rf .tox/
clean-buildfiles:
rm -rf build
pylint:
@pylint --rcfile utils/pylintrc sphinx

View File

@ -8,11 +8,13 @@ SPHINXPROJ = sphinx
SOURCEDIR = .
BUILDDIR = _build
# Has to be explicit, otherwise we don't get "make" without targets right.
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%:
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

360
doc/_static/conf.py.txt vendored Normal file
View File

@ -0,0 +1,360 @@
# -*- coding: utf-8 -*-
#
# test documentation build configuration file, created by
# sphinx-quickstart on Sun Jun 26 00:00:43 2016.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'test'
copyright = u'2016, test'
author = u'test'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'test'
# The full version, including alpha/beta/rc tags.
release = u'test'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#
# today = ''
#
# Else, today_fmt is used as the format for a strftime call.
#
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#
# html_title = u'test vtest'
# A shorter title for the navigation bar. Default is the same as html_title.
#
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#
# html_logo = None
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#
# html_extra_path = []
# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
#
# html_last_updated_fmt = None
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#
# html_additional_pages = {}
# If false, no module index is generated.
#
# html_domain_indices = True
# If false, no index is generated.
#
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
#
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
#
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'testdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'test.tex', u'test Documentation',
u'test', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#
# latex_use_parts = False
# If true, show page references after internal links.
#
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#
# latex_appendices = []
# If false, will not define \strong, \code, \titleref, \crossref ... but only
# \sphinxstrong, ..., \sphinxtitleref, ... to help avoid clash with user added
# packages.
#
# latex_keep_old_macro_names = True
# If false, no module index is generated.
#
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'test', u'test Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'test', u'test Documentation',
author, 'test', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#
# texinfo_appendices = []
# If false, no module index is generated.
#
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#
# texinfo_no_detailmenu = False
# -- A random example -----------------------------------------------------
import sys, os
sys.path.insert(0, os.path.abspath('.'))
exclude_patterns = ['zzz']
numfig = True
#language = 'ja'
extensions.append('sphinx.ext.todo')
extensions.append('sphinx.ext.autodoc')
#extensions.append('sphinx.ext.autosummary')
extensions.append('sphinx.ext.intersphinx')
extensions.append('sphinx.ext.mathjax')
extensions.append('sphinx.ext.viewcode')
extensions.append('sphinx.ext.graphviz')
autosummary_generate = True
html_theme = 'default'
#source_suffix = ['.rst', '.txt']

View File

@ -384,6 +384,10 @@ div.warning ul, div.warning ol {
padding: 0;
}
div.admonition div.highlight {
background: none;
}
.viewcode-back {
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
'Verdana', sans-serif;

View File

@ -48,13 +48,14 @@ epub_max_image_width = 0
epub_show_urls = 'inline'
epub_use_index = False
epub_guide = (('toc', 'contents.xhtml', u'Table of Contents'),)
epub3_description = 'Sphinx documentation generator system manual'
epub_description = 'Sphinx documentation generator system manual'
latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',
'Georg Brandl', 'manual', 1)]
latex_logo = '_static/sphinx.png'
latex_elements = {
'fontpkg': '\\usepackage{palatino}',
'passoptionstopackages': '\\PassOptionsToPackage{svgnames}{xcolor}',
}
latex_show_urls = 'footnote'

View File

@ -40,7 +40,7 @@ Important points to note:
delete them from the namespace with ``del`` if appropriate. Modules are
removed automatically, so you don't need to ``del`` your imports after use.
.. _conf-tags:
.. _conf-tags:
* There is a special object named ``tags`` available in the config file.
It can be used to query and change the tags (see :ref:`tags`). Use
@ -232,6 +232,7 @@ General configuration
* ref.option
* ref.citation
* ref.doc
* misc.highlighting_failure
You can choose from these types.
@ -239,6 +240,10 @@ General configuration
.. versionadded:: 1.4
.. versionchanged:: 1.5
Added ``misc.highlighting_failure``
.. confval:: needs_sphinx
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
@ -288,7 +293,8 @@ General configuration
.. note::
LaTeX builder always assign numbers whether this option is enabled or not.
The LaTeX builder always assigns numbers whether this option is enabled or
not.
.. versionadded:: 1.3
@ -296,8 +302,7 @@ General configuration
A dictionary mapping ``'figure'``, ``'table'``, ``'code-block'`` and
``'section'`` to strings that are used for format of figure numbers.
As a special character, `%s` and `{number}` will be replaced to figure
number. `{name}` will be replaced to figure caption.
As a special character, `%s` will be replaced to figure number.
Default is to use ``'Fig. %s'`` for ``'figure'``, ``'Table %s'`` for
``'table'``, ``'Listing %s'`` for ``'code-block'`` and ``'Section'`` for
@ -305,9 +310,6 @@ General configuration
.. versionadded:: 1.3
.. versionchanged:: 1.5
Support format of section. Allow to refer the caption of figures.
.. confval:: numfig_secnum_depth
The scope of figure numbers, that is, the numfig feature numbers figures
@ -317,6 +319,21 @@ General configuration
.. versionadded:: 1.3
.. confval:: tls_verify
If true, Sphinx verifies server certifications. Default is ``True``.
.. versionadded:: 1.5
.. confval:: tls_cacerts
A path to a certification file of CA or a path to directory which
contains the certificates. This also allows a dictionary mapping
hostname to the path to certificate file.
The certificates are used to verify server certifications.
.. versionadded:: 1.5
Project information
-------------------
@ -599,9 +616,25 @@ documentation on :ref:`intl` for details.
The filename format for language-specific figures. The default value is
``{root}.{language}{ext}``. It will be expanded to
``dirname/filename.en.png`` from ``.. image:: dirname/filename.png``.
The available format tokens are:
* ``{root}`` - the filename, including any path component, without the file
extension, e.g. ``dirname/filename``
* ``{path}`` - the directory path component of the filename, with a trailing
slash if non-empty, e.g. ``dirname/``
* ``{basename}`` - the filename without the directory path or file extension
components, e.g. ``filename``
* ``{ext}`` - the file extension, e.g. ``.png``
* ``{language}`` - the translation language, e.g. ``en``
For example, setting this to ``{path}{language}/{basename}{ext}`` will
expand to ``dirname/en/filename.png`` instead.
.. versionadded:: 1.4
.. versionchanged:: 1.5
Added ``{path}`` and ``{basename}`` tokens.
.. _html-options:
Options for HTML output
@ -1289,18 +1322,21 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
The title of the document. It defaults to the :confval:`html_title` option
but can be set independently for epub creation.
.. confval:: epub3_description
.. confval:: epub_description
The description of the document. The default value is ``''``.
.. versionadded:: 1.4
.. versionchanged:: 1.5
Renamed from ``epub3_description``
.. confval:: epub_author
The author of the document. This is put in the Dublin Core metadata. The
default value is ``'unknown'``.
.. confval:: epub3_contributor
.. confval:: epub_contributor
The name of a person, organization, etc. that played a secondary role in
the creation of the content of an EPUB Publication. The default value is
@ -1308,6 +1344,9 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
.. versionadded:: 1.4
.. versionchanged:: 1.5
Renamed from ``epub3_contributor``
.. confval:: epub_language
The language of the document. This is put in the Dublin Core metadata. The
@ -1467,7 +1506,7 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
.. versionadded:: 1.2
.. confval:: epub3_writing_mode
.. confval:: epub_writing_mode
It specifies writing direction. It can accept ``'horizontal'`` (default) and
``'vertical'``
@ -1476,7 +1515,7 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
:header-rows: 1
:stub-columns: 1
- * ``epub3_writing_mode``
- * ``epub_writing_mode``
* ``'horizontal'``
* ``'vertical'``
- * writing-mode [#]_
@ -1503,7 +1542,7 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
.. versionadded:: 1.4
.. deprecated:: 1.5
Use ``epub3_writing_mode``.
Use ``epub_writing_mode`` instead.
.. _latex-options:
@ -1517,10 +1556,10 @@ These options influence LaTeX output. See further :doc:`latex`.
The LaTeX engine to build the docs. The setting can have the following
values:
* pdflatex -- PDFLaTeX (default)
* xelatex -- XeLaTeX
* lualatex -- LuaLaTeX
* platex -- pLaTeX (default if `language` is 'ja')
* ``'pdflatex'`` -- PDFLaTeX (default)
* ``'xelatex'`` -- XeLaTeX
* ``'lualatex'`` -- LuaLaTeX
* ``'platex'`` -- pLaTeX (default if :confval:`language` is ``'ja'``)
.. confval:: latex_documents
@ -1540,11 +1579,13 @@ These options influence LaTeX output. See further :doc:`latex`.
* *author*: Author for the LaTeX document. The same LaTeX markup caveat as
for *title* applies. Use ``\and`` to separate multiple authors, as in:
``'John \and Sarah'``.
* *documentclass*: Normally, one of ``'manual'`` or ``'howto'`` (provided by
Sphinx). Other document classes can be given, but they must include the
"sphinx" package in order to define Sphinx's custom LaTeX commands. "howto"
documents will not get appendices. Also, howtos will have a simpler title
page.
* *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.
* *toctree_only*: Must be ``True`` or ``False``. If true, the *startdoc*
document itself is not included in the output, only the documents
@ -1669,9 +1710,32 @@ These options influence LaTeX output. See further :doc:`latex`.
example ``100px=1in``, one can use ``'0.01in'`` but it is more precise
to use ``'47363sp'``. To obtain ``72px=1in``, use ``'1bp'``.
.. versionadded:: 1.5
``'sphinxsetup'``
A comma separated list of ``key=value`` package options for the Sphinx
LaTeX style, default empty. See :doc:`latex`.
.. versionadded:: 1.5
``'passoptionstopackages'``
A string which will be positioned early in the preamble, designed to
contain ``\\PassOptionsToPackage{options}{foo}`` commands. Default empty.
.. versionadded:: 1.4
``'geometry'``
"geometry" package inclusion, the default definition is:
``'\\usepackage[margin=1in,marginparwidth=0.5in]{geometry}'``.
.. versionadded:: 1.5
``'babel'``
"babel" package inclusion, default ``'\\usepackage{babel}'``.
"babel" package inclusion, default ``'\\usepackage{babel}'`` (the
suitable document language string is passed as class option, and
``english`` is used if no language.) For Japanese documents, the
default is the empty string.
.. versionchanged:: 1.5
For :confval:`latex_engine` set to ``'xelatex'``, the default
is ``'\\usepackage{polyglossia}\n\\setmainlanguage{<language>}'``.
``'fontpkg'``
Font package inclusion, default ``'\\usepackage{times}'`` (which uses
Times and Helvetica). You can set this to ``''`` to use the Computer
@ -1680,21 +1744,22 @@ These options influence LaTeX output. See further :doc:`latex`.
.. versionchanged:: 1.2
Defaults to ``''`` when the :confval:`language` uses the Cyrillic
script.
.. versionchanged:: 1.5
Defaults to ``''`` when :confval:`latex_engine` is ``'xelatex'``.
``'fncychap'``
Inclusion of the "fncychap" package (which makes fancy chapter titles),
default ``'\\usepackage[Bjarne]{fncychap}'`` for English documentation,
default ``'\\usepackage[Bjarne]{fncychap}'`` for English documentation
(this option is slightly customized by Sphinx),
``'\\usepackage[Sonny]{fncychap}'`` for internationalized docs (because
the "Bjarne" style uses numbers spelled out in English). Other
"fncychap" styles you can try include "Lenny", "Glenn", "Conny" and
"Rejne". You can also set this to ``''`` to disable fncychap.
``'passoptionstopackages'``
"PassOptionsToPackage" call, default empty.
.. versionadded:: 1.4
"fncychap" styles you can try are "Lenny", "Glenn", "Conny", "Rejne" and
"Bjornstrup". You can also set this to ``''`` to disable fncychap.
``'preamble'``
Additional preamble content, default empty. See :doc:`latex`.
``'postamble'``
Additional postamble content (before the indices), default empty.
``'atendofbody'``
Additional document content (right before the indices), default empty.
.. versionadded:: 1.5
``'figure_align'``
Latex figure float alignment, default 'htbp' (here, top, bottom, page).
Whenever an image doesn't fit into the current page, it will be
@ -1707,14 +1772,31 @@ These options influence LaTeX output. See further :doc:`latex`.
Additional footer content (before the indices), default empty.
.. deprecated:: 1.5
User ``'postamble'`` key instead.
Use ``'atendofbody'`` key instead.
* Keys that don't need be overridden unless in special cases are:
``'maxlistdepth'``
LaTeX allows by default at most 6 levels for nesting list and
quote-like environments, with at most 4 enumerated lists, and 4 bullet
lists. Setting this key for example to ``'10'`` (as a string) will
allow up to 10 nested levels (of all sorts). Leaving it to the empty
string means to obey the LaTeX default.
.. warning::
- Using this key may prove incompatible with some LaTeX packages
or special document classes which do their own list customization.
- The key setting is silently *ignored* if ``\usepackage{enumitem}``
is executed inside the document preamble. Use then rather the
dedicated commands of this LaTeX package.
.. versionadded:: 1.5
``'inputenc'``
"inputenc" package inclusion, defaults to
``'\\usepackage[utf8]{inputenc}'`` when using pdflatex.
Otherwise unset.
Otherwise empty.
.. versionchanged:: 1.4.3
Previously ``'\\usepackage[utf8]{inputenc}'`` was used for all
@ -1725,16 +1807,41 @@ These options influence LaTeX output. See further :doc:`latex`.
.. versionadded:: 1.2
``'fontenc'``
"fontenc" package inclusion, default ``'\\usepackage[T1]{fontenc}'``.
.. versionchanged:: 1.5
Defaults to ``'\\usepackage{fontspec}'`` when
:confval:`latex_engine` is ``'xelatex'``.
``'hyperref'``
"hyperref" package inclusion; also loads package "hypcap" and issues
``\urlstyle{same}``. This is done after :file:`sphinx.sty` file is
loaded and before executing the contents of ``'preamble'`` key.
.. attention::
Loading of packages "hyperref" and "hypcap" is mandatory.
.. versionadded:: 1.5
Previously this was done from inside :file:`sphinx.sty`.
``'maketitle'``
"maketitle" call, default ``'\\maketitle'``. Override if you want to
"maketitle" call, default ``'\\maketitle'`` (but it has been
redefined by the Sphinx ``manual`` and ``howto`` classes.) Override
if you want to
generate a differently-styled title page.
``'releasename'``
value that prefixes ``'release'`` element on title page, default
``'Release'``.
``'tableofcontents'``
"tableofcontents" call, default ``'\\tableofcontents'``. Override if
"tableofcontents" call, default ``'\\sphinxtableofcontents'`` (it is a
wrapper of unmodified ``\tableofcontents``, which may itself be
customized by user loaded packages.)
Override if
you want to generate a different table of contents or put content
between the title page and the TOC.
.. versionchanged:: 1.5
Previously the meaning of ``\tableofcontents`` itself was modified
by Sphinx. This created an incompatibility with dedicated packages
modifying it also such as "tocloft" or "etoc".
``'transition'``
Commands used to display transitions, default
``'\n\n\\bigskip\\hrule{}\\bigskip\n\n'``. Override if you want to
@ -1744,7 +1851,9 @@ These options influence LaTeX output. See further :doc:`latex`.
``'printindex'``
"printindex" call, the last thing in the file, default
``'\\printindex'``. Override if you want to generate the index
differently or append some content after the index.
differently or append some content after the index. For example
``'\\footnotesize\\raggedright\\printindex'`` is advisable when the
index is full of long entries.
* Keys that are set by other options and therefore should not be overridden
are:
@ -1769,8 +1878,8 @@ These options influence LaTeX output. See further :doc:`latex`.
.. versionchanged:: 1.5
In Japanese docs(`language` is ``ja``), ``'jreport'`` is used for
``'howto'`` and ``'jsbooks'`` is used for ``'manual'`` by default.
In Japanese docs (:confval:`language` is ``'ja'``), by default
``'jreport'`` is used for ``'howto'`` and ``'jsbook'`` for ``'manual'``.
.. confval:: latex_additional_files
@ -2029,6 +2138,17 @@ Options for the linkcheck builder
.. versionadded:: 1.2
.. confval:: linkcheck_anchors_ignore
A list of regular expressions that match URIs that should skip checking
the validity of anchors in links. This allows skipping entire sites, where
anchors are used to control dynamic pages, or just specific anchors within
a page, where javascript is used to add anchors dynamically, or use the
fragment as part of to trigger an internal REST request. Default is
``["/#!"]``.
.. versionadded:: 1.5
Options for the XML builder
---------------------------
@ -2076,3 +2196,8 @@ Options for the C++ domain
.. versionadded:: 1.5
Example of configuration file
=============================
.. literalinclude:: _static/conf.py.txt
:language: python

View File

@ -114,6 +114,11 @@ These are the basic steps needed to start developing on Sphinx.
pip install -r test-reqs.txt
make test
* Again, it's useful to turn on deprecation warnings on so they're shown in
the test output::
PYTHONWARNINGS=all make test
* Build the documentation and check the output for different builders::
cd doc
@ -272,3 +277,55 @@ Debugging Tips
$ npm install
$ node_modules/.bin/grunt build # -> dest/*.global.js
Deprecating a feature
---------------------
There are a couple reasons that code in Sphinx might be deprecated:
* If a feature has been improved or modified in a backwards-incompatible way,
the old feature or behavior will be deprecated.
* Sometimes Sphinx will include a backport of a Python library that's not
included in a version of Python that Sphinx currently supports. When Sphinx
no longer needs to support the older version of Python that doesn't include
the library, the library will be deprecated in Sphinx.
As the :ref:`deprecation-policy` describes,
the first release of Sphinx that deprecates a feature (``A.B``) should raise a
``RemovedInSphinxXXWarning`` (where XX is the Sphinx version where the feature
will be removed) when the deprecated feature is invoked. Assuming we have good
test coverage, these warnings are converted to errors when running the test
suite with warnings enabled: ``python -Wall tests/run.py``. Thus, when adding
a ``RemovedInSphinxXXWarning`` you need to eliminate or silence any warnings
generated when running the tests.
.. _deprecation-policy:
Deprecation policy
------------------
A feature release may deprecate certain features from previous releases. If a
feature is deprecated in feature release 1.A, it will continue to work in all
1.A.x versions (for all versions of x) but raise warnings. Deprecated features
will be removed in the first 1.B release, or 1.B.1 for features deprecated in
the last 1.A.x feature release to ensure deprecations are done over at least 2
feature releases.
So, for example, if we decided to start the deprecation of a function in
Sphinx 1.4:
* Sphinx 1.4.x will contain a backwards-compatible replica of the function
which will raise a ``RemovedInSphinx16Warning``.
* Sphinx 1.5 (the version that follows 1.4) will still contain the
backwards-compatible replica.
* Sphinx 1.6 will remove the feature outright.
The warnings are displayed by default. You can turn off display of these
warnings with:
* ``PYTHONWARNINGS= make html`` (Linux/Mac)
* ``export PYTHONWARNINGS=`` and do ``make html`` (Linux/Mac)
* ``set PYTHONWARNINGS=`` and do ``make html`` (Windows)

View File

@ -446,6 +446,11 @@ member should be included in the documentation by using the following event:
documentation. The member is excluded if a handler returns ``True``. It is
included if the handler returns ``False``.
If more than one enabled extension handles the ``autodoc-skip-member``
event, autodoc will use the first non-``None`` value returned by a handler.
Handlers should return ``None`` to fall back to the skipping behavior of
autodoc and other enabled extensions.
:param app: the Sphinx application object
:param what: the type of the object which the docstring belongs to (one of
``"module"``, ``"class"``, ``"exception"``, ``"function"``, ``"method"``,

View File

@ -100,6 +100,9 @@ It adds these directives:
All three directives support a ``align`` option to align the graph horizontal.
The values "left", "center", "right" are allowed.
.. versionadded:: 1.6
All three directives support a ``name`` option to set the label to graph.
There are also these new config values:
.. confval:: graphviz_dot

View File

@ -10,6 +10,7 @@ Nodes for domain-specific object descriptions
.. autoclass:: desc
.. autoclass:: desc_signature
.. autoclass:: desc_signature_line
.. autoclass:: desc_addname
.. autoclass:: desc_type
.. autoclass:: desc_returns

View File

@ -282,10 +282,6 @@ The following notes may be helpful if you want to create Texinfo files:
info:Texinfo#makeinfo_options
which produces:
info:Texinfo#makeinfo_options
- Inline markup
The standard formatting for ``*strong*`` and ``_emphasis_`` can

View File

@ -73,6 +73,11 @@ Glossary
directive" (e.g. :rst:dir:`function` or :rst:dir:`object`) creates such a
block; and most objects can be cross-referenced to.
RemoveInSphinxXXXWarning
The feature which is warned will be removed in Sphinx-XXX version.
It usually caused from Sphinx extensions which is using deprecated.
See also :ref:`when-deprecation-warnings-are-displayed`.
role
A reStructuredText markup element that allows marking a piece of text.
Like directives, roles are extensible. The basic syntax looks like this:

View File

@ -118,13 +118,20 @@ Extension options
Enable `sphinx.ext.viewcode` extension.
.. option:: --extensions=EXTENSIONS
Enable arbitary extensions.
Makefile and Batchfile creation options
---------------------------------------
.. option:: --use-make-mode, --no-use-make-mode
Makefile/make.bat uses (or not use) make-mode. Default is not use.
Makefile/make.bat uses (or not use) make-mode. Default is use.
.. versionchanged:: 1.5
make-mode is default.
.. option:: --makefile, --no-makefile
@ -138,6 +145,32 @@ Makefile and Batchfile creation options
.. versionadded:: 1.3
Add various options for sphinx-quickstart invocation.
Project templating
------------------
.. option:: -t, --templatedir=TEMPLATEDIR
Template directory for template files. You can modify the templates of
sphinx project files generated by quickstart. Following Jinja2 template
files are allowed:
* master_doc.rst_t
* conf.py_t
* Makefile_t
* Makefile.new_t
* make.bat_t
* make.bat.new_t
In detail, please refer the system template files Sphinx provides.
(sphinx/templates/quickstart)
.. option:: -d NAME=VALUE
Define a template variable
.. versionadded:: 1.5
Project templating options for sphinx-quickstart
Invocation of sphinx-build
==========================
@ -377,6 +410,23 @@ variables to customize behavior:
Additional options for :program:`sphinx-build`.
.. _when-deprecation-warnings-are-displayed:
Deprecation Warnings
--------------------
If any deprecation warning like ``RemovedInSphinxXXXWarning`` are displayed
when building a user's document, some Sphinx extension is using deprecated
features. In that case, please report it to author of the extension.
To disable the deprecation warnings, please set ``PYTHONWARNINGS=`` environment
variable to your environment. For example:
* ``PYTHONWARNINGS= make html`` (Linux/Mac)
* ``export PYTHONWARNINGS=`` and do ``make html`` (Linux/Mac)
* ``set PYTHONWARNINGS=`` and do ``make html`` (Windows)
* modify your Makefile/make.bat and set the environment variable
.. _invocation-apidoc:

View File

@ -8,47 +8,333 @@ LaTeX customization
.. module:: latex
:synopsis: LaTeX specifics.
The *latex* target does not (yet) benefit from pre-prepared themes like the
The *latex* target does not benefit from pre-prepared themes like the
*html* target does (see :doc:`theming`).
There are two principal means of setting up customization:
.. raw:: latex
#. usage of the :ref:`latex-options` as described in :doc:`config`, particularly the
various keys of :confval:`latex_elements`, to modify the loaded packages,
for example::
\begingroup
\sphinxsetup{verbatimwithframe=false,%
VerbatimColor={named}{OldLace}, TitleColor={named}{DarkGoldenrod},%
hintBorderColor={named}{LightCoral}, attentionBgColor={named}{LightPink},%
attentionborder=3pt, attentionBorderColor={named}{Crimson},%
noteBorderColor={named}{Olive}, noteborder=2pt,%
cautionBorderColor={named}{Cyan}, cautionBgColor={named}{LightCyan},%
cautionborder=3pt}
\relax
'fontpkg': '\\usepackage{times}', # can load other font
'fncychap': '\\usepackage[Bjarne]{fncychap}', # can use other option
.. tip::
Basic customization
-------------------
It is not mandatory to load *fncychap*. Naturally, without it and in
absence of further customizations, the chapter headings will revert to
LaTeX's default for the *report* class.
It is available from ``conf.py`` via usage of the
:ref:`latex-options` as described in :doc:`config` (backslashes must be doubled
in Python string literals to reach latex.) For example::
#. usage of LaTeX ``\renewcommand``, ``\renewenvironment``, ``\setlength``,
``\definecolor`` to modify the defaults from package file :file:`sphinx.sty`
and class files :file:`sphinxhowto.cls` and :file:`sphinxmanual.cls`. If such
definitions are few, they can be located inside the ``'preamble'`` key of
:confval:`latex_elements`. In case of many it may prove more convenient to
assemble them into a specialized file :file:`customizedmacros.tex` and use::
# inside conf.py
latex_engine = 'xelatex'
latex_elements = {
'fontenc': '\\usepackage{fontspec}',
'fontpkg': '''\
\\setmainfont{DejaVu Serif}
\\setsansfont{DejaVu Sans}
\\setmonofont{DejaVu Sans Mono}''',
'geometry': '\\usepackage[vmargin=2.5cm, hmargin=3cm]{geometry}',
'preamble': '''\
\\usepackage[titles]{tocloft}
\\cftsetpnumwidth {1.25cm}\\cftsetrmarg{1.5cm}
\\setlength{\\cftchapnumwidth}{0.75cm}
\\setlength{\\cftsecindent}{\\cftchapnumwidth}
\\setlength{\\cftsecnumwidth}{1.25cm}''',
'fncychap': '\\usepackage[Bjornstrup]{fncychap}',
'printindex': '\\footnotesize\\raggedright\\printindex',
}
latex_show_urls = 'footnote'
'preamble': '\\makeatletter\\input{customizedmacros.tex}\\makeatother',
.. the above was tested on Sphinx's own 1.5a2 documentation with good effect !
More advanced LaTeX users will set up a style file
:file:`customizedmacros.sty`, which can then be loaded via::
.. highlight:: latex
'preamble': '\\usepackage{customizedmacros}',
More advanced customization will be obtained via insertion into the LaTeX
preamble of relevant ``\renewcommand``, ``\renewenvironment``, ``\setlength``,
or ``\definecolor`` commands. The ``'preamble'`` key of
:confval:`latex_elements` will serve for inserting these commands. If they are
numerous, it may prove more convenient to assemble them into a specialized
file :file:`mystyle.tex` and then use::
The :ref:`build configuration file <build-config>` file will then have its variable
:confval:`latex_additional_files` appropriately configured, for example::
'preamble': r'\makeatletter\input{mystyle.tex}\makeatother',
latex_additional_files = ["customizedmacros.sty"]
or, better, to set up a style file
:file:`mystyle.sty` which can then be loaded via::
Such *LaTeX Sphinx theme* files could possibly be contributed in the
future by advanced users for wider use.
'preamble': r'\usepackage{mystyle}',
Let us illustrate here what can be modified by the second method.
The :ref:`build configuration file <build-config>` file for the project needs
to have its variable :confval:`latex_additional_files` appropriately
configured, for example::
latex_additional_files = ["mystyle.sty"]
The Sphinx LaTeX style package options
--------------------------------------
The ``'sphinxsetup'`` key to :confval:`latex_elements` provides a
more convenient interface to various style parameters. It is a comma separated
string of ``key=value`` instructions::
key1=value1,key2=value2, ...
- if a key is repeated, it is its last occurence which counts,
- spaces around the commas and equal signs are ignored.
If non-empty, it will be passed as argument to the ``\sphinxsetup`` command::
\usepackage{sphinx}
\sphinxsetup{key1=value1,key2=value2,...}
.. versionadded:: 1.5
.. note::
- Most options described next could also have been positioned as
:file:`sphinx.sty` package options. But for those where the key value
contains some LaTeX code the use of ``\sphinxsetup`` is mandatory. Hence
the whole ``'sphinxsetup'`` string is passed as argument to
``\sphinxsetup``.
- As an alternative to the ``'sphinxsetup'`` key, it is possibly
to insert explicitely the ``\\sphinxsetup{key=value,..}`` inside the
``'preamble'`` key. It is even possible to use the ``\sphinxsetup`` in
the body of the document, via the :rst:dir:`raw` directive, to modify
dynamically the option values: this is actually what we did for the
duration of this chapter for the PDF output, which is styled using::
verbatimwithframe=false,
VerbatimColor={named}{OldLace}, TitleColor={named}{DarkGoldenrod},
hintBorderColor={named}{LightCoral}, attentionBgColor={named}{LightPink},
attentionborder=3pt, attentionBorderColor={named}{Crimson},
noteBorderColor={named}{Olive}, noteborder=2pt,
cautionBorderColor={named}{Cyan}, cautionBgColor={named}{LightCyan},
cautionborder=3pt
and with the ``svgnames`` option having been passed to "xcolor" package::
latex_elements = {
'passoptionstopackages': r'\PassOptionsToPackage{svgnames}{xcolor}',
}
Here are the currently available options together with their default values.
.. caution::
These options correspond to what has been so far the default LaTeX
rendering by Sphinx; if in future Sphinx offers various *themes* for LaTeX,
the interface may change.
``verbatimwithframe``
default ``true``. Boolean to specify if :rst:dir:`code-block`\ s and literal
includes are framed. Setting it to ``false`` does not deactivate use of
package "framed", because it is still in use for the optional background
colour (see below).
.. attention::
LaTeX requires ``true`` or ``false`` to be specified in *lowercase*.
``verbatimwrapslines``
default ``true``. Tells whether long lines in :rst:dir:`code-block`\ s
should be wrapped.
.. (comment) It is theoretically possible to customize this even
more and decide at which characters a line-break can occur and whether
before or after, but this is accessible currently only by re-defining some
macros with complicated LaTeX syntax from :file:`sphinx.sty`.
``inlineliteralwraps``
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 shrinked) in order to accomodate the linebreak.
.. versionadded:: 1.5
set this option to ``false`` to recover former behaviour.
``verbatimvisiblespace``
default ``\textcolor{red}{\textvisiblespace}``. When a long code line is
split, space characters located at end of the line before the break are
displayed using this code.
``verbatimcontinued``
The default is::
\makebox[2\fontcharwd\font`\x][r]{\textcolor{red}{\tiny$\hookrightarrow$}}
It is printed at start of continuation lines. This rather formidable
expression reserves twice the width of a typical character in the current
(monospaced) font and puts there a small red hook pointing to the right.
.. versionchanged:: 1.5
The breaking of long code lines was introduced at 1.4.2. The space
reserved to the continuation symbol was changed at 1.5 to obey the
current font characteristics (this was needed as Sphinx 1.5 LaTeX
allows code-blocks in footnotes which use a smaller font size).
.. hint::
This specification gives the same spacing as before 1.5::
\normalfont\normalsize\makebox[3ex][r]{\textcolor{red}{\tiny$\hookrightarrow$}
``TitleColor``
default ``{rgb}{0.126,0.263,0.361}``. The colour for titles (as configured
via use of package "titlesec".) It must obey the syntax of the
``\definecolor`` command. Check the documentation of packages ``color`` or
``xcolor``.
``InnerLinkColor``
default ``{rgb}{0.208,0.374,0.486}``. A colour passed to ``hyperref`` as
value of ``linkcolor`` and ``citecolor``.
``OuterLinkColor``
default ``{rgb}{0.216,0.439,0.388}``. A colour passed to ``hyperref`` as
value of ``filecolor``, ``menucolor``, and ``urlcolor``.
``VerbatimColor``
default ``{rgb}{1,1,1}``. The background colour for
:rst:dir:`code-block`\ s. The default is white.
``VerbatimBorderColor``
default ``{rgb}{0,0,0}``. The frame color, defaults to black.
``verbatimsep``
default ``\fboxsep``. The separation between code lines and the frame.
``verbatimborder``
default ``\fboxrule``. The width of the frame around
:rst:dir:`code-block`\ s.
``shadowsep``
default ``5pt``. The separation between contents and frame for
:dudir:`contents` and :dudir:`topic` boxes.
``shadowsize``
default ``4pt``. The width of the lateral "shadow" to the right.
``shadowrule``
default ``\fboxrule``. The width of the frame around :dudir:`topic` boxes.
``noteBorderColor``
default ``{rgb}{0,0,0}``. The colour for the two horizontal rules used by
Sphinx in LaTeX for styling a
:dudir:`note` admonition. Defaults to black.
.. note::
The actual name of the colour as declared to "color" or "xcolor" is
``sphinxnoteBorderColor``. The same "sphinx" prefix applies to all
colours for notices and admonitions.
``hintBorderColor``
default ``{rgb}{0,0,0}``. id.
``importantBorderColor``
default ``{rgb}{0,0,0}``. id.
``tipBorderColor``
default ``{rgb}{0,0,0}``. id.
``noteborder``
default ``0.5pt``. The width of the two horizontal rules.
``hintborder``
default ``0.5pt``. id.
``importantborder``
default ``0.5pt``. id.
``tipborder``
default ``0.5pt``. id.
``warningBorderColor``
default ``{rgb}{0,0,0}``. The colour of the frame for :dudir:`warning` type
admonitions. Defaults to black.
``cautionBorderColor``
default ``{rgb}{0,0,0}``. id.
``attentionBorderColor``
default ``{rgb}{0,0,0}``. id.
``dangerBorderColor``
default ``{rgb}{0,0,0}``. id.
``errorBorderColor``
default ``{rgb}{0,0,0}``. id.
``warningBgColor``
default ``{rgb}{1,1,1}``. The background colour for :dudir:`warning` type
admonition, defaults to white.
``cautionBgColor``
default ``{rgb}{1,1,1}``. id.
``attentionBgColor``
default ``{rgb}{1,1,1}``. id.
``dangerBgColor``
default ``{rgb}{1,1,1}``. id.
``errorBgColor``
default ``{rgb}{1,1,1}``. id.
``warningborder``
default ``1pt``. The width of the frame.
``cautionborder``
default ``1pt``. id.
``attentionborder``
default ``1pt``. id.
``dangerborder``
default ``1pt``. id.
``errorborder``
default ``1pt``. id.
``AtStartFootnote``
default ``\mbox{ }``. LaTeX macros inserted at the start of the footnote
text at bottom of page, after the footnote number.
``BeforeFootnote``
default ``\leavevmode\unskip``. LaTeX macros inserted before the footnote
mark. The default removes possible space before it.
It can be set to empty (``BeforeFootnote={},``) to recover the earlier
behaviour of Sphinx, or alternatively contain a ``\nobreak\space`` or a
``\thinspace`` after the ``\unskip`` to insert some chosen
(non-breakable) space.
.. versionadded:: 1.5
formerly, footnotes from explicit mark-up were
preceded by a space (hence a linebreak there was possible), but
automatically generated footnotes had no such space.
``HeaderFamily``
default ``\sffamily\bfseries``. Sets the font used by headings.
As seen above, key values may even be used for LaTeX commands. But don't
forget to double the backslashes if not using "raw" Python strings.
The LaTeX environments defined by Sphinx
----------------------------------------
Let us now list some macros from the package file
:file:`sphinx.sty` and class file :file:`sphinxhowto.cls` or
:file:`sphinxmanual.cls`, which can be entirely redefined, if desired.
- text styling commands (they have one argument): ``\sphinx<foo>`` with
``<foo>`` being one of ``strong``, ``bfcode``, ``email``, ``tablecontinued``,
@ -60,7 +346,9 @@ Let us illustrate here what can be modified by the second method.
.. versionchanged:: 1.4.5
use of ``\sphinx`` prefixed macro names to limit possibilities of conflict
with user added packages. The LaTeX writer uses always the prefixed names.
with user added packages: if
:confval:`latex_keep_old_macro_names` is set to ``False`` in
:file:`conf.py` only the prefixed names are defined.
- more text styling commands: ``\sphinxstyle<bar>`` with ``<bar>`` one of
``indexentry``, ``indexextra``, ``indexpageref``, ``topictitle``,
``sidebartitle``, ``othertitle``, ``sidebarsubtitle``, ``thead``,
@ -68,37 +356,23 @@ Let us illustrate here what can be modified by the second method.
``abbreviation``, ``literalintitle``.
.. versionadded:: 1.5
earlier, the LaTeX writer used hard-coded ``\texttt``, ``\emph``, etc...
- parameters for paragraph level environments: with ``<foo>`` one of
:dudir:`warning`, :dudir:`caution`, :dudir:`attention`,
:dudir:`danger`, :dudir:`error`, the colours
*sphinx<foo>bordercolor* and *sphinx<foo>bgcolor* can be
re-defined using ``\definecolor`` command. The
``\sphinx<foo>border`` is a command (not a LaTeX length) which
specifies the thickness of the frame (default ``1pt``) and can be
``\renewcommand`` 'd. The same applies with ``<foo>`` one of
:dudir:`note`, :dudir:`hint`, :dudir:`important`, :dudir:`tip`, but
the background colour is not implemented by the default environments
and the top and bottom rule thickness default is ``0.5pt``.
.. versionchanged:: 1.5
customizability of the parameters for each type of admonition.
- paragraph level environments: for each admonition as in the previous item, the
the new macros are wrappers of the formerly hard-coded ``\texttt``,
``\emph``, ... The default definitions can be found in
:file:`sphinx.sty`.
- paragraph level environments: for each admonition type ``<foo>``, the
used environment is named ``sphinx<foo>``. They may be ``\renewenvironment``
'd individually, and must then be defined with one argument (it is the heading
of the notice, for example ``Warning:`` for :dudir:`warning` directive, if
English is the document language). Their default definitions use either the
*sphinxheavybox* (for the first listed directives) or the *sphinxlightbox*
environments, configured to use the parameters (colours, border thickness)
specific to each type, as mentioned in the previous item.
specific to each type, which can be set via ``'sphinxsetup'`` string.
.. versionchanged:: 1.5
use of public environment names, separate customizability of the parameters.
- the :dudir:`contents` directive (with ``:local:`` option) and the
:dudir:`topic` directive are implemented by environment ``sphinxShadowBox``.
Its default definition obeys three LaTeX lengths (not commands) as parameters:
``\sphinxshadowsep`` (distance from contents), ``\sphinxshadowsize`` (width of
lateral shadow), ``\sphinxshadowrule`` (thickness of the frame).
See above for the three dimensions associated with it.
.. versionchanged:: 1.5
use of public names for the three lengths. The environment itself was
@ -107,8 +381,7 @@ Let us illustrate here what can be modified by the second method.
implemented using ``sphinxVerbatim`` environment which is a wrapper of
``Verbatim`` environment from package ``fancyvrb.sty``. It adds the handling
of the top caption and the wrapping of long lines, and a frame which allows
pagebreaks. The LaTeX lengths (not commands) ``\sphinxverbatimsep`` and
``\sphinxverbatimborder`` customize the framing. Inside tables the used
pagebreaks. Inside tables the used
environment is ``sphinxVerbatimintable`` (it does not draw a frame, but
allows a caption).
@ -117,9 +390,10 @@ Let us illustrate here what can be modified by the second method.
which is the one of ``OriginalVerbatim`` too), and custom one is called
``sphinxVerbatim``. Also, earlier version of Sphinx used
``OriginalVerbatim`` inside tables (captions were lost, long code lines
were not wrapped), they now use ``sphinxVerbatimintable``.
were not wrapped), it now uses there ``sphinxVerbatimintable``.
.. versionadded:: 1.5
the two customizable lengths, the ``sphinxVerbatimintable``.
the two customizable lengths, the ``sphinxVerbatimintable``, the boolean
toggles described above.
- by default the Sphinx style file ``sphinx.sty`` includes the command
``\fvset{fontsize=\small}`` as part of its configuration of
``fancyvrb.sty``. The user may override this for example via
@ -128,27 +402,34 @@ Let us illustrate here what can be modified by the second method.
.. versionadded:: 1.5
formerly, the use of ``\small`` for code listings was not customizable.
- miscellaneous colours: *TitleColor*, *InnerLinkColor*, *OuterLinkColor*,
*VerbatimColor* (this is a background colour), *VerbatimBorderColor*.
- the ``\sphinxAtStartFootnote`` is inserted between footnote numbers and their
texts, by default it does ``\mbox{ }``.
- use ``\sphinxSetHeaderFamily`` to set the font used by headings
(default is ``\sffamily\bfseries``).
.. versionadded:: 1.5
- the section, subsection, ... headings are set using *titlesec*'s
``\titleformat`` command.
- for the ``'manual'`` class, the chapter headings can be customized using
*fncychap*'s commands ``\ChNameVar``, ``\ChNumVar``, ``\ChTitleVar``. Or, if
the loading of this package has been removed from ``'fncychap'`` key, one can
use the *titlesec* ``\titleformat`` command.
``\titleformat`` command. Check :file:`sphinx.sty` for the definitions.
- for the ``'sphinxmanual'`` class (corresponding to the fifth element of
:confval:`latex_documents` being set to ``'manual'``), the chapter headings
can be customized using *fncychap*'s commands ``\ChNameVar``, ``\ChNumVar``,
``\ChTitleVar``. Check :file:`sphinx.sty` for the default definitions. They
are applied only if *fncychap* is loaded with option ``Bjarne``. It is also
possible to use an empty ``'fncychap'`` key, and use the *titlesec*
``\titleformat`` command to style the chapter titles.
.. note::
.. versionchanged:: 1.5
formerly, use of *fncychap* with other styles than ``Bjarne`` was
dysfunctional.
- the table of contents is typeset via ``\sphinxtableofcontents`` which is a
wrapper (whose definition can be found in :file:`sphinxhowto.cls` or in
:file:`sphinxmanual.cls`) of standard ``\tableofcontents``.
It is impossible to revert or prevent the loading of a package that results
from a ``\usepackage`` executed from inside the :file:`sphinx.sty` style
file. Sphinx aims at loading as few packages as are really needed for its
default design.
.. versionchanged:: 1.5
formerly, the meaning of ``\tableofcontents`` was modified by Sphinx.
- the bibliography and Python Module index are typeset respectively within
environments ``sphinxthebibliography`` and ``sphinxtheindex``, which are
simple wrappers of the non-modified ``thebibliography`` and ``theindex``
environments.
.. versionchanged:: 1.5
formerly, the original environments were modified by Sphinx.
- the list is not exhaustive: refer to :file:`sphinx.sty` for more.
.. hint::
@ -158,3 +439,7 @@ Let us illustrate here what can be modified by the second method.
will be changed in future version.
.. versionadded:: 1.5
.. raw:: latex
\endgroup

View File

@ -241,7 +241,7 @@ Dedent
.. versionadded:: 1.3
A ``dedent`` option can be given to strip a precedence characters from the code
A ``dedent`` option can be given to strip indentation characters from the code
block. For example::
.. literalinclude:: example.rb

View File

@ -214,6 +214,7 @@ Cross-referencing figures by figure number
.. versionchanged:: 1.5
`numref` role can also refer sections.
And `numref` allows `{name}` for the link text.
.. rst:role:: numref
@ -223,7 +224,10 @@ Cross-referencing figures by figure number
If an explicit link text is given (like usual: ``:numref:`Image of Sphinx (Fig.
%s) <my-figure>```), the link caption will be the title of the reference.
The format of link text is same as :confval:`numfig_format`.
As a special character, `%s` and `{number}` will be replaced to figure
number. `{name}` will be replaced to figure caption.
If no explicit link text is given, the value of :confval:`numfig_format` is
used to default value of link text.
If :confval:`numfig` is ``False``, figures are not numbered.
so this role inserts not a reference but labels or link text.

View File

@ -238,10 +238,19 @@ following directive exists:
By default, Sphinx uses a table layout with ``L`` for every column.
.. hint::
For columns which are known to be much narrower than the others it is
recommended to use the lowercase specifiers. For more information, check
the ``tabulary`` manual.
.. versionadded:: 0.3
.. warning::
Tables with more than 30 rows are rendered using ``longtable``, not
``tabulary``, in order to allow pagebreaks.
Tables that contain list-like elements such as object descriptions,
blockquotes or any kind of lists cannot be set out of the box with
``tabulary``. They are therefore set with the standard LaTeX ``tabular``
@ -253,8 +262,6 @@ following directive exists:
literal block are always set with ``tabular``. Also, the verbatim
environment used for literal blocks only works in ``p{width}`` columns, which
means that by default, Sphinx generates such column specs for such tables.
Use the :rst:dir:`tabularcolumns` directive to get finer control over such
tables.
.. rubric:: Footnotes

View File

@ -123,6 +123,16 @@ tables of contents. The ``toctree`` directive is the central element.
toctree directive. This is useful if you want to generate a "sitemap" from
the toctree.
You can use the ``reversed`` flag option to reverse the order of the entries
in the list. This can be useful when using the ``glob`` flag option to
reverse the ordering of the files. Example::
.. toctree::
:glob:
:reversed:
recipe/*
You can also give a "hidden" option to the directive, like this::
.. toctree::

View File

@ -393,6 +393,7 @@ are in HTML form), these variables are also available:
The name of the copied source file for the current document. This is only
nonempty if the :confval:`html_copy_source` value is ``True``.
This has empty value on creating automatically-generated files.
.. data:: toc

6
mypy.ini Normal file
View File

@ -0,0 +1,6 @@
[mypy]
python_version = 2.7
silent_imports = True
fast_parser = True
incremental = True
check_untyped_defs = True

View File

@ -26,4 +26,4 @@ universal = 1
[flake8]
max-line-length=95
ignore=E113,E116,E221,E226,E241,E251,E901
exclude=tests/*,build/*,sphinx/search/*,sphinx/pycode/pgen2/*,doc/ext/example*.py
exclude=tests/*,build/*,sphinx/search/*,sphinx/pycode/pgen2/*,doc/ext/example*.py,.tox/*

View File

@ -51,6 +51,7 @@ requires = [
'alabaster>=0.7,<0.8',
'imagesize',
'requests',
'typing',
]
extras_require = {
# Environment Marker works for wheel 0.24 or later
@ -157,7 +158,7 @@ else:
msgid = msgid[0]
jscatalog[msgid] = message.string
with open(js_file, 'wb') as outfile:
with open(js_file, 'wt') as outfile:
outfile.write('Documentation.addTranslations(')
dump(dict(
messages=jscatalog,
@ -191,6 +192,7 @@ class CompileGrammarCommand(Command):
def sub_commands(self):
pass
cmdclass['compile_grammar'] = CompileGrammarCommand

View File

@ -12,16 +12,31 @@
# Keep this file executable as-is in Python 3!
# (Otherwise getting the version out of it from setup.py is impossible.)
from __future__ import absolute_import
import os
import sys
import warnings
from os import path
__version__ = '1.5a2'
__released__ = '1.5a2' # used when Sphinx builds its own docs
from .deprecation import RemovedInNextVersionWarning
# by default, all DeprecationWarning under sphinx package will be emit.
# Users can avoid this by using environment variable: PYTHONWARNINGS=
if 'PYTHONWARNINGS' not in os.environ:
warnings.filterwarnings('default',
category=RemovedInNextVersionWarning, module='sphinx')
# docutils.io using mode='rU' for open
warnings.filterwarnings('ignore', "'U' mode is deprecated",
DeprecationWarning, module='docutils.io')
__version__ = '1.6'
__released__ = '1.6+' # used when Sphinx builds its own docs
# version info for better programmatic use
# possible values for 3rd element: 'alpha', 'beta', 'rc', 'final'
# 'final' has 0 as the last element
version_info = (1, 5, 0, 'alpha', 2)
version_info = (1, 6, 0, 'beta', 1)
package_dir = path.abspath(path.dirname(__file__))
@ -39,7 +54,7 @@ if __version__.endswith('+'):
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
if out:
__display_version__ += '/' + out.decode().strip()
__display_version__ += '/' + out.decode().strip() # type: ignore
except Exception:
pass

View File

@ -12,6 +12,7 @@
import warnings
from docutils import nodes
from sphinx.deprecation import RemovedInSphinx16Warning
class translatable(object):
@ -76,13 +77,27 @@ class desc_signature(nodes.Part, nodes.Inline, nodes.TextElement):
"""Node for object signatures.
The "term" part of the custom Sphinx definition list.
As default the signature is a single line signature,
but set ``is_multiline = True`` to describe a multi-line signature.
In that case all child nodes must be ``desc_signature_line`` nodes.
"""
# nodes to use within a desc_signature
class desc_signature_line(nodes.Part, nodes.Inline, nodes.TextElement):
"""Node for a line in a multi-line object signatures.
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.
"""
# nodes to use within a desc_signature or desc_signature_line
class desc_addname(nodes.Part, nodes.Inline, nodes.TextElement):
"""Node for additional name parts (module name, class name)."""
# compatibility alias
desc_classname = desc_addname
@ -262,12 +277,12 @@ class termsep(nodes.Structural, nodes.Element):
"""Separates two terms within a <term> node.
.. versionchanged:: 1.4
sphinx.addnodes.termsep is deprecated. It will be removed at Sphinx-1.5.
sphinx.addnodes.termsep is deprecated. It will be removed at Sphinx-1.6.
"""
def __init__(self, *args, **kw):
warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.5',
DeprecationWarning, stacklevel=2)
warnings.warn('sphinx.addnodes.termsep will be removed at Sphinx-1.6',
RemovedInSphinx16Warning, stacklevel=2)
super(termsep, self).__init__(*args, **kw)

View File

@ -21,10 +21,15 @@ import sys
import optparse
from os import path
from six import binary_type
from fnmatch import fnmatch
from sphinx.util.osutil import FileAvoidWrite, walk
from sphinx import __display_version__
if False:
# For type annotation
from typing import Any, Tuple # NOQA
# automodule options
if 'SPHINX_APIDOC_OPTIONS' in os.environ:
OPTIONS = os.environ['SPHINX_APIDOC_OPTIONS'].split(',')
@ -41,6 +46,7 @@ PY_SUFFIXES = set(['.py', '.pyx'])
def makename(package, module):
# type: (unicode, unicode) -> unicode
"""Join package and module with a dot."""
# Both package and module can be None/empty.
if package:
@ -53,6 +59,7 @@ def makename(package, module):
def write_file(name, text, opts):
# type: (unicode, unicode, Any) -> None
"""Write the output file for module/package <name>."""
fname = path.join(opts.destdir, '%s.%s' % (name, opts.suffix))
if opts.dryrun:
@ -67,12 +74,14 @@ def write_file(name, text, opts):
def format_heading(level, text):
# type: (int, unicode) -> unicode
"""Create a heading of <level> [1, 2 or 3 supported]."""
underlining = ['=', '-', '~', ][level - 1] * len(text)
return '%s\n%s\n\n' % (text, underlining)
def format_directive(module, package=None):
# type: (unicode, unicode) -> unicode
"""Create the automodule directive and add the options."""
directive = '.. automodule:: %s\n' % makename(package, module)
for option in OPTIONS:
@ -81,6 +90,7 @@ def format_directive(module, package=None):
def create_module_file(package, module, opts):
# type: (unicode, unicode, Any) -> None
"""Build the text of the file and write the file."""
if not opts.noheadings:
text = format_heading(1, '%s module' % module)
@ -92,6 +102,7 @@ def create_module_file(package, module, opts):
def create_package_file(root, master_package, subroot, py_files, opts, subs, is_namespace):
# type: (unicode, unicode, unicode, List[unicode], Any, List[unicode], bool) -> None
"""Build the text of the file and write the file."""
text = format_heading(1, ('%s package' if not is_namespace else "%s namespace")
% makename(master_package, subroot))
@ -147,13 +158,14 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs, is_
def create_modules_toc_file(modules, opts, name='modules'):
# type: (List[unicode], Any, unicode) -> None
"""Create the module's index."""
text = format_heading(1, '%s' % opts.header)
text += '.. toctree::\n'
text += ' :maxdepth: %s\n\n' % opts.maxdepth
modules.sort()
prev_module = ''
prev_module = '' # type: unicode
for module in modules:
# look if the module is a subpackage and, if yes, ignore it
if module.startswith(prev_module + '.'):
@ -165,6 +177,7 @@ def create_modules_toc_file(modules, opts, name='modules'):
def shall_skip(module, opts):
# type: (unicode, Any) -> bool
"""Check if we want to skip this module."""
# skip if the file doesn't exist and not using implicit namespaces
if not opts.implicit_namespaces and not path.exists(module):
@ -183,6 +196,7 @@ def shall_skip(module, opts):
def recurse_tree(rootpath, excludes, opts):
# type: (unicode, List[unicode], Any) -> List[unicode]
"""
Look for every file in the directory tree and create the corresponding
ReST files.
@ -216,7 +230,7 @@ def recurse_tree(rootpath, excludes, opts):
# remove hidden ('.') and private ('_') directories, as well as
# excluded dirs
if includeprivate:
exclude_prefixes = ('.',)
exclude_prefixes = ('.',) # type: Tuple[unicode, ...]
else:
exclude_prefixes = ('.', '_')
subs[:] = sorted(sub for sub in subs if not sub.startswith(exclude_prefixes) and
@ -246,33 +260,36 @@ def recurse_tree(rootpath, excludes, opts):
def normalize_excludes(rootpath, excludes):
# type: (unicode, List[unicode]) -> List[unicode]
"""Normalize the excluded directory list."""
return [path.abspath(exclude) for exclude in excludes]
def is_excluded(root, excludes):
# type: (unicode, List[unicode]) -> bool
"""Check if the directory is in the exclude list.
Note: by having trailing slashes, we avoid common prefix issues, like
e.g. an exlude "foo" also accidentally excluding "foobar".
"""
for exclude in excludes:
if root == exclude:
if fnmatch(root, exclude): # type: ignore
return True
return False
def main(argv=sys.argv):
# type: (List[str]) -> int
"""Parse and check the command line arguments."""
parser = optparse.OptionParser(
usage="""\
usage: %prog [options] -o <output_path> <module_path> [exclude_path, ...]
usage: %prog [options] -o <output_path> <module_path> [exclude_pattern, ...]
Look recursively in <module_path> for Python modules and packages and create
one reST file with automodule directives per package in the <output_path>.
The <exclude_path>s can be files and/or directories that will be excluded
from generation.
The <exclude_pattern>s can be file and/or directory patterns that will be
excluded from generation.
Note: By default this script will not overwrite already created files.""")
@ -358,7 +375,7 @@ Note: By default this script will not overwrite already created files.""")
if opts.full:
from sphinx import quickstart as qs
modules.sort()
prev_module = ''
prev_module = '' # type: unicode
text = ''
for module in modules:
if module.startswith(prev_module + '.'):
@ -401,6 +418,7 @@ Note: By default this script will not overwrite already created files.""")
elif not opts.notoc:
create_modules_toc_file(modules, opts)
# So program can be started with "python -m sphinx.apidoc ..."
if __name__ == "__main__":
main()

View File

@ -22,13 +22,13 @@ from collections import deque
from six import iteritems, itervalues, text_type
from six.moves import cStringIO
from docutils import nodes
from docutils.parsers.rst import convert_directive_function, \
directives, roles
import sphinx
from sphinx import package_dir, locale
from sphinx.roles import XRefRole
from sphinx.config import Config
from sphinx.errors import SphinxError, SphinxWarning, ExtensionError, \
VersionRequirementError, ConfigError
@ -36,17 +36,24 @@ from sphinx.domains import ObjType
from sphinx.domains.std import GenericObject, Target, StandardDomain
from sphinx.environment import BuildEnvironment
from sphinx.io import SphinxStandaloneReader
from sphinx.roles import XRefRole
from sphinx.util import pycompat # noqa: F401
from sphinx.util import import_object
from sphinx.util.tags import Tags
from sphinx.util.osutil import ENOENT
from sphinx.util.logging import is_suppressed_warning
from sphinx.util.console import bold, lightgray, darkgray, darkred, darkgreen, \
term_width_line
from sphinx.util.console import ( # type: ignore
bold, lightgray, darkgray, darkred, darkgreen, term_width_line
)
from sphinx.util.i18n import find_catalog_source_files
if hasattr(sys, 'intern'):
intern = sys.intern
if False:
# For type annotation
from typing import Any, Callable, IO, Iterable, Iterator, Tuple, Type, Union # NOQA
from docutils.parsers import Parser # NOQA
from docutils.transform import Transform # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.domains import Domain # NOQA
# List of all known core events. Maps name to arguments description.
events = {
@ -63,7 +70,7 @@ events = {
'html-collect-pages': 'builder',
'html-page-context': 'pagename, context, doctree or None',
'build-finished': 'exception',
}
} # type: Dict[unicode, unicode]
builtin_extensions = (
'sphinx.builders.applehelp',
'sphinx.builders.changes',
@ -93,14 +100,14 @@ builtin_extensions = (
'sphinx.directives.other',
'sphinx.directives.patches',
'sphinx.roles',
)
) # type: Tuple[unicode, ...]
CONFIG_FILENAME = 'conf.py'
ENV_PICKLE_FILENAME = 'environment.pickle'
# list of deprecated extensions. Keys are extension name.
# Values are Sphinx version that merge the extension.
EXTENSION_BLACKLIST = {"sphinxjp.themecore": "1.2"}
EXTENSION_BLACKLIST = {"sphinxjp.themecore": "1.2"} # type: Dict[unicode, unicode]
class Sphinx(object):
@ -109,19 +116,20 @@ class Sphinx(object):
confoverrides=None, status=sys.stdout, warning=sys.stderr,
freshenv=False, warningiserror=False, tags=None, verbosity=0,
parallel=0):
# type: (unicode, unicode, unicode, unicode, unicode, Dict, IO, IO, bool, bool, unicode, int, int) -> None # NOQA
self.verbosity = verbosity
self.next_listener_id = 0
self._extensions = {}
self._extension_metadata = {}
self._additional_source_parsers = {}
self._listeners = {}
self._setting_up_extension = ['?']
self.domains = {}
self._extensions = {} # type: Dict[unicode, Any]
self._extension_metadata = {} # type: Dict[unicode, Dict[unicode, Any]]
self._additional_source_parsers = {} # type: Dict[unicode, Parser]
self._listeners = {} # type: Dict[unicode, Dict[int, Callable]]
self._setting_up_extension = ['?'] # type: List[unicode]
self.domains = {} # type: Dict[unicode, Type[Domain]]
self.buildername = buildername
self.builderclasses = {}
self.builder = None
self.env = None
self.enumerable_nodes = {}
self.builderclasses = {} # type: Dict[unicode, Type[Builder]]
self.builder = None # type: Builder
self.env = None # type: BuildEnvironment
self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, Callable]] # NOQA
self.srcdir = srcdir
self.confdir = confdir
@ -131,24 +139,24 @@ class Sphinx(object):
self.parallel = parallel
if status is None:
self._status = cStringIO()
self._status = cStringIO() # type: IO
self.quiet = True
else:
self._status = status
self.quiet = False
if warning is None:
self._warning = cStringIO()
self._warning = cStringIO() # type: IO
else:
self._warning = warning
self._warncount = 0
self.warningiserror = warningiserror
self._events = events.copy()
self._translators = {}
self._translators = {} # type: Dict[unicode, nodes.GenericNodeVisitor]
# keep last few messages for traceback
self.messagelog = deque(maxlen=10)
self.messagelog = deque(maxlen=10) # type: deque
# say hello to the world
self.info(bold('Running Sphinx v%s' % sphinx.__display_version__))
@ -249,6 +257,7 @@ class Sphinx(object):
self._init_enumerable_nodes()
def _init_i18n(self):
# type: () -> None
"""Load translated strings from the configured localedirs if enabled in
the configuration.
"""
@ -274,6 +283,7 @@ class Sphinx(object):
self.info('not available for built-in messages')
def _init_source_parsers(self):
# type: () -> None
for suffix, parser in iteritems(self._additional_source_parsers):
if suffix not in self.config.source_suffix:
self.config.source_suffix.append(suffix)
@ -281,6 +291,7 @@ class Sphinx(object):
self.config.source_parsers[suffix] = parser
def _init_env(self, freshenv):
# type: (bool) -> None
if freshenv:
self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
self.env.set_warnfunc(self.warn)
@ -293,6 +304,7 @@ class Sphinx(object):
self.env = BuildEnvironment.frompickle(
self.srcdir, self.config, path.join(self.doctreedir, ENV_PICKLE_FILENAME))
self.env.set_warnfunc(self.warn)
self.env.init_managers()
self.env.domains = {}
for domain in self.domains.keys():
# this can raise if the data version doesn't fit
@ -303,9 +315,10 @@ class Sphinx(object):
self.info('not yet created')
else:
self.info('failed: %s' % err)
return self._init_env(freshenv=True)
self._init_env(freshenv=True)
def _init_builder(self, buildername):
# type: (unicode) -> None
if buildername is None:
print('No builder selected, using default: html', file=self._status)
buildername = 'html'
@ -317,12 +330,14 @@ class Sphinx(object):
self.emit('builder-inited')
def _init_enumerable_nodes(self):
# type: () -> None
for node, settings in iteritems(self.enumerable_nodes):
self.env.domains['std'].enumerable_nodes[node] = settings
self.env.get_domain('std').enumerable_nodes[node] = settings # type: ignore
# ---- main "build" method -------------------------------------------------
def build(self, force_all=False, filenames=None):
# type: (bool, List[unicode]) -> None
try:
if force_all:
self.builder.compile_all_catalogs()
@ -356,11 +371,14 @@ class Sphinx(object):
# ---- logging handling ----------------------------------------------------
def _log(self, message, wfile, nonl=False):
# type: (unicode, IO, bool) -> None
try:
wfile.write(message)
except UnicodeEncodeError:
encoding = getattr(wfile, 'encoding', 'ascii') or 'ascii'
wfile.write(message.encode(encoding, 'replace'))
# wfile.write accept only str, not bytes.So, we encode and replace
# non-encodable characters, then decode them.
wfile.write(message.encode(encoding, 'replace').decode(encoding))
if not nonl:
wfile.write('\n')
if hasattr(wfile, 'flush'):
@ -369,6 +387,7 @@ class Sphinx(object):
def warn(self, message, location=None, prefix='WARNING: ',
type=None, subtype=None, colorfunc=darkred):
# type: (unicode, unicode, unicode, unicode, unicode, Callable) -> None
"""Emit a warning.
If *location* is given, it should either be a tuple of (docname, lineno)
@ -401,6 +420,7 @@ class Sphinx(object):
self._log(colorfunc(warntext), self._warning, True)
def info(self, message='', nonl=False):
# type: (unicode, bool) -> None
"""Emit an informational message.
If *nonl* is true, don't emit a newline at the end (which implies that
@ -409,6 +429,7 @@ class Sphinx(object):
self._log(message, self._status, nonl)
def verbose(self, message, *args, **kwargs):
# type: (unicode, Any, Any) -> None
"""Emit a verbose informational message.
The message will only be emitted for verbosity levels >= 1 (i.e. at
@ -424,6 +445,7 @@ class Sphinx(object):
self._log(message, self._status)
def debug(self, message, *args, **kwargs):
# type: (unicode, Any, Any) -> None
"""Emit a debug-level informational message.
The message will only be emitted for verbosity levels >= 2 (i.e. at
@ -439,6 +461,7 @@ class Sphinx(object):
self._log(darkgray(message), self._status)
def debug2(self, message, *args, **kwargs):
# type: (unicode, Any, Any) -> None
"""Emit a lowlevel debug-level informational message.
The message will only be emitted for verbosity level 3 (i.e. three
@ -454,6 +477,7 @@ class Sphinx(object):
self._log(lightgray(message), self._status)
def _display_chunk(chunk):
# type: (Any) -> unicode
if isinstance(chunk, (list, tuple)):
if len(chunk) == 1:
return text_type(chunk[0])
@ -462,12 +486,13 @@ class Sphinx(object):
def old_status_iterator(self, iterable, summary, colorfunc=darkgreen,
stringify_func=_display_chunk):
# type: (Iterable, unicode, Callable, Callable) -> Iterator
l = 0
for item in iterable:
if l == 0:
self.info(bold(summary), nonl=1)
self.info(bold(summary), nonl=True)
l = 1
self.info(colorfunc(stringify_func(item)) + ' ', nonl=1)
self.info(colorfunc(stringify_func(item)) + ' ', nonl=True)
yield item
if l == 1:
self.info()
@ -475,6 +500,7 @@ class Sphinx(object):
# new version with progress info
def status_iterator(self, iterable, summary, colorfunc=darkgreen, length=0,
stringify_func=_display_chunk):
# type: (Iterable, unicode, Callable, int, Callable) -> Iterable
if length == 0:
for item in self.old_status_iterator(iterable, summary, colorfunc,
stringify_func):
@ -490,7 +516,7 @@ class Sphinx(object):
s += '\n'
else:
s = term_width_line(s)
self.info(s, nonl=1)
self.info(s, nonl=True)
yield item
if l > 0:
self.info()
@ -498,6 +524,7 @@ class Sphinx(object):
# ---- general extensibility interface -------------------------------------
def setup_extension(self, extension):
# type: (unicode) -> None
"""Import and setup a Sphinx extension module. No-op if called twice."""
self.debug('[app] setting up extension: %r', extension)
if extension in self._extensions:
@ -545,22 +572,25 @@ class Sphinx(object):
self._setting_up_extension.pop()
def require_sphinx(self, version):
# type: (unicode) -> None
# check the Sphinx version if requested
if version > sphinx.__display_version__[:3]:
raise VersionRequirementError(version)
def import_object(self, objname, source=None):
# type: (str, unicode) -> Any
"""Import an object from a 'module.name' string."""
return import_object(objname, source=None)
# event interface
def _validate_event(self, event):
event = intern(event)
# type: (unicode) -> None
if event not in self._events:
raise ExtensionError('Unknown event name: %s' % event)
def connect(self, event, callback):
# type: (unicode, Callable) -> int
self._validate_event(event)
listener_id = self.next_listener_id
if event not in self._listeners:
@ -573,11 +603,13 @@ class Sphinx(object):
return listener_id
def disconnect(self, listener_id):
# type: (int) -> None
self.debug('[app] disconnecting event: [id=%s]', listener_id)
for event in itervalues(self._listeners):
event.pop(listener_id, None)
def emit(self, event, *args):
# type: (unicode, Any) -> List
try:
self.debug2('[app] emitting event: %r%s', event, repr(args)[:100])
except Exception:
@ -591,6 +623,7 @@ class Sphinx(object):
return results
def emit_firstresult(self, event, *args):
# type: (unicode, Any) -> Any
for result in self.emit(event, *args):
if result is not None:
return result
@ -599,6 +632,7 @@ class Sphinx(object):
# registering addon parts
def add_builder(self, builder):
# type: (Type[Builder]) -> None
self.debug('[app] adding builder: %r', builder)
if not hasattr(builder, 'name'):
raise ExtensionError('Builder class %s has no "name" attribute'
@ -610,8 +644,9 @@ class Sphinx(object):
self.builderclasses[builder.name] = builder
def add_config_value(self, name, default, rebuild, types=()):
# type: (unicode, Any, Union[bool, unicode], Any) -> None
self.debug('[app] adding config value: %r',
(name, default, rebuild) + ((types,) if types else ()))
(name, default, rebuild) + ((types,) if types else ())) # type: ignore
if name in self.config.values:
raise ExtensionError('Config value %r already present' % name)
if rebuild in (False, True):
@ -619,16 +654,19 @@ class Sphinx(object):
self.config.values[name] = (default, rebuild, types)
def add_event(self, name):
# type: (unicode) -> None
self.debug('[app] adding event: %r', name)
if name in self._events:
raise ExtensionError('Event %r already present' % name)
self._events[name] = ''
def set_translator(self, name, translator_class):
# type: (unicode, Any) -> None
self.info(bold('A Translator for the %s builder is changed.' % name))
self._translators[name] = translator_class
def add_node(self, node, **kwds):
# type: (nodes.Node, Any) -> None
self.debug('[app] adding node: %r', (node, kwds))
if not kwds.pop('override', False) and \
hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__):
@ -647,17 +685,15 @@ class Sphinx(object):
if translator is not None:
pass
elif key == 'html':
from sphinx.writers.html import HTMLTranslator as translator
from sphinx.writers.html import HTMLTranslator as translator # type: ignore
elif key == 'latex':
from sphinx.writers.latex import LaTeXTranslator as translator
from sphinx.writers.latex import LaTeXTranslator as translator # type: ignore
elif key == 'text':
from sphinx.writers.text import TextTranslator as translator
from sphinx.writers.text import TextTranslator as translator # type: ignore
elif key == 'man':
from sphinx.writers.manpage import ManualPageTranslator \
as translator
from sphinx.writers.manpage import ManualPageTranslator as translator # type: ignore # NOQA
elif key == 'texinfo':
from sphinx.writers.texinfo import TexinfoTranslator \
as translator
from sphinx.writers.texinfo import TexinfoTranslator as translator # type: ignore # NOQA
else:
# ignore invalid keys for compatibility
continue
@ -666,14 +702,16 @@ class Sphinx(object):
setattr(translator, 'depart_'+node.__name__, depart)
def add_enumerable_node(self, node, figtype, title_getter=None, **kwds):
# type: (nodes.Node, unicode, Callable, Any) -> None
self.enumerable_nodes[node] = (figtype, title_getter)
self.add_node(node, **kwds)
def _directive_helper(self, obj, content=None, arguments=None, **options):
# type: (Any, unicode, Any, Any) -> Any
if isinstance(obj, (types.FunctionType, types.MethodType)):
obj.content = content
obj.arguments = arguments or (0, 0, False)
obj.options = options
obj.content = content # type: ignore
obj.arguments = arguments or (0, 0, False) # type: ignore
obj.options = options # type: ignore
return convert_directive_function(obj)
else:
if content or arguments or options:
@ -682,6 +720,7 @@ class Sphinx(object):
return obj
def add_directive(self, name, obj, content=None, arguments=None, **options):
# type: (unicode, Any, unicode, Any, Any) -> None
self.debug('[app] adding directive: %r',
(name, obj, content, arguments, options))
if name in directives._directives:
@ -693,6 +732,7 @@ class Sphinx(object):
name, self._directive_helper(obj, content, arguments, **options))
def add_role(self, name, role):
# type: (unicode, Any) -> None
self.debug('[app] adding role: %r', (name, role))
if name in roles._roles:
self.warn('while setting up extension %s: role %r is '
@ -702,6 +742,7 @@ class Sphinx(object):
roles.register_local_role(name, role)
def add_generic_role(self, name, nodeclass):
# type: (unicode, Any) -> None
# don't use roles.register_generic_role because it uses
# register_canonical_role
self.debug('[app] adding generic role: %r', (name, nodeclass))
@ -714,12 +755,14 @@ class Sphinx(object):
roles.register_local_role(name, role)
def add_domain(self, domain):
# type: (Type[Domain]) -> None
self.debug('[app] adding domain: %r', domain)
if domain.name in self.domains:
raise ExtensionError('domain %s already registered' % domain.name)
self.domains[domain.name] = domain
def override_domain(self, domain):
# type: (Type[Domain]) -> None
self.debug('[app] overriding domain: %r', domain)
if domain.name not in self.domains:
raise ExtensionError('domain %s not yet registered' % domain.name)
@ -730,6 +773,7 @@ class Sphinx(object):
def add_directive_to_domain(self, domain, name, obj,
content=None, arguments=None, **options):
# type: (unicode, unicode, Any, unicode, Any, Any) -> None
self.debug('[app] adding directive to domain: %r',
(domain, name, obj, content, arguments, options))
if domain not in self.domains:
@ -738,12 +782,14 @@ class Sphinx(object):
self._directive_helper(obj, content, arguments, **options)
def add_role_to_domain(self, domain, name, role):
# type: (unicode, unicode, Any) -> None
self.debug('[app] adding role to domain: %r', (domain, name, role))
if domain not in self.domains:
raise ExtensionError('domain %s not yet registered' % domain)
self.domains[domain].roles[name] = role
def add_index_to_domain(self, domain, index):
# type: (unicode, unicode) -> None
self.debug('[app] adding index to domain: %r', (domain, index))
if domain not in self.domains:
raise ExtensionError('domain %s not yet registered' % domain)
@ -752,15 +798,16 @@ class Sphinx(object):
def add_object_type(self, directivename, rolename, indextemplate='',
parse_node=None, ref_nodeclass=None, objname='',
doc_field_types=[]):
# type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None
self.debug('[app] adding object type: %r',
(directivename, rolename, indextemplate, parse_node,
ref_nodeclass, objname, doc_field_types))
StandardDomain.object_types[directivename] = \
ObjType(objname or directivename, rolename)
# create a subclass of GenericObject as the new directive
new_directive = type(directivename, (GenericObject, object),
new_directive = type(directivename, (GenericObject, object), # type: ignore
{'indextemplate': indextemplate,
'parse_node': staticmethod(parse_node),
'parse_node': staticmethod(parse_node), # type: ignore
'doc_field_types': doc_field_types})
StandardDomain.directives[directivename] = new_directive
# XXX support more options?
@ -771,23 +818,26 @@ class Sphinx(object):
def add_crossref_type(self, directivename, rolename, indextemplate='',
ref_nodeclass=None, objname=''):
# type: (unicode, unicode, unicode, nodes.Node, unicode) -> None
self.debug('[app] adding crossref type: %r',
(directivename, rolename, indextemplate, ref_nodeclass,
objname))
StandardDomain.object_types[directivename] = \
ObjType(objname or directivename, rolename)
# create a subclass of Target as the new directive
new_directive = type(directivename, (Target, object),
new_directive = type(directivename, (Target, object), # type: ignore
{'indextemplate': indextemplate})
StandardDomain.directives[directivename] = new_directive
# XXX support more options?
StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
def add_transform(self, transform):
# type: (Transform) -> None
self.debug('[app] adding transform: %r', transform)
SphinxStandaloneReader.transforms.append(transform)
def add_javascript(self, filename):
# type: (unicode) -> None
self.debug('[app] adding javascript: %r', filename)
from sphinx.builders.html import StandaloneHTMLBuilder
if '://' in filename:
@ -797,6 +847,7 @@ class Sphinx(object):
posixpath.join('_static', filename))
def add_stylesheet(self, filename, alternate=None, title=None):
# type: (unicode) -> None
self.debug('[app] adding stylesheet: %r', filename)
from sphinx.builders.html import StandaloneHTMLBuilder
props = {}
@ -812,10 +863,12 @@ class Sphinx(object):
StandaloneHTMLBuilder.css_props[fname] = props
def add_latex_package(self, packagename, options=None):
# type: (unicode, unicode) -> None
self.debug('[app] adding latex package: %r', packagename)
self.builder.usepackages.append((packagename, options))
def add_lexer(self, alias, lexer):
# type: (unicode, Any) -> None
self.debug('[app] adding lexer: %r', (alias, lexer))
from sphinx.highlighting import lexers
if lexers is None:
@ -823,24 +876,28 @@ class Sphinx(object):
lexers[alias] = lexer
def add_autodocumenter(self, cls):
# type: (Any) -> None
self.debug('[app] adding autodocumenter: %r', cls)
from sphinx.ext import autodoc
autodoc.add_documenter(cls)
self.add_directive('auto' + cls.objtype, autodoc.AutoDirective)
def add_autodoc_attrgetter(self, type, getter):
# type: (Any, Callable) -> None
self.debug('[app] adding autodoc attrgetter: %r', (type, getter))
from sphinx.ext import autodoc
autodoc.AutoDirective._special_attrgetters[type] = getter
def add_search_language(self, cls):
# type: (Any) -> None
self.debug('[app] adding search language: %r', cls)
from sphinx.search import languages, SearchLanguage
assert issubclass(cls, SearchLanguage)
languages[cls.lang] = cls
def add_source_parser(self, suffix, parser):
self.debug('[app] adding search source_parser: %r, %r', (suffix, parser))
# type: (unicode, Parser) -> None
self.debug('[app] adding search source_parser: %r, %r', suffix, parser)
if suffix in self._additional_source_parsers:
self.warn('while setting up extension %s: source_parser for %r is '
'already registered, it will be overridden' %
@ -856,6 +913,7 @@ class TemplateBridge(object):
"""
def init(self, builder, theme=None, dirs=None):
# type: (Builder, unicode, List[unicode]) -> None
"""Called by the builder to initialize the template system.
*builder* is the builder object; you'll probably want to look at the
@ -867,6 +925,7 @@ class TemplateBridge(object):
raise NotImplementedError('must be implemented in subclasses')
def newest_template_mtime(self):
# type: () -> 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``.
@ -874,12 +933,14 @@ class TemplateBridge(object):
return 0
def render(self, template, context):
# type: (unicode, 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: (unicode, Dict) -> unicode
"""Called by the builder to render a template given as a string with a
specified context (a Python dictionary).
"""

View File

@ -22,7 +22,7 @@ from docutils import nodes
from sphinx.util import i18n, path_stabilize
from sphinx.util.osutil import SEP, relative_uri
from sphinx.util.i18n import find_catalog
from sphinx.util.console import bold, darkgreen
from sphinx.util.console import bold, darkgreen # type: ignore
from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
parallel_available
@ -30,6 +30,15 @@ from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
from sphinx import roles # noqa
from sphinx import directives # noqa
if False:
# For type annotation
from typing import Any, Callable, Iterable, Sequence, Tuple, Union # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.util.i18n import CatalogInfo # NOQA
from sphinx.util.tags import Tags # NOQA
class Builder(object):
"""
@ -47,7 +56,8 @@ class Builder(object):
allow_parallel = False
def __init__(self, app):
self.env = app.env
# type: (Sphinx) -> None
self.env = app.env # type: BuildEnvironment
self.env.set_versioning_method(self.versioning_method,
self.versioning_compare)
self.srcdir = app.srcdir
@ -57,11 +67,11 @@ class Builder(object):
if not path.isdir(self.doctreedir):
os.makedirs(self.doctreedir)
self.app = app
self.warn = app.warn
self.info = app.info
self.config = app.config
self.tags = app.tags
self.app = app # type: Sphinx
self.warn = app.warn # type: Callable
self.info = app.info # type: Callable
self.config = app.config # type: Config
self.tags = app.tags # type: Tags
self.tags.add(self.format)
self.tags.add(self.name)
self.tags.add("format_%s" % self.format)
@ -71,7 +81,7 @@ class Builder(object):
self.old_status_iterator = app.old_status_iterator
# images that need to be copied over (source -> dest)
self.images = {}
self.images = {} # type: Dict[unicode, unicode]
# basename of images directory
self.imagedir = ""
# relative path to image directory from current docname (used at writing docs)
@ -79,7 +89,7 @@ class Builder(object):
# these get set later
self.parallel_ok = False
self.finish_tasks = None
self.finish_tasks = None # type: Any
# load default translator class
self.translator_class = app._translators.get(self.name)
@ -88,12 +98,14 @@ class Builder(object):
# helper methods
def init(self):
# type: () -> None
"""Load necessary templates and perform initialization. The default
implementation does nothing.
"""
pass
def create_template_bridge(self):
# type: () -> None
"""Return the template bridge configured."""
if self.config.template_bridge:
self.templates = self.app.import_object(
@ -103,6 +115,7 @@ class Builder(object):
self.templates = BuiltinTemplateLoader()
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
"""Return the target URI for a document name.
*typ* can be used to qualify the link characteristic for individual
@ -111,6 +124,7 @@ class Builder(object):
raise NotImplementedError
def get_relative_uri(self, from_, to, typ=None):
# type: (unicode, unicode, unicode) -> unicode
"""Return a relative URI between two source filenames.
May raise environment.NoUri if there's no way to return a sensible URI.
@ -119,6 +133,7 @@ class Builder(object):
self.get_target_uri(to, typ))
def get_outdated_docs(self):
# type: () -> Union[unicode, Iterable[unicode]]
"""Return an iterable of output files that are outdated, or a string
describing what an update build will build.
@ -128,9 +143,10 @@ class Builder(object):
"""
raise NotImplementedError
supported_image_types = []
supported_image_types = [] # type: List[unicode]
def post_process_images(self, doctree):
# type: (nodes.Node) -> None
"""Pick the best candidate for all image URIs."""
for node in doctree.traverse(nodes.image):
if '?' in node['candidates']:
@ -157,6 +173,7 @@ class Builder(object):
# compile po methods
def compile_catalogs(self, catalogs, message):
# type: (Set[CatalogInfo], unicode) -> None
if not self.config.gettext_auto_build:
return
@ -170,6 +187,7 @@ class Builder(object):
catalog.write_mo(self.config.language)
def compile_all_catalogs(self):
# type: () -> None
catalogs = i18n.find_catalog_source_files(
[path.join(self.srcdir, x) for x in self.config.locale_dirs],
self.config.language,
@ -180,6 +198,7 @@ class Builder(object):
self.compile_catalogs(catalogs, message)
def compile_specific_catalogs(self, specified_files):
# type: (List[unicode]) -> None
def to_domain(fpath):
docname, _ = path.splitext(path_stabilize(fpath))
dom = find_catalog(docname, self.config.gettext_compact)
@ -196,6 +215,7 @@ class Builder(object):
self.compile_catalogs(catalogs, message)
def compile_update_catalogs(self):
# type: () -> None
catalogs = i18n.find_catalog_source_files(
[path.join(self.srcdir, x) for x in self.config.locale_dirs],
self.config.language,
@ -207,16 +227,19 @@ class Builder(object):
# build methods
def build_all(self):
# type: () -> None
"""Build all source files."""
self.build(None, summary='all source files', method='all')
def build_specific(self, filenames):
# type: (List[unicode]) -> None
"""Only rebuild as much as needed for changes in the *filenames*."""
# bring the filenames to the canonical format, that is,
# relative to the source directory and without source_suffix.
dirlen = len(self.srcdir) + 1
to_write = []
suffixes = tuple(self.config.source_suffix)
suffixes = None # type: Tuple[unicode]
suffixes = tuple(self.config.source_suffix) # type: ignore
for filename in filenames:
filename = path.normpath(path.abspath(filename))
if not filename.startswith(self.srcdir):
@ -240,6 +263,7 @@ class Builder(object):
'line' % len(to_write))
def build_update(self):
# type: () -> None
"""Only rebuild what was changed or added since last build."""
to_build = self.get_outdated_docs()
if isinstance(to_build, str):
@ -251,6 +275,7 @@ class Builder(object):
'out of date' % len(to_build))
def build(self, docnames, summary=None, method='update'):
# type: (Iterable[unicode], unicode, unicode) -> None
"""Main build method.
First updates the environment, and then calls :meth:`write`.
@ -328,6 +353,7 @@ class Builder(object):
self.finish_tasks.join()
def write(self, build_docnames, updated_docnames, method='update'):
# type: (Iterable[unicode], Sequence[unicode], unicode) -> None
if build_docnames is None or build_docnames == ['__all__']:
# build_all
build_docnames = self.env.found_docs
@ -349,7 +375,7 @@ class Builder(object):
self.prepare_writing(docnames)
self.info('done')
warnings = []
warnings = [] # type: List[Tuple[Tuple, Dict]]
self.env.set_warnfunc(lambda *args, **kwargs: warnings.append((args, kwargs)))
if self.parallel_ok:
# number of subprocesses is parallel-1 because the main process
@ -361,6 +387,7 @@ class Builder(object):
self.env.set_warnfunc(self.warn)
def _write_serial(self, docnames, warnings):
# type: (Sequence[unicode], List[Tuple[Tuple, Dict]]) -> None
for docname in self.app.status_iterator(
docnames, 'writing output... ', darkgreen, len(docnames)):
doctree = self.env.get_and_resolve_doctree(docname, self)
@ -370,7 +397,9 @@ class Builder(object):
self.warn(*warning, **kwargs)
def _write_parallel(self, docnames, warnings, nproc):
# type: (Iterable[unicode], List[Tuple[Tuple, Dict]], int) -> None
def write_process(docs):
# type: (List[Tuple[unicode, nodes.Node]]) -> List[Tuple[Tuple, Dict]]
local_warnings = []
def warnfunc(*args, **kwargs):
@ -384,7 +413,7 @@ class Builder(object):
warnings.extend(wlist)
# warm up caches/compile templates using the first document
firstname, docnames = docnames[0], docnames[1:]
firstname, docnames = docnames[0], docnames[1:] # type: ignore
doctree = self.env.get_and_resolve_doctree(firstname, self)
self.write_doc_serialized(firstname, doctree)
self.write_doc(firstname, doctree)
@ -409,20 +438,24 @@ class Builder(object):
self.warn(*warning, **kwargs)
def prepare_writing(self, docnames):
# type: (Set[unicode]) -> None
"""A place where you can add logic before :meth:`write_doc` is run"""
raise NotImplementedError
def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
"""Where you actually write something to the filesystem."""
raise NotImplementedError
def write_doc_serialized(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
"""Handle parts of write_doc that must be called in the main process
if parallel build is active.
"""
pass
def finish(self):
# type: () -> None
"""Finish the building process.
The default implementation does nothing.
@ -430,6 +463,7 @@ class Builder(object):
pass
def cleanup(self):
# type: () -> None
"""Cleanup any resources.
The default implementation does nothing.
@ -437,6 +471,7 @@ class Builder(object):
pass
def get_builder_config(self, option, default):
# type: (unicode, unicode) -> Any
"""Return a builder specific option.
This method allows customization of common builder settings by

View File

@ -19,7 +19,7 @@ import shlex
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.config import string_classes
from sphinx.util.osutil import copyfile, ensuredir, make_filename
from sphinx.util.console import bold
from sphinx.util.console import bold # type: ignore
from sphinx.util.fileutil import copy_asset
from sphinx.util.pycompat import htmlescape
from sphinx.util.matching import Matcher
@ -28,10 +28,13 @@ from sphinx.errors import SphinxError
import plistlib
import subprocess
if False:
# For type annotation
from sphinx.application import Sphinx # NOQA
# Use plistlib.dump in 3.4 and above
try:
write_plist = plistlib.dump
write_plist = plistlib.dump # type: ignore
except AttributeError:
write_plist = plistlib.writePlist
@ -83,6 +86,7 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
search = False
def init(self):
# type: () -> None
super(AppleHelpBuilder, self).init()
# the output files for HTML help must be .html only
self.out_suffix = '.html'
@ -101,12 +105,14 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
self.config.applehelp_locale + '.lproj')
def handle_finish(self):
# type: () -> None
super(AppleHelpBuilder, self).handle_finish()
self.finish_tasks.add_task(self.copy_localized_files)
self.finish_tasks.add_task(self.build_helpbook)
def copy_localized_files(self):
# type: () -> None
source_dir = path.join(self.confdir, self.config.applehelp_locale + '.lproj')
target_dir = self.outdir
@ -120,6 +126,7 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
self.info('done')
def build_helpbook(self):
# type: () -> None
contents_dir = path.join(self.bundle_path, 'Contents')
resources_dir = path.join(contents_dir, 'Resources')
language_dir = path.join(resources_dir,
@ -264,6 +271,7 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
def setup(app):
# type: (Sphinx) -> None
app.setup_extension('sphinx.builders.html')
app.add_builder(AppleHelpBuilder)
@ -286,10 +294,10 @@ def setup(app):
app.add_config_value('applehelp_title', lambda self: self.project + ' Help', 'applehelp')
app.add_config_value('applehelp_codesign_identity',
lambda self: environ.get('CODE_SIGN_IDENTITY', None),
'applehelp'),
'applehelp')
app.add_config_value('applehelp_codesign_flags',
lambda self: shlex.split(environ.get('OTHER_CODE_SIGN_FLAGS', '')),
'applehelp'),
'applehelp')
app.add_config_value('applehelp_indexer_path', '/usr/bin/hiutil', 'applehelp')
app.add_config_value('applehelp_codesign_path', '/usr/bin/codesign', 'applehelp')
app.add_config_value('applehelp_disable_external_tools', False, None)

View File

@ -19,10 +19,15 @@ from sphinx.locale import _
from sphinx.theming import Theme
from sphinx.builders import Builder
from sphinx.util.osutil import ensuredir, os_path
from sphinx.util.console import bold
from sphinx.util.console import bold # type: ignore
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.pycompat import htmlescape
if False:
# For type annotation
from typing import Any, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
class ChangesBuilder(Builder):
"""
@ -31,6 +36,7 @@ class ChangesBuilder(Builder):
name = 'changes'
def init(self):
# type: () -> None
self.create_template_bridge()
Theme.init_themes(self.confdir, self.config.html_theme_path,
warn=self.warn)
@ -38,19 +44,21 @@ class ChangesBuilder(Builder):
self.templates.init(self, self.theme)
def get_outdated_docs(self):
# type: () -> unicode
return self.outdir
typemap = {
'versionadded': 'added',
'versionchanged': 'changed',
'deprecated': 'deprecated',
}
} # type: Dict[unicode, unicode]
def write(self, *ignored):
# type: (Any) -> None
version = self.config.version
libchanges = {}
apichanges = []
otherchanges = {}
libchanges = {} # type: Dict[unicode, List[Tuple[unicode, unicode, int]]]
apichanges = [] # type: List[Tuple[unicode, unicode, int]]
otherchanges = {} # type: Dict[Tuple[unicode, unicode], List[Tuple[unicode, unicode, int]]] # NOQA
if version not in self.env.versionchanges:
self.info(bold('no changes in version %s.' % version))
return
@ -101,9 +109,9 @@ class ChangesBuilder(Builder):
'show_copyright': self.config.html_show_copyright,
'show_sphinx': self.config.html_show_sphinx,
}
with codecs.open(path.join(self.outdir, 'index.html'), 'w', 'utf8') as f:
with codecs.open(path.join(self.outdir, 'index.html'), 'w', 'utf8') as f: # type: ignore # NOQA
f.write(self.templates.render('changes/frameset.html', ctx))
with codecs.open(path.join(self.outdir, 'changes.html'), 'w', 'utf8') as f:
with codecs.open(path.join(self.outdir, 'changes.html'), 'w', 'utf8') as f: # type: ignore # NOQA
f.write(self.templates.render('changes/versionchanges.html', ctx))
hltext = ['.. versionadded:: %s' % version,
@ -120,7 +128,7 @@ class ChangesBuilder(Builder):
self.info(bold('copying source files...'))
for docname in self.env.all_docs:
with codecs.open(self.env.doc2path(docname), 'r',
with codecs.open(self.env.doc2path(docname), 'r', # type: ignore
self.env.config.source_encoding) as f:
try:
lines = f.readlines()
@ -129,7 +137,7 @@ class ChangesBuilder(Builder):
continue
targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
ensuredir(path.dirname(targetfn))
with codecs.open(targetfn, 'w', 'utf-8') as f:
with codecs.open(targetfn, 'w', 'utf-8') as f: # type: ignore
text = ''.join(hl(i+1, line) for (i, line) in enumerate(lines))
ctx = {
'filename': self.env.doc2path(docname, None),
@ -144,6 +152,7 @@ class ChangesBuilder(Builder):
self.outdir)
def hl(self, text, version):
# type: (unicode, unicode) -> unicode
text = htmlescape(text)
for directive in ['versionchanged', 'versionadded', 'deprecated']:
text = text.replace('.. %s:: %s' % (directive, version),
@ -151,8 +160,10 @@ class ChangesBuilder(Builder):
return text
def finish(self):
# type: () -> None
pass
def setup(app):
# type: (Sphinx) -> None
app.add_builder(ChangesBuilder)

View File

@ -25,7 +25,12 @@ from sphinx.builders.html import StandaloneHTMLBuilder
try:
import xml.etree.ElementTree as etree
except ImportError:
import lxml.etree as etree
import lxml.etree as etree # type: ignore
if False:
# For type annotation
from typing import Any # NOQA
from sphinx.application import Sphinx # NOQA
class DevhelpBuilder(StandaloneHTMLBuilder):
@ -44,14 +49,17 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
embedded = True
def init(self):
# type: () -> None
StandaloneHTMLBuilder.init(self)
self.out_suffix = '.html'
self.link_suffix = '.html'
def handle_finish(self):
# type: () -> None
self.build_devhelp(self.outdir, self.config.devhelp_basename)
def build_devhelp(self, outdir, outname):
# type: (unicode, unicode) -> None
self.info('dumping devhelp index...')
# Basic info
@ -69,6 +77,7 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
self.config.master_doc, self, prune_toctrees=False)
def write_toc(node, parent):
# type: (nodes.Node, nodes.Node) -> None
if isinstance(node, addnodes.compact_paragraph) or \
isinstance(node, nodes.bullet_list):
for subnode in node:
@ -82,6 +91,7 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
parent.attrib['name'] = node.astext()
def istoctree(node):
# type: (nodes.Node) -> bool
return isinstance(node, addnodes.compact_paragraph) and \
'toctree' in node
@ -93,6 +103,7 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
index = self.env.create_index(self)
def write_index(title, refs, subitems):
# type: (unicode, List[Any], Any) -> None
if len(refs) == 0:
pass
elif len(refs) == 1:
@ -105,7 +116,7 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
link=ref[1])
if subitems:
parent_title = re.sub(r'\s*\(.*\)\s*$', '', title)
parent_title = re.sub(r'\s*\(.*\)\s*$', '', title) # type: ignore
for subitem in subitems:
write_index("%s %s" % (parent_title, subitem[0]),
subitem[1], [])
@ -116,11 +127,12 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
# Dump the XML file
xmlfile = path.join(outdir, outname + '.devhelp.gz')
with gzip.open(xmlfile, 'w') as f:
with gzip.open(xmlfile, 'w') as f: # type: ignore
tree.write(f, 'utf-8')
def setup(app):
# type: (Sphinx) -> None
app.setup_extension('sphinx.builders.html')
app.add_builder(DevhelpBuilder)

View File

@ -31,7 +31,12 @@ from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util.osutil import ensuredir, copyfile, make_filename, EEXIST
from sphinx.util.smartypants import sphinx_smarty_pants as ssp
from sphinx.util.console import brown
from sphinx.util.console import brown # type: ignore
if False:
# For type annotation
from typing import Any, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
# (Fragment) templates from which the metainfo files content.opf, toc.ncx,
@ -159,7 +164,7 @@ MEDIA_TYPES = {
'.otf': 'application/x-font-otf',
'.ttf': 'application/x-font-ttf',
'.woff': 'application/font-woff',
}
} # type: Dict[unicode, unicode]
VECTOR_GRAPHICS_EXTENSIONS = ('.svg',)
@ -221,6 +226,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
refuri_re = REFURI_RE
def init(self):
# type: () -> None
StandaloneHTMLBuilder.init(self)
# the output files for epub must be .html only
self.out_suffix = '.xhtml'
@ -230,10 +236,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.use_index = self.get_builder_config('use_index', 'epub')
def get_theme_config(self):
# type: () -> Tuple[unicode, Dict]
return self.config.epub_theme, self.config.epub_theme_options
# generic support functions
def make_id(self, name, id_cache={}):
# type: (unicode, Dict[unicode, unicode]) -> unicode
# id_cache is intentionally mutable
"""Return a unique id for name."""
id = id_cache.get(name)
@ -243,6 +251,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return id
def esc(self, name):
# type: (unicode) -> unicode
"""Replace all characters not allowed in text an attribute values."""
# Like cgi.escape, but also replace apostrophe
name = name.replace('&', '&amp;')
@ -253,6 +262,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return name
def get_refnodes(self, doctree, result):
# type: (nodes.Node, List[Dict[unicode, Any]]) -> List[Dict[unicode, Any]]
"""Collect section titles, their depth in the toc and the refuri."""
# XXX: is there a better way than checking the attribute
# toctree-l[1-8] on the parent node?
@ -276,6 +286,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return result
def get_toc(self):
# type: () -> None
"""Get the total table of contents, containing the master_doc
and pre and post files not managed by sphinx.
"""
@ -291,6 +302,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.toc_add_files(self.refnodes)
def toc_add_files(self, refnodes):
# type: (List[nodes.Node]) -> None
"""Add the master_doc, pre and post files to a list of refnodes.
"""
refnodes.insert(0, {
@ -313,10 +325,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
})
def fix_fragment(self, prefix, fragment):
# type: (unicode, unicode) -> unicode
"""Return a href/id attribute with colons replaced by hyphens."""
return prefix + fragment.replace(':', '-')
def fix_ids(self, tree):
# type: (nodes.Node) -> None
"""Replace colons with hyphens in href and id attributes.
Some readers crash because they interpret the part as a
@ -337,9 +351,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
node.attributes['ids'] = newids
def add_visible_links(self, tree, show_urls='inline'):
# type: (nodes.Node, unicode) -> None
"""Add visible link targets for external links"""
def make_footnote_ref(doc, label):
# type: (nodes.Node, unicode) -> nodes.footnote_reference
"""Create a footnote_reference node with children"""
footnote_ref = nodes.footnote_reference('[#]_')
footnote_ref.append(nodes.Text(label))
@ -347,6 +363,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return footnote_ref
def make_footnote(doc, label, uri):
# type: (nodes.Node, unicode, unicode) -> nodes.footnote
"""Create a footnote node with children"""
footnote = nodes.footnote(uri)
para = nodes.paragraph()
@ -357,6 +374,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return footnote
def footnote_spot(tree):
# type: (nodes.Node) -> Tuple[nodes.Node, int]
"""Find or create a spot to place footnotes.
The function returns the tuple (parent, index)."""
@ -406,6 +424,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
fn_idx += 1
def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
"""Write one document file.
This method is overwritten in order to fix fragment identifiers
@ -413,9 +432,10 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""
self.fix_ids(doctree)
self.add_visible_links(doctree, self.config.epub_show_urls)
return StandaloneHTMLBuilder.write_doc(self, docname, doctree)
StandaloneHTMLBuilder.write_doc(self, docname, doctree)
def fix_genindex(self, tree):
# type: (nodes.Node) -> None
"""Fix href attributes for genindex pages."""
# XXX: modifies tree inline
# Logic modeled from themes/basic/genindex.html
@ -434,11 +454,13 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.fix_fragment(m.group(1), m.group(2)))
def is_vector_graphics(self, filename):
# type: (unicode) -> bool
"""Does the filename extension indicate a vector graphic format?"""
ext = path.splitext(filename)[-1]
return ext in VECTOR_GRAPHICS_EXTENSIONS
def copy_image_files_pil(self):
# type: () -> None
"""Copy images using the PIL.
The method tries to read and write the files with the PIL,
converting the format and resizing the image if necessary/possible.
@ -477,6 +499,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
(path.join(self.srcdir, src), err))
def copy_image_files(self):
# type: () -> None
"""Copy image files to destination directory.
This overwritten method can use the PIL to convert image files.
"""
@ -491,10 +514,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
super(EpubBuilder, self).copy_image_files()
def copy_download_files(self):
# type: () -> None
pass
def handle_page(self, pagename, addctx, templatename='page.html',
outfilename=None, event_arg=None):
# type: (unicode, Dict, unicode, unicode, Any) -> None
"""Create a rendered page.
This method is overwritten for genindex pages in order to fix href link
@ -510,6 +535,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
# Finish by building the epub file
def handle_finish(self):
# type: () -> None
"""Create the metainfo files and finally the epub."""
self.get_toc()
self.build_mimetype(self.outdir, 'mimetype')
@ -519,12 +545,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.build_epub(self.outdir, self.config.epub_basename + '.epub')
def build_mimetype(self, outdir, outname):
# type: (unicode, unicode) -> None
"""Write the metainfo file mimetype."""
self.info('writing %s file...' % outname)
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f:
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f: # type: ignore
f.write(self.mimetype_template)
def build_container(self, outdir, outname):
# type: (unicode, unicode) -> None
"""Write the metainfo file META-INF/cointainer.xml."""
self.info('writing %s file...' % outname)
fn = path.join(outdir, outname)
@ -533,14 +561,15 @@ class EpubBuilder(StandaloneHTMLBuilder):
except OSError as err:
if err.errno != EEXIST:
raise
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f:
f.write(self.container_template)
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f: # type: ignore
f.write(self.container_template) # type: ignore
def content_metadata(self, files, spine, guide):
# type: (List[unicode], Any, Any) -> Dict[unicode, Any]
"""Create a dictionary with all metadata for the content.opf
file properly escaped.
"""
metadata = {}
metadata = {} # type: Dict[unicode, Any]
metadata['title'] = self.esc(self.config.epub_title)
metadata['author'] = self.esc(self.config.epub_author)
metadata['uid'] = self.esc(self.config.epub_uid)
@ -556,6 +585,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return metadata
def build_content(self, outdir, outname):
# type: (unicode, unicode) -> None
"""Write the metainfo file content.opf It contains bibliographic data,
a file list and the spine (the reading order).
"""
@ -565,8 +595,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
if not outdir.endswith(os.sep):
outdir += os.sep
olen = len(outdir)
projectfiles = []
self.files = []
projectfiles = [] # type: List[unicode]
self.files = [] # type: List[unicode]
self.ignored_files = ['.buildinfo', 'mimetype', 'content.opf',
'toc.ncx', 'META-INF/container.xml',
'Thumbs.db', 'ehthumbs.db', '.DS_Store',
@ -679,16 +709,17 @@ class EpubBuilder(StandaloneHTMLBuilder):
'title': self.guide_titles['toc'],
'uri': self.esc(self.refnodes[0]['refuri'])
})
projectfiles = '\n'.join(projectfiles)
spine = '\n'.join(spine)
guide = '\n'.join(guide)
projectfiles = '\n'.join(projectfiles) # type: ignore
spine = '\n'.join(spine) # type: ignore
guide = '\n'.join(guide) # type: ignore
# write the project file
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f:
f.write(content_tmpl %
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f: # type: ignore
f.write(content_tmpl % # type: ignore
self.content_metadata(projectfiles, spine, guide))
def new_navpoint(self, node, level, incr=True):
# type: (nodes.Node, int, bool) -> unicode
"""Create a new entry in the toc from the node at given level."""
# XXX Modifies the node
if incr:
@ -700,6 +731,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return self.navpoint_template % node
def insert_subnav(self, node, subnav):
# type: (nodes.Node, unicode) -> unicode
"""Insert nested navpoints for given node.
The node and subnav are already rendered to text.
@ -709,6 +741,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return '\n'.join(nlist)
def build_navpoints(self, nodes):
# type: (nodes.Node) -> unicode
"""Create the toc navigation structure.
Subelements of a node are nested inside the navpoint. For nested nodes
@ -752,10 +785,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
return '\n'.join(navlist)
def toc_metadata(self, level, navpoints):
# type: (int, List[unicode]) -> Dict[unicode, Any]
"""Create a dictionary with all metadata for the toc.ncx file
properly escaped.
"""
metadata = {}
metadata = {} # type: Dict[unicode, Any]
metadata['uid'] = self.config.epub_uid
metadata['title'] = self.config.epub_title
metadata['level'] = level
@ -763,6 +797,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return metadata
def build_toc(self, outdir, outname):
# type: (unicode, unicode) -> None
"""Write the metainfo file toc.ncx."""
self.info('writing %s file...' % outname)
@ -778,29 +813,31 @@ class EpubBuilder(StandaloneHTMLBuilder):
navpoints = self.build_navpoints(refnodes)
level = max(item['level'] for item in self.refnodes)
level = min(level, self.config.epub_tocdepth)
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f:
f.write(self.toc_template % self.toc_metadata(level, navpoints))
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f: # type: ignore
f.write(self.toc_template % self.toc_metadata(level, navpoints)) # type: ignore
def build_epub(self, outdir, outname):
# type: (unicode, unicode) -> None
"""Write the epub file.
It is a zip file with the mimetype file stored uncompressed as the first
entry.
"""
self.info('writing %s file...' % outname)
projectfiles = ['META-INF/container.xml', 'content.opf', 'toc.ncx'] \
+ self.files
epub = zipfile.ZipFile(path.join(outdir, outname), 'w',
projectfiles = ['META-INF/container.xml', 'content.opf', 'toc.ncx'] # type: List[unicode] # NOQA
projectfiles.extend(self.files)
epub = zipfile.ZipFile(path.join(outdir, outname), 'w', # type: ignore
zipfile.ZIP_DEFLATED)
epub.write(path.join(outdir, 'mimetype'), 'mimetype',
epub.write(path.join(outdir, 'mimetype'), 'mimetype', # type: ignore
zipfile.ZIP_STORED)
for file in projectfiles:
fp = path.join(outdir, file)
epub.write(fp, file, zipfile.ZIP_DEFLATED)
epub.write(fp, file, zipfile.ZIP_DEFLATED) # type: ignore
epub.close()
def setup(app):
# type: (Sphinx) -> None
app.setup_extension('sphinx.builders.html')
app.add_builder(EpubBuilder)

View File

@ -111,13 +111,6 @@ class Epub3Builder(EpubBuilder):
content_template = PACKAGE_DOC_TEMPLATE
doctype = DOCTYPE
# Warning deprecated option
def init(self):
if self.config.epub3_page_progression_direction:
self.warn('epub3_page_progression_direction option is deprecated'
' from 1.5. Use epub3_writing_mode instead of this.')
super(Epub3Builder, self).init()
# Finish by building the epub file
def handle_finish(self):
"""Create the metainfo files and finally the epub."""
@ -135,8 +128,8 @@ class Epub3Builder(EpubBuilder):
"""
metadata = super(Epub3Builder, self).content_metadata(
files, spine, guide)
metadata['description'] = self.esc(self.config.epub3_description)
metadata['contributor'] = self.esc(self.config.epub3_contributor)
metadata['description'] = self.esc(self.config.epub_description)
metadata['contributor'] = self.esc(self.config.epub_contributor)
metadata['page_progression_direction'] = self._page_progression_direction()
metadata['ibook_scroll_axis'] = self._ibook_scroll_axis()
metadata['date'] = self.esc(datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"))
@ -144,25 +137,25 @@ class Epub3Builder(EpubBuilder):
return metadata
def _page_progression_direction(self):
if self.config.epub3_writing_mode == 'horizontal':
if self.config.epub_writing_mode == 'horizontal':
page_progression_direction = 'ltr'
elif self.config.epub3_writing_mode == 'vertical':
elif self.config.epub_writing_mode == 'vertical':
page_progression_direction = 'rtl'
else:
page_progression_direction = 'default'
return page_progression_direction
def _ibook_scroll_axis(self):
if self.config.epub3_writing_mode == 'horizontal':
if self.config.epub_writing_mode == 'horizontal':
scroll_axis = 'vertical'
elif self.config.epub3_writing_mode == 'vertical':
elif self.config.epub_writing_mode == 'vertical':
scroll_axis = 'horizontal'
else:
scroll_axis = 'default'
return scroll_axis
def _css_writing_mode(self):
if self.config.epub3_writing_mode == 'vertical':
if self.config.epub_writing_mode == 'vertical':
editing_mode = 'vertical-rl'
else:
editing_mode = 'horizontal-tb'
@ -263,11 +256,28 @@ class Epub3Builder(EpubBuilder):
self.files.append(outname)
def validate_config_values(app):
if app.config.epub3_description is not None:
app.warn('epub3_description is deprecated. Use epub_description instead.')
app.config.epub_description = app.config.epub3_description
if app.config.epub3_contributor is not None:
app.warn('epub3_contributor is deprecated. Use epub_contributor instead.')
app.config.epub_contributor = app.config.epub3_contributor
if app.config.epub3_page_progression_direction is not None:
app.warn('epub3_page_progression_direction option is deprecated'
' from 1.5. Use epub_writing_mode instead.')
def setup(app):
app.setup_extension('sphinx.builders.epub')
app.add_builder(Epub3Builder)
app.connect('builder-inited', validate_config_values)
app.add_config_value('epub3_description', '', 'epub3', string_classes)
app.add_config_value('epub3_contributor', 'unknown', 'epub3', string_classes)
app.add_config_value('epub3_writing_mode', 'horizontal', 'epub3', string_classes)
app.add_config_value('epub3_page_progression_direction', '', 'epub3', string_classes)
app.add_config_value('epub_description', '', 'epub3', string_classes)
app.add_config_value('epub_contributor', 'unknown', 'epub3', string_classes)
app.add_config_value('epub_writing_mode', 'horizontal', 'epub3', string_classes)
app.add_config_value('epub3_description', None, 'epub3', string_classes)
app.add_config_value('epub3_contributor', None, 'epub3', string_classes)
app.add_config_value('epub3_page_progression_direction', None, 'epub3', string_classes)

View File

@ -26,9 +26,16 @@ from sphinx.util.tags import Tags
from sphinx.util.nodes import extract_messages, traverse_translatable_index
from sphinx.util.osutil import safe_relpath, ensuredir, canon_path
from sphinx.util.i18n import find_catalog
from sphinx.util.console import darkgreen, purple, bold
from sphinx.util.console import darkgreen, purple, bold # type: ignore
from sphinx.locale import pairindextypes
if False:
# For type annotation
from typing import Any, Iterable, Tuple # NOQA
from docutils import nodes # NOQA
from sphinx.util.i18n import CatalogInfo # NOQA
from sphinx.application import Sphinx # NOQA
POHEADER = r"""
# SOME DESCRIPTIVE TITLE.
# Copyright (C) %(copyright)s
@ -55,10 +62,14 @@ class Catalog(object):
"""Catalog of translatable messages."""
def __init__(self):
self.messages = [] # retain insertion order, a la OrderedDict
self.metadata = {} # msgid -> file, line, uid
# type: () -> None
self.messages = [] # type: List[unicode]
# retain insertion order, a la OrderedDict
self.metadata = {} # type: Dict[unicode, List[Tuple[unicode, int, unicode]]]
# msgid -> file, line, uid
def add(self, msg, origin):
# type: (unicode, MsgOrigin) -> None
if not hasattr(origin, 'uid'):
# Nodes that are replicated like todo don't have a uid,
# however i18n is also unnecessary.
@ -75,6 +86,7 @@ class MsgOrigin(object):
"""
def __init__(self, source, line):
# type: (unicode, int) -> None
self.source = source
self.line = line
self.uid = uuid4().hex
@ -87,6 +99,7 @@ class I18nTags(Tags):
always returns True value even if no tags are defined.
"""
def eval_condition(self, condition):
# type: (Any) -> bool
return True
@ -99,27 +112,34 @@ class I18nBuilder(Builder):
versioning_compare = None # be set by `gettext_uuid`
def __init__(self, app):
# type: (Sphinx) -> None
self.versioning_compare = app.env.config.gettext_uuid
super(I18nBuilder, self).__init__(app)
def init(self):
# type: () -> None
Builder.init(self)
self.tags = I18nTags()
self.catalogs = defaultdict(Catalog)
self.catalogs = defaultdict(Catalog) # type: defaultdict[unicode, Catalog]
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
return ''
def get_outdated_docs(self):
# type: () -> Set[unicode]
return self.env.found_docs
def prepare_writing(self, docnames):
# type: (Set[unicode]) -> None
return
def compile_catalogs(self, catalogs, message):
# type: (Set[CatalogInfo], unicode) -> None
return
def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
catalog = self.catalogs[find_catalog(docname,
self.config.gettext_compact)]
@ -153,15 +173,19 @@ if source_date_epoch is not None:
class LocalTimeZone(tzinfo):
def __init__(self, *args, **kw):
super(LocalTimeZone, self).__init__(*args, **kw)
# type: (Any, Any) -> None
super(LocalTimeZone, self).__init__(*args, **kw) # type: ignore
self.tzdelta = tzdelta
def utcoffset(self, dt):
# type: (datetime) -> timedelta
return self.tzdelta
def dst(self, dt):
# type: (datetime) -> timedelta
return timedelta(0)
ltz = LocalTimeZone()
@ -172,11 +196,13 @@ class MessageCatalogBuilder(I18nBuilder):
name = 'gettext'
def init(self):
# type: () -> None
I18nBuilder.init(self)
self.create_template_bridge()
self.templates.init(self)
def _collect_templates(self):
# type: () -> Set[unicode]
template_files = set()
for template_path in self.config.templates_path:
tmpl_abs_path = path.join(self.app.srcdir, template_path)
@ -188,6 +214,7 @@ class MessageCatalogBuilder(I18nBuilder):
return template_files
def _extract_from_template(self):
# type: () -> None
files = self._collect_templates()
self.info(bold('building [%s]: ' % self.name), nonl=1)
self.info('targets for %d template files' % len(files))
@ -196,23 +223,25 @@ class MessageCatalogBuilder(I18nBuilder):
for template in self.app.status_iterator(
files, 'reading templates... ', purple, len(files)):
with open(template, 'r', encoding='utf-8') as f:
with open(template, 'r', encoding='utf-8') as f: # type: ignore
context = f.read()
for line, meth, msg in extract_translations(context):
origin = MsgOrigin(template, line)
self.catalogs['sphinx'].add(msg, origin)
def build(self, docnames, summary=None, method='update'):
# type: (Iterable[unicode], unicode, unicode) -> None
self._extract_from_template()
I18nBuilder.build(self, docnames, summary, method)
def finish(self):
# type: () -> None
I18nBuilder.finish(self)
data = dict(
version = self.config.version,
copyright = self.config.copyright,
project = self.config.project,
ctime = datetime.fromtimestamp(
ctime = datetime.fromtimestamp( # type: ignore
timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
)
for textdomain, catalog in self.app.status_iterator(
@ -223,31 +252,32 @@ class MessageCatalogBuilder(I18nBuilder):
ensuredir(path.join(self.outdir, path.dirname(textdomain)))
pofn = path.join(self.outdir, textdomain + '.pot')
with open(pofn, 'w', encoding='utf-8') as pofile:
pofile.write(POHEADER % data)
with open(pofn, 'w', encoding='utf-8') as pofile: # type: ignore
pofile.write(POHEADER % data) # type: ignore
for message in catalog.messages:
positions = catalog.metadata[message]
if self.config.gettext_location:
# generate "#: file1:line1\n#: file2:line2 ..."
pofile.write("#: %s\n" % "\n#: ".join(
pofile.write("#: %s\n" % "\n#: ".join( # type: ignore
"%s:%s" % (canon_path(
safe_relpath(source, self.outdir)), line)
for source, line, _ in positions))
if self.config.gettext_uuid:
# generate "# uuid1\n# uuid2\n ..."
pofile.write("# %s\n" % "\n# ".join(
pofile.write("# %s\n" % "\n# ".join( # type: ignore
uid for _, _, uid in positions))
# message contains *one* line of text ready for translation
message = message.replace('\\', r'\\'). \
replace('"', r'\"'). \
replace('\n', '\\n"\n"')
pofile.write('msgid "%s"\nmsgstr ""\n\n' % message)
pofile.write('msgid "%s"\nmsgstr ""\n\n' % message) # type: ignore
def setup(app):
# type: (Sphinx) -> None
app.add_builder(MessageCatalogBuilder)
app.add_config_value('gettext_compact', True, 'gettext')

View File

@ -19,6 +19,7 @@ from hashlib import md5
from six import iteritems, text_type, string_types
from six.moves import cPickle as pickle
from docutils import nodes
from docutils.io import DocTreeInput, StringOutput
from docutils.core import Publisher
@ -41,10 +42,16 @@ from sphinx.theming import Theme
from sphinx.builders import Builder
from sphinx.application import ENV_PICKLE_FILENAME
from sphinx.highlighting import PygmentsBridge
from sphinx.util.console import bold, darkgreen, brown
from sphinx.util.console import bold, darkgreen, brown # type: ignore
from sphinx.writers.html import HTMLWriter, HTMLTranslator, \
SmartyPantsHTMLTranslator
if False:
# For type annotation
from typing import Any, Iterable, Iterator, Tuple, Union # NOQA
from sphinx.domains import Domain, Index # NOQA
from sphinx.application import Sphinx # NOQA
#: the filename for the inventory of objects
INVENTORY_FILENAME = 'objects.inv'
#: the filename for the "last build" file (for serializing builders)
@ -52,6 +59,7 @@ LAST_BUILD_FILENAME = 'last_build'
def get_stable_hash(obj):
# type: (Any) -> unicode
"""
Return a stable hash for a Python data structure. We can't just use
the md5 of str(obj) since for example dictionary items are enumerated
@ -85,14 +93,18 @@ class StandaloneHTMLBuilder(Builder):
allow_sharp_as_current_path = True
embedded = False # for things like HTML help or Qt help: suppresses sidebar
search = True # for things like HTML help and Apple help: suppress search
use_index = False
download_support = True # enable download role
# This is a class attribute because it is mutated by Sphinx.add_javascript.
script_files = ['_static/jquery.js', '_static/underscore.js',
'_static/doctools.js']
'_static/doctools.js'] # type: List[unicode]
# Ditto for these ones (Sphinx.add_stylesheet).
css_files = []
css_props = {}
css_files = [] # type: List[unicode]
css_props = {} # type: Dict[unicode, unicode/bool]
imgpath = None # type: unicode
domain_indices = [] # type: List[Tuple[unicode, Index, unicode, bool]]
default_sidebars = ['localtoc.html', 'relations.html',
'sourcelink.html', 'searchbox.html']
@ -101,15 +113,16 @@ class StandaloneHTMLBuilder(Builder):
_publisher = None
def init(self):
# type: () -> None
# a hash of all config values that, if changed, cause a full rebuild
self.config_hash = ''
self.tags_hash = ''
self.config_hash = '' # type: unicode
self.tags_hash = '' # type: unicode
# basename of images directory
self.imagedir = '_images'
# section numbers for headings in the currently visited document
self.secnumbers = {}
self.secnumbers = {} # type: Dict[unicode, Tuple[int, ...]]
# currently written docname
self.current_docname = None
self.current_docname = None # type: unicode
self.init_templates()
self.init_highlighter()
@ -128,6 +141,7 @@ class StandaloneHTMLBuilder(Builder):
self.use_index = self.get_builder_config('use_index', 'html')
def _get_translations_js(self):
# type: () -> unicode
candidates = [path.join(package_dir, 'locale', self.config.language,
'LC_MESSAGES', 'sphinx.js'),
path.join(sys.prefix, 'share/sphinx/locale',
@ -141,9 +155,11 @@ class StandaloneHTMLBuilder(Builder):
return None
def get_theme_config(self):
# type: () -> Tuple[unicode, Dict]
return self.config.html_theme, self.config.html_theme_options
def init_templates(self):
# type: () -> None
Theme.init_themes(self.confdir, self.config.html_theme_path,
warn=self.warn)
themename, themeoptions = self.get_theme_config()
@ -153,6 +169,7 @@ class StandaloneHTMLBuilder(Builder):
self.templates.init(self, self.theme)
def init_highlighter(self):
# type: () -> None
# determine Pygments style and create the highlighter
if self.config.pygments_style is not None:
style = self.config.pygments_style
@ -164,18 +181,20 @@ class StandaloneHTMLBuilder(Builder):
self.config.trim_doctest_flags)
def init_translator_class(self):
# type: () -> None
if self.translator_class is None:
if self.config.html_use_smartypants:
self.translator_class = SmartyPantsHTMLTranslator
else:
self.translator_class = HTMLTranslator
def get_outdated_docs(self):
def get_outdated_docs(self): # type: ignore
# type: () -> Iterator[unicode]
cfgdict = dict((name, self.config[name])
for (name, desc) in iteritems(self.config.values)
if desc[1] == 'html')
self.config_hash = get_stable_hash(cfgdict)
self.tags_hash = get_stable_hash(sorted(self.tags))
self.tags_hash = get_stable_hash(sorted(self.tags)) # type: ignore
old_config_hash = old_tags_hash = ''
try:
with open(path.join(self.outdir, '.buildinfo')) as fp:
@ -223,6 +242,7 @@ class StandaloneHTMLBuilder(Builder):
pass
def render_partial(self, node):
# type: (nodes.Nodes) -> Dict[unicode, unicode]
"""Utility: Render a lone doctree node."""
if node is None:
return {'fragment': ''}
@ -248,6 +268,7 @@ class StandaloneHTMLBuilder(Builder):
return pub.writer.parts
def prepare_writing(self, docnames):
# type: (Iterable[unicode]) -> nodes.Node
# create the search indexer
self.indexer = None
if self.search:
@ -273,6 +294,7 @@ class StandaloneHTMLBuilder(Builder):
indices_config = self.config.html_domain_indices
if indices_config:
for domain_name in sorted(self.env.domains):
domain = None # type: Domain
domain = self.env.domains[domain_name]
for indexcls in domain.indices:
indexname = '%s-%s' % (domain.name, indexcls.name)
@ -314,7 +336,7 @@ class StandaloneHTMLBuilder(Builder):
rellinks = []
if self.use_index:
rellinks.append(('genindex', _('General Index'), 'I', _('index')))
for indexname, indexcls, content, collapse in self.domain_indices:
for indexname, indexcls, content, collapse in self.domain_indices: # type: ignore
# if it has a short name
if indexcls.shortname:
rellinks.append((indexname, indexcls.localname,
@ -355,7 +377,7 @@ class StandaloneHTMLBuilder(Builder):
parents = [],
logo = logo,
favicon = favicon,
)
) # type: Dict[unicode, Any]
if self.theme:
self.globalcontext.update(
('theme_' + key, val) for (key, val) in
@ -363,6 +385,7 @@ class StandaloneHTMLBuilder(Builder):
self.globalcontext.update(self.config.html_context)
def get_doc_context(self, docname, body, metatags):
# type: (unicode, unicode, Dict) -> Dict[unicode, Any]
"""Collect items for the template context of a page."""
# find out relations
prev = next = None
@ -443,6 +466,7 @@ class StandaloneHTMLBuilder(Builder):
)
def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
destination = StringOutput(encoding='utf-8')
doctree.settings = self.docsettings
@ -460,6 +484,7 @@ class StandaloneHTMLBuilder(Builder):
self.handle_page(docname, ctx, event_arg=doctree)
def write_doc_serialized(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir)
self.post_process_images(doctree)
title = self.env.longtitles.get(docname)
@ -467,6 +492,7 @@ class StandaloneHTMLBuilder(Builder):
self.index_page(docname, doctree, title)
def finish(self):
# type: () -> None
self.finish_tasks.add_task(self.gen_indices)
self.finish_tasks.add_task(self.gen_additional_pages)
self.finish_tasks.add_task(self.copy_image_files)
@ -479,6 +505,7 @@ class StandaloneHTMLBuilder(Builder):
self.handle_finish()
def gen_indices(self):
# type: () -> None
self.info(bold('generating indices...'), nonl=1)
# the global general index
@ -491,6 +518,7 @@ class StandaloneHTMLBuilder(Builder):
self.info()
def gen_additional_pages(self):
# type: () -> None
# pages from extensions
for pagelist in self.app.emit('html-collect-pages'):
for pagename, context, template in pagelist:
@ -517,6 +545,7 @@ class StandaloneHTMLBuilder(Builder):
self.info()
def write_genindex(self):
# type: () -> None
# the total count of lines for each index letter, used to distribute
# the entries into two columns
genindex = self.env.create_index(self)
@ -546,6 +575,7 @@ class StandaloneHTMLBuilder(Builder):
self.handle_page('genindex', genindexcontext, 'genindex.html')
def write_domain_indices(self):
# type: () -> None
for indexname, indexcls, content, collapse in self.domain_indices:
indexcontext = dict(
indextitle = indexcls.localname,
@ -556,6 +586,7 @@ class StandaloneHTMLBuilder(Builder):
self.handle_page(indexname, indexcontext, 'domainindex.html')
def copy_image_files(self):
# type: () -> None
# copy image files
if self.images:
ensuredir(path.join(self.outdir, self.imagedir))
@ -570,6 +601,7 @@ class StandaloneHTMLBuilder(Builder):
(path.join(self.srcdir, src), err))
def copy_download_files(self):
# type: () -> None
def to_relpath(f):
return relative_path(self.srcdir, f)
# copy downloadable files
@ -588,6 +620,7 @@ class StandaloneHTMLBuilder(Builder):
(path.join(self.srcdir, src), err))
def copy_static_files(self):
# type: () -> None
# copy static files
self.info(bold('copying static files... '), nonl=True)
ensuredir(path.join(self.outdir, '_static'))
@ -648,6 +681,7 @@ class StandaloneHTMLBuilder(Builder):
self.info('done')
def copy_extra_files(self):
# type: () -> None
# copy html_extra_path files
self.info(bold('copying extra files... '), nonl=True)
excluded = Matcher(self.config.exclude_patterns)
@ -662,6 +696,7 @@ class StandaloneHTMLBuilder(Builder):
self.info('done')
def write_buildinfo(self):
# type: () -> None
# write build info file
with open(path.join(self.outdir, '.buildinfo'), 'w') as fp:
fp.write('# Sphinx build info version 1\n'
@ -671,11 +706,13 @@ class StandaloneHTMLBuilder(Builder):
(self.config_hash, self.tags_hash))
def cleanup(self):
# type: () -> None
# clean up theme stuff
if self.theme:
self.theme.cleanup()
def post_process_images(self, doctree):
# type: (nodes.Node) -> None
"""Pick the best candidate for an image and link down-scaled images to
their high res version.
"""
@ -701,15 +738,16 @@ class StandaloneHTMLBuilder(Builder):
reference.append(node)
def load_indexer(self, docnames):
# type: (Set[unicode]) -> None
keep = set(self.env.all_docs) - set(docnames)
try:
searchindexfn = path.join(self.outdir, self.searchindex_filename)
if self.indexer_dumps_unicode:
f = codecs.open(searchindexfn, 'r', encoding='utf-8')
f = codecs.open(searchindexfn, 'r', encoding='utf-8') # type: ignore
else:
f = open(searchindexfn, 'rb')
f = open(searchindexfn, 'rb') # type: ignore
with f:
self.indexer.load(f, self.indexer_format)
self.indexer.load(f, self.indexer_format) # type: ignore
except (IOError, OSError, ValueError):
if keep:
self.warn('search index couldn\'t be loaded, but not all '
@ -719,6 +757,7 @@ class StandaloneHTMLBuilder(Builder):
self.indexer.prune(keep)
def index_page(self, pagename, doctree, title):
# type: (unicode, nodes.Node, unicode) -> None
# only index pages with title
if self.indexer is not None and title:
filename = self.env.doc2path(pagename, base=None)
@ -729,15 +768,18 @@ class StandaloneHTMLBuilder(Builder):
self.indexer.feed(pagename, title, doctree)
def _get_local_toctree(self, docname, collapse=True, **kwds):
# type: (unicode, bool, Any) -> unicode
if 'includehidden' not in kwds:
kwds['includehidden'] = False
return self.render_partial(self.env.get_toctree_for(
docname, self, collapse, **kwds))['fragment']
def get_outfilename(self, pagename):
# type: (unicode) -> unicode
return path.join(self.outdir, os_path(pagename) + self.out_suffix)
def add_sidebars(self, pagename, ctx):
# type: (unicode, Dict) -> None
def has_wildcard(pattern):
return any(char in pattern for char in '*?[')
sidebars = None
@ -770,11 +812,14 @@ class StandaloneHTMLBuilder(Builder):
# --------- these are overwritten by the serialization builder
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
return docname + self.link_suffix
def handle_page(self, pagename, addctx, templatename='page.html',
outfilename=None, event_arg=None):
# type: (unicode, Dict, unicode, unicode, Any) -> None
ctx = self.globalcontext.copy()
ctx['warn'] = self.warn
# current_page_name is backwards compatibility
ctx['pagename'] = ctx['current_page_name'] = pagename
default_baseuri = self.get_target_uri(pagename)
@ -830,7 +875,7 @@ class StandaloneHTMLBuilder(Builder):
# outfilename's path is in general different from self.outdir
ensuredir(path.dirname(outfilename))
try:
with codecs.open(outfilename, 'w', encoding, 'xmlcharrefreplace') as f:
with codecs.open(outfilename, 'w', encoding, 'xmlcharrefreplace') as f: # type: ignore # NOQA
f.write(output)
except (IOError, OSError) as err:
self.warn("error writing file %s: %s" % (outfilename, err))
@ -842,11 +887,13 @@ class StandaloneHTMLBuilder(Builder):
copyfile(self.env.doc2path(pagename), source_name)
def handle_finish(self):
# type: () -> None
if self.indexer:
self.finish_tasks.add_task(self.dump_search_index)
self.finish_tasks.add_task(self.dump_inventory)
def dump_inventory(self):
# type: () -> None
self.info(bold('dumping object inventory... '), nonl=True)
with open(path.join(self.outdir, INVENTORY_FILENAME), 'wb') as f:
f.write((u'# Sphinx inventory version 2\n'
@ -873,6 +920,7 @@ class StandaloneHTMLBuilder(Builder):
self.info('done')
def dump_search_index(self):
# type: () -> None
self.info(
bold('dumping search index in %s ... ' % self.indexer.label()),
nonl=True)
@ -881,11 +929,11 @@ class StandaloneHTMLBuilder(Builder):
# first write to a temporary file, so that if dumping fails,
# the existing index won't be overwritten
if self.indexer_dumps_unicode:
f = codecs.open(searchindexfn + '.tmp', 'w', encoding='utf-8')
f = codecs.open(searchindexfn + '.tmp', 'w', encoding='utf-8') # type: ignore
else:
f = open(searchindexfn + '.tmp', 'wb')
f = open(searchindexfn + '.tmp', 'wb') # type: ignore
with f:
self.indexer.dump(f, self.indexer_format)
self.indexer.dump(f, self.indexer_format) # type: ignore
movefile(searchindexfn + '.tmp', searchindexfn)
self.info('done')
@ -899,6 +947,7 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
name = 'dirhtml'
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
if docname == 'index':
return ''
if docname.endswith(SEP + 'index'):
@ -906,6 +955,7 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
return docname + SEP
def get_outfilename(self, pagename):
# type: (unicode) -> unicode
if pagename == 'index' or pagename.endswith(SEP + 'index'):
outfilename = path.join(self.outdir, os_path(pagename) +
self.out_suffix)
@ -916,6 +966,7 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
return outfilename
def prepare_writing(self, docnames):
# type: (Iterable[unicode]) -> None
StandaloneHTMLBuilder.prepare_writing(self, docnames)
self.globalcontext['no_search_suffix'] = True
@ -928,10 +979,12 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
name = 'singlehtml'
copysource = False
def get_outdated_docs(self):
def get_outdated_docs(self): # type: ignore
# type: () -> Union[unicode, List[unicode]]
return 'all documents'
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
if docname in self.env.all_docs:
# all references are on the same page...
return self.config.master_doc + self.out_suffix + \
@ -941,10 +994,12 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
return docname + self.out_suffix
def get_relative_uri(self, from_, to, typ=None):
# type: (unicode, unicode, unicode) -> unicode
# ignore source
return self.get_target_uri(to, typ)
def fix_refuris(self, tree):
# type: (nodes.Node) -> None
# fix refuris with double anchor
fname = self.config.master_doc + self.out_suffix
for refnode in tree.traverse(nodes.reference):
@ -959,6 +1014,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
refnode['refuri'] = fname + refuri[hashindex:]
def _get_local_toctree(self, docname, collapse=True, **kwds):
# type: (unicode, bool, Any) -> unicode
if 'includehidden' not in kwds:
kwds['includehidden'] = False
toctree = self.env.get_toctree_for(docname, self, collapse, **kwds)
@ -966,6 +1022,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
return self.render_partial(toctree)['fragment']
def assemble_doctree(self):
# type: () -> nodes.Node
master = self.config.master_doc
tree = self.env.get_doctree(master)
tree = inline_all_toctrees(self, set(), master, tree, darkgreen, [master])
@ -975,6 +1032,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
return tree
def assemble_toc_secnumbers(self):
# type: () -> Dict[unicode, Dict[Tuple[unicode, unicode], Tuple[int, ...]]]
# Assemble toc_secnumbers to resolve section numbers on SingleHTML.
# Merge all secnumbers to single secnumber.
#
@ -992,6 +1050,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
return {self.config.master_doc: new_secnumbers}
def assemble_toc_fignumbers(self):
# type: () -> Dict[unicode, Dict[Tuple[unicode, unicode], Dict[unicode, Tuple[int, ...]]]] # NOQA
# Assemble toc_fignumbers to resolve figure numbers on SingleHTML.
# Merge all fignumbers to single fignumber.
#
@ -1001,7 +1060,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
#
# There are related codes in inline_all_toctres() and
# HTMLTranslter#add_fignumber().
new_fignumbers = {}
new_fignumbers = {} # type: Dict[Tuple[unicode, unicode], Dict[unicode, Tuple[int, ...]]] # NOQA
# {u'foo': {'figure': {'id2': (2,), 'id1': (1,)}}, u'bar': {'figure': {'id1': (3,)}}}
for docname, fignumlist in iteritems(self.env.toc_fignumbers):
for figtype, fignums in iteritems(fignumlist):
@ -1012,8 +1071,9 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
return {self.config.master_doc: new_fignumbers}
def get_doc_context(self, docname, body, metatags):
# type: (unicode, unicode, Dict) -> Dict
# no relation links...
toc = self.env.get_toctree_for(self.config.master_doc, self, False)
toc = self.env.get_toctree_for(self.config.master_doc, self, False) # type: Any
# if there is no toctree, toc is None
if toc:
self.fix_refuris(toc)
@ -1038,6 +1098,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
)
def write(self, *ignored):
# type: (Any) -> None
docnames = self.env.all_docs
self.info(bold('preparing documents... '), nonl=True)
@ -1055,6 +1116,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
self.info('done')
def finish(self):
# type: () -> None
# no indices or search pages are supported
self.info(bold('writing additional files...'), nonl=1)
@ -1085,18 +1147,19 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
#: the serializing implementation to use. Set this to a module that
#: implements a `dump`, `load`, `dumps` and `loads` functions
#: (pickle, simplejson etc.)
implementation = None
implementation = None # type: Any
implementation_dumps_unicode = False
#: additional arguments for dump()
additional_dump_args = ()
#: the filename for the global context file
globalcontext_filename = None
globalcontext_filename = None # type: unicode
supported_image_types = ['image/svg+xml', 'image/png',
'image/gif', 'image/jpeg']
def init(self):
# type: () -> None
self.config_hash = ''
self.tags_hash = ''
self.imagedir = '_images'
@ -1109,6 +1172,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
self.use_index = self.get_builder_config('use_index', 'html')
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
if docname == 'index':
return ''
if docname.endswith(SEP + 'index'):
@ -1116,15 +1180,17 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
return docname + SEP
def dump_context(self, context, filename):
# type: (Dict, unicode) -> None
if self.implementation_dumps_unicode:
f = codecs.open(filename, 'w', encoding='utf-8')
f = codecs.open(filename, 'w', encoding='utf-8') # type: ignore
else:
f = open(filename, 'wb')
f = open(filename, 'wb') # type: ignore
with f:
self.implementation.dump(context, f, *self.additional_dump_args)
def handle_page(self, pagename, ctx, templatename='page.html',
outfilename=None, event_arg=None):
# type: (unicode, Dict, unicode, unicode, Any) -> None
ctx['current_page_name'] = pagename
self.add_sidebars(pagename, ctx)
@ -1148,6 +1214,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
copyfile(self.env.doc2path(pagename), source_name)
def handle_finish(self):
# type: () -> None
# dump the global context
outfilename = path.join(self.outdir, self.globalcontext_filename)
self.dump_context(self.globalcontext, outfilename)
@ -1179,6 +1246,7 @@ class PickleHTMLBuilder(SerializingHTMLBuilder):
globalcontext_filename = 'globalcontext.pickle'
searchindex_filename = 'searchindex.pickle'
# compatibility alias
WebHTMLBuilder = PickleHTMLBuilder
@ -1197,16 +1265,19 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
searchindex_filename = 'searchindex.json'
def init(self):
# type: () -> None
SerializingHTMLBuilder.init(self)
def validate_config_values(app):
# type: (Sphinx) -> None
if app.config.html_translator_class:
app.warn('html_translator_class is deprecated. '
'Use Sphinx.set_translator() API instead.')
def setup(app):
# type: (Sphinx) -> None
# builders
app.add_builder(StandaloneHTMLBuilder)
app.add_builder(DirectoryHTMLBuilder)

View File

@ -13,6 +13,7 @@ import os
from os import path
from six import iteritems
from docutils import nodes
from docutils.io import FileOutput
from docutils.utils import new_document
@ -28,9 +29,14 @@ from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.osutil import SEP, make_filename
from sphinx.util.console import bold, darkgreen
from sphinx.util.console import bold, darkgreen # type: ignore
from sphinx.writers.latex import LaTeXWriter
if False:
# For type annotation
from typing import Any, Iterable, Tuple, Union # NOQA
from sphinx.application import Sphinx # NOQA
class LaTeXBuilder(Builder):
"""
@ -41,44 +47,50 @@ class LaTeXBuilder(Builder):
supported_image_types = ['application/pdf', 'image/png', 'image/jpeg']
def init(self):
self.docnames = []
self.document_data = []
self.usepackages = []
# type: () -> None
self.docnames = [] # type: Iterable[unicode]
self.document_data = [] # type: List[Tuple[unicode, unicode, unicode, unicode, unicode, bool]] # NOQA
self.usepackages = [] # type: List[unicode]
texescape.init()
def get_outdated_docs(self):
# type: () -> Union[unicode, List[unicode]]
return 'all documents' # for now
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
if docname not in self.docnames:
raise NoUri
else:
return '%' + docname
def get_relative_uri(self, from_, to, typ=None):
# type: (unicode, unicode, unicode) -> unicode
# ignore source path
return self.get_target_uri(to, typ)
def init_document_data(self):
# type: () -> None
preliminary_document_data = [list(x) for x in self.config.latex_documents]
if not preliminary_document_data:
self.warn('no "latex_documents" config value found; no documents '
'will be written')
return
# assign subdirs to titles
self.titles = []
self.titles = [] # type: List[Tuple[unicode, unicode]]
for entry in preliminary_document_data:
docname = entry[0]
if docname not in self.env.all_docs:
self.warn('"latex_documents" config value references unknown '
'document %s' % docname)
continue
self.document_data.append(entry)
self.document_data.append(entry) # type: ignore
if docname.endswith(SEP+'index'):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
def write_stylesheet(self):
# type: () -> None
highlighter = highlighting.PygmentsBridge(
'latex', self.config.pygments_style, self.config.trim_doctest_flags)
stylesheet = path.join(self.outdir, 'sphinxhighlight.sty')
@ -89,6 +101,7 @@ class LaTeXBuilder(Builder):
f.write(highlighter.get_stylesheet())
def write(self, *ignored):
# type: (Any) -> None
docwriter = LaTeXWriter(self)
docsettings = OptionParser(
defaults=self.env.settings,
@ -131,6 +144,7 @@ class LaTeXBuilder(Builder):
self.info("done")
def get_contentsname(self, indexfile):
# type: (unicode) -> unicode
tree = self.env.get_doctree(indexfile)
contentsname = None
for toctree in tree.traverse(addnodes.toctree):
@ -141,6 +155,7 @@ class LaTeXBuilder(Builder):
return contentsname
def assemble_doctree(self, indexfile, toctree_only, appendices):
# type: (unicode, bool, List[unicode]) -> nodes.Node
self.docnames = set([indexfile] + appendices)
self.info(darkgreen(indexfile) + " ", nonl=1)
tree = self.env.get_doctree(indexfile)
@ -184,6 +199,7 @@ class LaTeXBuilder(Builder):
return largetree
def finish(self):
# type: () -> None
# copy image files
if self.images:
self.info(bold('copying images...'), nonl=1)
@ -220,17 +236,18 @@ class LaTeXBuilder(Builder):
def validate_config_values(app):
# type: (Sphinx) -> None
if app.config.latex_toplevel_sectioning not in (None, 'part', 'chapter', 'section'):
app.warn('invalid latex_toplevel_sectioning, ignored: %s' %
app.config.latex_toplevel_sectioning)
app.config.latex_toplevel_sectioning = None
app.config.latex_toplevel_sectioning = None # type: ignore
if app.config.latex_use_parts:
if app.config.latex_toplevel_sectioning:
app.warn('latex_use_parts conflicts with latex_toplevel_sectioning, ignored.')
else:
app.warn('latex_use_parts is deprecated. Use latex_toplevel_sectioning instead.')
app.config.latex_toplevel_sectioning = 'parts'
app.config.latex_toplevel_sectioning = 'parts' # type: ignore
if app.config.latex_use_modindex is not True: # changed by user
app.warn('latex_use_modeindex is deprecated. Use latex_domain_indices instead.')
@ -269,6 +286,7 @@ def validate_config_values(app):
def setup(app):
# type: (Sphinx) -> None
app.add_builder(LaTeXBuilder)
app.connect('builder-inited', validate_config_values)

View File

@ -16,9 +16,10 @@ import threading
from os import path
from requests.exceptions import HTTPError
from six.moves import queue
from six.moves import queue # type: ignore
from six.moves.urllib.parse import unquote
from six.moves.html_parser import HTMLParser
from docutils import nodes
# 2015-06-25 barry@python.org. This exception was deprecated in Python 3.3 and
@ -26,34 +27,45 @@ from docutils import nodes
# going to just remove it. If it doesn't exist, define an exception that will
# never be caught but leaves the code in check_anchor() intact.
try:
from six.moves.html_parser import HTMLParseError
from six.moves.html_parser import HTMLParseError # type: ignore
except ImportError:
class HTMLParseError(Exception):
class HTMLParseError(Exception): # type: ignore
pass
from sphinx.builders import Builder
from sphinx.util import encode_uri
from sphinx.util.console import purple, red, darkgreen, darkgray, \
darkred, turquoise
from sphinx.util.requests import requests, useragent_header
from sphinx.util import encode_uri, requests
from sphinx.util.console import ( # type: ignore
purple, red, darkgreen, darkgray, darkred, turquoise
)
from sphinx.util.requests import is_ssl_error
if False:
# For type annotation
from typing import Any, Tuple, Union # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.util.requests.requests import Response # NOQA
class AnchorCheckParser(HTMLParser):
"""Specialized HTML parser that looks for a specific anchor."""
def __init__(self, search_anchor):
# type: (unicode) -> None
HTMLParser.__init__(self)
self.search_anchor = search_anchor
self.found = False
def handle_starttag(self, tag, attrs):
# type: (Any, Dict[unicode, unicode]) -> None
for key, value in attrs:
if key in ('id', 'name') and value == self.search_anchor:
self.found = True
break
def check_anchor(response, anchor):
# type: (Response, unicode) -> bool
"""Reads HTML data from a response object `response` searching for `anchor`.
Returns True if anchor was found, False otherwise.
"""
@ -61,7 +73,7 @@ def check_anchor(response, anchor):
try:
# 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():
for chunk in response.iter_content(chunk_size=4096, decode_unicode=True):
parser.feed(chunk)
if parser.found:
break
@ -80,22 +92,22 @@ class CheckExternalLinksBuilder(Builder):
name = 'linkcheck'
def init(self):
# type: () -> None
self.to_ignore = [re.compile(x) for x in self.app.config.linkcheck_ignore]
self.good = set()
self.broken = {}
self.redirected = {}
self.anchors_ignore = [re.compile(x)
for x in self.app.config.linkcheck_anchors_ignore]
self.good = set() # type: Set[unicode]
self.broken = {} # type: Dict[unicode, unicode]
self.redirected = {} # type: Dict[unicode, Tuple[unicode, int]]
# set a timeout for non-responding servers
socket.setdefaulttimeout(5.0)
# create output file
open(path.join(self.outdir, 'output.txt'), 'w').close()
self.session = requests.Session()
self.session.headers = dict(useragent_header)
# create queues and worker threads
self.wqueue = queue.Queue()
self.rqueue = queue.Queue()
self.workers = []
self.workers = [] # type: List[threading.Thread]
for i in range(self.app.config.linkcheck_workers):
thread = threading.Thread(target=self.check_thread)
thread.setDaemon(True)
@ -103,6 +115,7 @@ class CheckExternalLinksBuilder(Builder):
self.workers.append(thread)
def check_thread(self):
# type: () -> None
kwargs = {}
if self.app.config.linkcheck_timeout:
kwargs['timeout'] = self.app.config.linkcheck_timeout
@ -110,9 +123,14 @@ class CheckExternalLinksBuilder(Builder):
kwargs['allow_redirects'] = True
def check_uri():
# type: () -> Tuple[unicode, unicode, int]
# split off anchor
if '#' in uri:
req_url, anchor = uri.split('#', 1)
for rex in self.anchors_ignore:
if rex.match(anchor):
anchor = None
break
else:
req_url = uri
anchor = None
@ -124,28 +142,25 @@ class CheckExternalLinksBuilder(Builder):
req_url = encode_uri(req_url)
try:
if anchor and self.app.config.linkcheck_anchors and \
not anchor.startswith('!'):
if anchor and self.app.config.linkcheck_anchors:
# Read the whole document and see if #anchor exists
# (Anchors starting with ! are ignored since they are
# commonly used for dynamic pages)
response = self.session.get(req_url, stream=True, **kwargs)
response = requests.get(req_url, stream=True, config=self.app.config,
**kwargs)
found = check_anchor(response, unquote(anchor))
if not found:
raise Exception("Anchor '%s' not found" % anchor)
else:
try:
# try a HEAD request, which should be easier on
# try a HEAD request first, which should be easier on
# the server and the network
response = self.session.head(req_url, **kwargs)
response = requests.head(req_url, config=self.app.config, **kwargs)
response.raise_for_status()
except HTTPError as err:
if err.response.status_code not in (403, 405):
raise
# retry with GET if that fails, some servers
# don't like HEAD requests and reply with 403 or 405
response = self.session.get(req_url, stream=True, **kwargs)
# 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)
response.raise_for_status()
except HTTPError as err:
if err.response.status_code == 401:
@ -154,7 +169,10 @@ class CheckExternalLinksBuilder(Builder):
else:
return 'broken', str(err), 0
except Exception as err:
return 'broken', str(err), 0
if is_ssl_error(err):
return 'ignored', str(err), 0
else:
return 'broken', str(err), 0
if response.url.rstrip('/') == req_url.rstrip('/'):
return 'working', '', 0
else:
@ -167,6 +185,7 @@ class CheckExternalLinksBuilder(Builder):
return 'redirected', new_url, code
def check():
# type: () -> Tuple[unicode, unicode, int]
# check for various conditions without bothering the network
if len(uri) == 0 or uri.startswith(('#', 'mailto:', 'ftp:')):
return 'unchecked', '', 0
@ -205,6 +224,7 @@ class CheckExternalLinksBuilder(Builder):
self.rqueue.put((uri, docname, lineno, status, info, code))
def process_result(self, result):
# type: (Tuple[unicode, unicode, int, unicode, unicode, int]) -> None
uri, docname, lineno, status, info, code = result
if status == 'unchecked':
return
@ -213,7 +233,10 @@ class CheckExternalLinksBuilder(Builder):
if lineno:
self.info('(line %4d) ' % lineno, nonl=1)
if status == 'ignored':
self.info(darkgray('-ignored- ') + uri)
if info:
self.info(darkgray('-ignored- ') + uri + ': ' + info)
else:
self.info(darkgray('-ignored- ') + uri)
elif status == 'local':
self.info(darkgray('-local- ') + uri)
self.write_entry('local', docname, lineno, uri)
@ -239,15 +262,19 @@ class CheckExternalLinksBuilder(Builder):
self.info(color('redirect ') + uri + color(' - ' + text + ' to ' + info))
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
return ''
def get_outdated_docs(self):
# type: () -> Set[unicode]
return self.env.found_docs
def prepare_writing(self, docnames):
# type: (nodes.Node) -> None
return
def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
self.info()
n = 0
for node in doctree.traverse(nodes.reference):
@ -271,17 +298,19 @@ class CheckExternalLinksBuilder(Builder):
self.app.statuscode = 1
def write_entry(self, what, docname, line, uri):
output = codecs.open(path.join(self.outdir, 'output.txt'), 'a', 'utf-8')
output.write("%s:%s: [%s] %s\n" % (self.env.doc2path(docname, None),
line, what, uri))
output.close()
# type: (unicode, unicode, int, unicode) -> None
with codecs.open(path.join(self.outdir, 'output.txt'), 'a', 'utf-8') as output: # type: ignore # NOQA
output.write("%s:%s: [%s] %s\n" % (self.env.doc2path(docname, None),
line, what, uri))
def finish(self):
# type: () -> None
for worker in self.workers:
self.wqueue.put((None, None, None), False)
def setup(app):
# type: (Sphinx) -> None
app.add_builder(CheckExternalLinksBuilder)
app.add_config_value('linkcheck_ignore', [], None)
@ -289,3 +318,6 @@ def setup(app):
app.add_config_value('linkcheck_timeout', None, None, [int])
app.add_config_value('linkcheck_workers', 5, None)
app.add_config_value('linkcheck_anchors', True, None)
# Anchors starting with ! are ignored since they are
# commonly used for dynamic pages
app.add_config_value('linkcheck_anchors_ignore', ["^!"], None)

View File

@ -12,6 +12,7 @@
from os import path
from six import string_types
from docutils.io import FileOutput
from docutils.frontend import OptionParser
@ -20,9 +21,14 @@ from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import make_filename
from sphinx.util.console import bold, darkgreen
from sphinx.util.console import bold, darkgreen # type: ignore
from sphinx.writers.manpage import ManualPageWriter
if False:
# For type annotation
from typing import Any, Union # NOQA
from sphinx.application import Sphinx # NOQA
class ManualPageBuilder(Builder):
"""
@ -30,22 +36,26 @@ class ManualPageBuilder(Builder):
"""
name = 'man'
format = 'man'
supported_image_types = []
supported_image_types = [] # type: List[unicode]
def init(self):
# type: () -> None
if not self.config.man_pages:
self.warn('no "man_pages" config value found; no manual pages '
'will be written')
def get_outdated_docs(self):
# type: () -> Union[unicode, List[unicode]]
return 'all manpages' # for now
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
if typ == 'token':
return ''
raise NoUri
def write(self, *ignored):
# type: (Any) -> None
docwriter = ManualPageWriter(self)
docsettings = OptionParser(
defaults=self.env.settings,
@ -69,7 +79,7 @@ class ManualPageBuilder(Builder):
encoding='utf-8')
tree = self.env.get_doctree(docname)
docnames = set()
docnames = set() # type: Set[unicode]
largetree = inline_all_toctrees(self, docnames, docname, tree,
darkgreen, [docname])
self.info('} ', nonl=True)
@ -88,10 +98,12 @@ class ManualPageBuilder(Builder):
self.info()
def finish(self):
# type: () -> None
pass
def setup(app):
# type: (Sphinx) -> None
app.add_builder(ManualPageBuilder)
app.add_config_value('man_pages',

View File

@ -16,6 +16,7 @@ import posixpath
from os import path
from six import text_type
from docutils import nodes
from sphinx import addnodes
@ -24,6 +25,11 @@ from sphinx.util import force_decode
from sphinx.util.osutil import make_filename
from sphinx.util.pycompat import htmlescape
if False:
# For type annotation
from typing import Any, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
_idpattern = re.compile(
r'(?P<title>.+) (\((class in )?(?P<id>[\w\.]+)( (?P<descr>\w+))?\))$')
@ -115,6 +121,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
search = False
def init(self):
# type: () -> None
StandaloneHTMLBuilder.init(self)
# the output files for HTML help must be .html only
self.out_suffix = '.html'
@ -122,12 +129,15 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
# self.config.html_style = 'traditional.css'
def get_theme_config(self):
# type: () -> Tuple[unicode, Dict]
return self.config.qthelp_theme, self.config.qthelp_theme_options
def handle_finish(self):
# type: () -> None
self.build_qhp(self.outdir, self.config.qthelp_basename)
def build_qhp(self, outdir, outname):
# type: (unicode, unicode) -> None
self.info('writing project file...')
# sections
@ -153,7 +163,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
new_sections.append(force_decode(section, None))
else:
new_sections.append(section)
sections = u'\n'.join(new_sections)
sections = u'\n'.join(new_sections) # type: ignore
# keywords
keywords = []
@ -161,7 +171,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
for (key, group) in index:
for title, (refs, subitems, key_) in group:
keywords.extend(self.build_keywords(title, refs, subitems))
keywords = u'\n'.join(keywords)
keywords = u'\n'.join(keywords) # type: ignore
# files
if not outdir.endswith(os.sep):
@ -179,7 +189,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
filename = path.join(root, fn)[olen:]
projectfiles.append(file_template %
{'filename': htmlescape(filename)})
projectfiles = '\n'.join(projectfiles)
projectfiles = '\n'.join(projectfiles) # type: ignore
# it seems that the "namespace" may not contain non-alphanumeric
# characters, and more than one successive dot, or leading/trailing
@ -190,8 +200,8 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
nspace = nspace.lower()
# write the project file
with codecs.open(path.join(outdir, outname+'.qhp'), 'w', 'utf-8') as f:
f.write(project_template % {
with codecs.open(path.join(outdir, outname+'.qhp'), 'w', 'utf-8') as f: # type: ignore
f.write(project_template % { # type: ignore
'outname': htmlescape(outname),
'title': htmlescape(self.config.html_title),
'version': htmlescape(self.config.version),
@ -207,14 +217,15 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
startpage = 'qthelp://' + posixpath.join(nspace, 'doc', 'index.html')
self.info('writing collection project file...')
with codecs.open(path.join(outdir, outname+'.qhcp'), 'w', 'utf-8') as f:
f.write(collection_template % {
with codecs.open(path.join(outdir, outname+'.qhcp'), 'w', 'utf-8') as f: # type: ignore # NOQA
f.write(collection_template % { # type: ignore
'outname': htmlescape(outname),
'title': htmlescape(self.config.html_short_title),
'homepage': htmlescape(homepage),
'startpage': htmlescape(startpage)})
def isdocnode(self, node):
# type: (nodes.Node) -> bool
if not isinstance(node, nodes.list_item):
return False
if len(node.children) != 2:
@ -228,8 +239,9 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
return True
def write_toc(self, node, indentlevel=4):
# type: (nodes.Node, int) -> List[unicode]
# XXX this should return a Unicode string, not a bytestring
parts = []
parts = [] # type: List[unicode]
if self.isdocnode(node):
refnode = node.children[0][0]
link = refnode['refuri']
@ -247,7 +259,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
link = node['refuri']
title = htmlescape(node.astext()).replace('"', '&quot;')
item = section_template % {'title': title, 'ref': link}
item = u' ' * 4 * indentlevel + item
item = u' ' * 4 * indentlevel + item # type: ignore
parts.append(item.encode('ascii', 'xmlcharrefreplace'))
elif isinstance(node, nodes.bullet_list):
for subnode in node:
@ -259,7 +271,8 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
return parts
def keyword_item(self, name, ref):
matchobj = _idpattern.match(name)
# type: (unicode, Any) -> unicode
matchobj = _idpattern.match(name) # type: ignore
if matchobj:
groupdict = matchobj.groupdict()
shortname = groupdict['title']
@ -280,7 +293,8 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
return item
def build_keywords(self, title, refs, subitems):
keywords = []
# type: (unicode, List[Any], Any) -> List[unicode]
keywords = [] # type: List[unicode]
title = htmlescape(title)
# if len(refs) == 0: # XXX
@ -304,6 +318,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
def setup(app):
# type: (Sphinx) -> None
app.setup_extension('sphinx.builders.html')
app.add_builder(QtHelpBuilder)

View File

@ -12,6 +12,7 @@
from os import path
from six import iteritems
from docutils import nodes
from docutils.io import FileOutput
from docutils.utils import new_document
@ -23,9 +24,14 @@ from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import SEP, copyfile, make_filename
from sphinx.util.console import bold, darkgreen
from sphinx.util.console import bold, darkgreen # type: ignore
from sphinx.writers.texinfo import TexinfoWriter
if False:
# For type annotation
from sphinx.application import Sphinx # NOQA
from typing import Any, Iterable, Tuple, Union # NOQA
TEXINFO_MAKEFILE = '''\
# Makefile for Sphinx Texinfo output
@ -91,47 +97,53 @@ class TexinfoBuilder(Builder):
'image/gif']
def init(self):
self.docnames = []
self.document_data = []
# type: () -> None
self.docnames = [] # type: Iterable[unicode]
self.document_data = [] # type: List[Tuple[unicode, unicode, unicode, unicode, unicode, unicode, unicode, bool]] # NOQA
def get_outdated_docs(self):
# type: () -> Union[unicode, List[unicode]]
return 'all documents' # for now
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
if docname not in self.docnames:
raise NoUri
else:
return '%' + docname
def get_relative_uri(self, from_, to, typ=None):
# type: (unicode, unicode, unicode) -> unicode
# ignore source path
return self.get_target_uri(to, typ)
def init_document_data(self):
# type: () -> None
preliminary_document_data = [list(x) for x in self.config.texinfo_documents]
if not preliminary_document_data:
self.warn('no "texinfo_documents" config value found; no documents '
'will be written')
return
# assign subdirs to titles
self.titles = []
self.titles = [] # type: List[Tuple[unicode, unicode]]
for entry in preliminary_document_data:
docname = entry[0]
if docname not in self.env.all_docs:
self.warn('"texinfo_documents" config value references unknown '
'document %s' % docname)
continue
self.document_data.append(entry)
self.document_data.append(entry) # type: ignore
if docname.endswith(SEP+'index'):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
def write(self, *ignored):
# type: (Any) -> None
self.init_document_data()
for entry in self.document_data:
docname, targetname, title, author = entry[:4]
targetname += '.texi'
direntry = description = category = ''
direntry = description = category = '' # type: unicode
if len(entry) > 6:
direntry, description, category = entry[4:7]
toctree_only = False
@ -164,6 +176,7 @@ class TexinfoBuilder(Builder):
self.info("done")
def assemble_doctree(self, indexfile, toctree_only, appendices):
# type: (unicode, bool, List[unicode]) -> nodes.Node
self.docnames = set([indexfile] + appendices)
self.info(darkgreen(indexfile) + " ", nonl=1)
tree = self.env.get_doctree(indexfile)
@ -206,6 +219,7 @@ class TexinfoBuilder(Builder):
return largetree
def finish(self):
# type: () -> None
# copy image files
if self.images:
self.info(bold('copying images...'), nonl=1)
@ -228,6 +242,7 @@ class TexinfoBuilder(Builder):
def setup(app):
# type: (Sphinx) -> None
app.add_builder(TexinfoBuilder)
app.add_config_value('texinfo_documents',

View File

@ -25,6 +25,8 @@ class TextBuilder(Builder):
out_suffix = '.txt'
allow_parallel = True
current_docname = None # type: unicode
def init(self):
pass

View File

@ -16,17 +16,22 @@ import traceback
from os import path
from six import text_type, binary_type
from docutils.utils import SystemMessage
from sphinx import __display_version__
from sphinx.errors import SphinxError
from sphinx.application import Sphinx
from sphinx.util import Tee, format_exception_cut_frames, save_traceback
from sphinx.util.console import red, nocolor, color_terminal
from sphinx.util.console import red, nocolor, color_terminal # type: ignore
from sphinx.util.docutils import docutils_namespace
from sphinx.util.osutil import abspath, fs_encoding
from sphinx.util.pycompat import terminal_safe
if False:
# For type annotation
from typing import Any, IO, Union # NOQA
USAGE = """\
Sphinx v%s
@ -45,18 +50,21 @@ For more information, visit <http://sphinx-doc.org/>.
class MyFormatter(optparse.IndentedHelpFormatter):
def format_usage(self, usage):
# type: (Any) -> Any
return usage
def format_help(self, formatter):
result = []
if self.description:
# type: (Any) -> unicode
result = [] # type: List[unicode]
if self.description: # type: ignore
result.append(self.format_description(formatter))
if self.option_list:
result.append(self.format_option_help(formatter))
if self.option_list: # type: ignore
result.append(self.format_option_help(formatter)) # type: ignore
return "\n".join(result)
def handle_exception(app, opts, exception, stderr=sys.stderr):
# type: (Sphinx, Any, Union[Exception, KeyboardInterrupt], IO) -> None
if opts.pdb:
import pdb
print(red('Exception occurred while building, starting debugger:'),
@ -107,6 +115,7 @@ def handle_exception(app, opts, exception, stderr=sys.stderr):
def main(argv):
# type: (List[unicode]) -> int
if not color_terminal():
nocolor()
@ -210,11 +219,11 @@ def main(argv):
# handle remaining filename arguments
filenames = args[2:]
err = 0
err = 0 # type: ignore
for filename in filenames:
if not path.isfile(filename):
print('Error: Cannot find file %r.' % filename, file=sys.stderr)
err = 1
err = 1 # type: ignore
if err:
return 1
@ -249,13 +258,13 @@ def main(argv):
print('Error: Cannot open warning file %r: %s' %
(opts.warnfile, exc), file=sys.stderr)
sys.exit(1)
warning = Tee(warning, warnfp)
warning = Tee(warning, warnfp) # type: ignore
error = warning
confoverrides = {}
for val in opts.define:
try:
key, val = val.split('=')
key, val = val.split('=', 1)
except ValueError:
print('Error: -D option argument must be in the form name=value.',
file=sys.stderr)

View File

@ -16,9 +16,14 @@ from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integ
from sphinx.errors import ConfigError
from sphinx.locale import l_
from sphinx.util.i18n import format_date
from sphinx.util.osutil import cd
from sphinx.util.pycompat import execfile_, NoneType
from sphinx.util.i18n import format_date
if False:
# For type annotation
from typing import Any, Callable, Tuple # NOQA
from sphinx.util.tags import Tags # NOQA
nonascii_re = re.compile(br'[\x80-\xff]')
copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])')
@ -30,8 +35,10 @@ CONFIG_EXIT_ERROR = "The configuration file (or one of the modules it imports) "
"called sys.exit()"
CONFIG_ENUM_WARNING = "The config value `{name}` has to be a one of {candidates}, " \
"but `{current}` is given."
CONFIG_PERMITTED_TYPE_WARNING = "The config value `{name}' has type `{current.__name__}', " \
"expected to {permitted}."
CONFIG_TYPE_WARNING = "The config value `{name}' has type `{current.__name__}', " \
"defaults to `{default.__name__}.'"
"defaults to `{default.__name__}'."
class ENUM(object):
@ -41,13 +48,15 @@ class ENUM(object):
app.add_config_value('latex_show_urls', 'no', ENUM('no', 'footnote', 'inline'))
"""
def __init__(self, *candidates):
# type: (unicode) -> None
self.candidates = candidates
def match(self, value):
# type: (unicode) -> bool
return value in self.candidates
string_classes = [text_type]
string_classes = [text_type] # type: List
if PY2:
string_classes.append(binary_type) # => [str, unicode]
@ -110,14 +119,18 @@ class Config(object):
'code-block': l_('Listing %s')},
'env'),
tls_verify = (True, 'env'),
tls_cacerts = (None, 'env'),
# pre-initialized confval for HTML builder
html_translator_class = (None, 'html', string_classes),
)
) # type: Dict[unicode, Tuple]
def __init__(self, dirname, filename, overrides, tags):
# type: (unicode, unicode, Dict, Tags) -> None
self.overrides = overrides
self.values = Config.config_values.copy()
config = {}
config = {} # type: Dict[unicode, Any]
if dirname is not None:
config_file = path.join(dirname, filename)
config['__file__'] = config_file
@ -135,14 +148,14 @@ class Config(object):
self._raw_config = config
# these two must be preinitialized because extensions can add their
# own config values
self.setup = config.get('setup', None)
self.setup = config.get('setup', None) # type: Callable
if 'extensions' in overrides:
if isinstance(overrides['extensions'], string_types):
config['extensions'] = overrides.pop('extensions').split(',')
else:
config['extensions'] = overrides.pop('extensions')
self.extensions = config.get('extensions', [])
self.extensions = config.get('extensions', []) # type: List[unicode]
# correct values of copyright year that are not coherent with
# the SOURCE_DATE_EPOCH environment variable (if set)
@ -150,10 +163,11 @@ class Config(object):
if getenv('SOURCE_DATE_EPOCH') is not None:
for k in ('copyright', 'epub_copyright'):
if k in config:
config[k] = copyright_year_re.sub('\g<1>%s' % format_date('%Y'),
config[k] = copyright_year_re.sub('\g<1>%s' % format_date('%Y'), # type: ignore # NOQA
config[k])
def check_types(self, warn):
# type: (Callable) -> None
# check all values for deviation from the default value's type, since
# that can result in TypeErrors all over the place
# NB. since config values might use l_() we have to wait with calling
@ -186,19 +200,26 @@ class Config(object):
if common_bases:
continue # at least we share a non-trivial base class
warn(CONFIG_TYPE_WARNING.format(
name=name, current=type(current), default=type(default)))
if permitted:
warn(CONFIG_PERMITTED_TYPE_WARNING.format(
name=name, current=type(current),
permitted=str([cls.__name__ for cls in permitted])))
else:
warn(CONFIG_TYPE_WARNING.format(
name=name, current=type(current), default=type(default)))
def check_unicode(self, warn):
# type: (Callable) -> None
# check all string values for non-ASCII characters in bytestrings,
# since that can result in UnicodeErrors all over the place
for name, value in iteritems(self._raw_config):
if isinstance(value, binary_type) and nonascii_re.search(value):
if isinstance(value, binary_type) and nonascii_re.search(value): # type: ignore
warn('the config value %r is set to a string with non-ASCII '
'characters; this can lead to Unicode errors occurring. '
'Please use Unicode strings, e.g. %r.' % (name, u'Content'))
def convert_overrides(self, name, value):
# type: (unicode, Any) -> Any
if not isinstance(value, string_types):
return value
else:
@ -208,10 +229,10 @@ class Config(object):
'ignoring (use %r to set individual elements)' %
(name, name + '.key=value'))
elif isinstance(defvalue, list):
return value.split(',')
return value.split(',') # type: ignore
elif isinstance(defvalue, integer_types):
try:
return int(value)
return int(value) # type: ignore
except ValueError:
raise ValueError('invalid number %r for config value %r, ignoring' %
(value, name))
@ -224,6 +245,7 @@ class Config(object):
return value
def pre_init_values(self, warn):
# type: (Callable) -> None
"""Initialize some limited config variables before loading extensions"""
variables = ['needs_sphinx', 'suppress_warnings', 'html_translator_class']
for name in variables:
@ -236,12 +258,13 @@ class Config(object):
warn(exc)
def init_values(self, warn):
# type: (Callable) -> None
config = self._raw_config
for valname, value in iteritems(self.overrides):
try:
if '.' in valname:
realvalname, key = valname.split('.', 1)
config.setdefault(realvalname, {})[key] = value
config.setdefault(realvalname, {})[key] = value # type: ignore
continue
elif valname not in self.values:
warn('unknown config value %r in override, ignoring' % valname)
@ -255,10 +278,11 @@ class Config(object):
for name in config:
if name in self.values:
self.__dict__[name] = config[name]
if isinstance(self.source_suffix, string_types):
self.source_suffix = [self.source_suffix]
if isinstance(self.source_suffix, string_types): # type: ignore
self.source_suffix = [self.source_suffix] # type: ignore
def __getattr__(self, name):
# type: (unicode) -> Any
if name.startswith('_'):
raise AttributeError(name)
if name not in self.values:
@ -269,13 +293,17 @@ class Config(object):
return default
def __getitem__(self, name):
# type: (unicode) -> unicode
return getattr(self, name)
def __setitem__(self, name, value):
# type: (unicode, Any) -> None
setattr(self, name, value)
def __delitem__(self, name):
# type: (unicode) -> None
delattr(self, name)
def __contains__(self, name):
# type: (unicode) -> bool
return name in self.values

21
sphinx/deprecation.py Normal file
View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
"""
sphinx.deprecation
~~~~~~~~~~~~~~~~~~
Sphinx deprecation classes and utilities.
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
class RemovedInSphinx16Warning(DeprecationWarning):
pass
class RemovedInSphinx17Warning(PendingDeprecationWarning):
pass
RemovedInNextVersionWarning = RemovedInSphinx16Warning

View File

@ -17,6 +17,24 @@ from docutils.parsers.rst import Directive, directives, roles
from sphinx import addnodes
from sphinx.util.docfields import DocFieldTransformer
# import all directives sphinx provides
from sphinx.directives.code import ( # noqa
Highlight, CodeBlock, LiteralInclude
)
from sphinx.directives.other import ( # noqa
TocTree, Author, Index, VersionChange, SeeAlso,
TabularColumns, Centered, Acks, HList, Only, Include, Class
)
from sphinx.directives.patches import ( # noqa
Figure, Meta
)
if False:
# For type annotation
from typing import Any # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
# RE to strip backslash escapes
nl_escape_re = re.compile(r'\\\n')
@ -39,9 +57,13 @@ class ObjectDescription(Directive):
}
# types of doc fields that this directive handles, see sphinx.util.docfields
doc_field_types = []
doc_field_types = [] # type: List[Any]
domain = None # type: unicode
objtype = None # type: unicode
indexnode = None # type: addnodes.index
def get_signatures(self):
# type: () -> List[unicode]
"""
Retrieve the signatures to document from the directive arguments. By
default, signatures are given as arguments, one per line.
@ -53,6 +75,7 @@ class ObjectDescription(Directive):
return [strip_backslash_re.sub(r'\1', line.strip()) for line in lines]
def handle_signature(self, sig, signode):
# type: (unicode, addnodes.desc_signature) -> Any
"""
Parse the signature *sig* into individual nodes and append them to
*signode*. If ValueError is raised, parsing is aborted and the whole
@ -65,6 +88,7 @@ class ObjectDescription(Directive):
raise ValueError
def add_target_and_index(self, name, sig, signode):
# type: (Any, unicode, addnodes.desc_signature) -> None
"""
Add cross-reference IDs and entries to self.indexnode, if applicable.
@ -73,6 +97,7 @@ class ObjectDescription(Directive):
return # do nothing by default
def before_content(self):
# type: () -> None
"""
Called before parsing content. Used to set information about the current
directive context on the build environment.
@ -80,6 +105,7 @@ class ObjectDescription(Directive):
pass
def after_content(self):
# type: () -> None
"""
Called after parsing content. Used to reset information about the
current directive context on the build environment.
@ -87,6 +113,7 @@ class ObjectDescription(Directive):
pass
def run(self):
# type: () -> List[nodes.Node]
"""
Main directive entry function, called by docutils upon encountering the
directive.
@ -108,7 +135,7 @@ class ObjectDescription(Directive):
self.domain, self.objtype = self.name.split(':', 1)
else:
self.domain, self.objtype = '', self.name
self.env = self.state.document.settings.env
self.env = self.state.document.settings.env # type: BuildEnvironment
self.indexnode = addnodes.index(entries=[])
node = addnodes.desc()
@ -118,7 +145,7 @@ class ObjectDescription(Directive):
node['objtype'] = node['desctype'] = self.objtype
node['noindex'] = noindex = ('noindex' in self.options)
self.names = []
self.names = [] # type: List[unicode]
signatures = self.get_signatures()
for i, sig in enumerate(signatures):
# add a signature node for each signature in the current unit
@ -155,6 +182,7 @@ class ObjectDescription(Directive):
self.after_content()
return [self.indexnode, node]
# backwards compatible old name
DescDirective = ObjectDescription
@ -168,6 +196,7 @@ class DefaultRole(Directive):
final_argument_whitespace = False
def run(self):
# type: () -> List[nodes.Node]
if not self.arguments:
if '' in roles._roles:
# restore the "default" default role
@ -196,9 +225,10 @@ class DefaultDomain(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
domain_name = self.arguments[0].lower()
# if domain_name not in env.domains:
@ -212,6 +242,7 @@ class DefaultDomain(Directive):
def setup(app):
# type: (Sphinx) -> None
directives.register_directive('default-role', DefaultRole)
directives.register_directive('default-domain', DefaultDomain)
directives.register_directive('describe', ObjectDescription)

View File

@ -11,17 +11,22 @@ import sys
import codecs
from difflib import unified_diff
from six import string_types
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.statemachine import ViewList
from six import string_types
from sphinx import addnodes
from sphinx.locale import _
from sphinx.util import parselinenos
from sphinx.util.nodes import set_source_info
if False:
# For type annotation
from typing import Any # NOQA
from sphinx.application import Sphinx # NOQA
class Highlight(Directive):
"""
@ -38,6 +43,7 @@ class Highlight(Directive):
}
def run(self):
# type: () -> List[nodes.Node]
if 'linenothreshold' in self.options:
try:
linenothreshold = int(self.options['linenothreshold'])
@ -50,6 +56,7 @@ class Highlight(Directive):
def dedent_lines(lines, dedent):
# type: (List[unicode], int) -> List[unicode]
if not dedent:
return lines
@ -64,6 +71,7 @@ def dedent_lines(lines, dedent):
def container_wrapper(directive, literal_node, caption):
# type: (Directive, nodes.Node, unicode) -> nodes.container
container_node = nodes.container('', literal_block=True,
classes=['literal-block-wrapper'])
parsed = nodes.Element()
@ -101,6 +109,7 @@ class CodeBlock(Directive):
}
def run(self):
# type: () -> List[nodes.Node]
code = u'\n'.join(self.content)
linespec = self.options.get('emphasize-lines')
@ -137,7 +146,7 @@ class CodeBlock(Directive):
literal = container_wrapper(self, literal, caption)
except ValueError as exc:
document = self.state.document
errmsg = _('Invalid caption: %s' % exc[0][0].astext())
errmsg = _('Invalid caption: %s' % exc[0][0].astext()) # type: ignore
return [document.reporter.warning(errmsg, line=self.lineno)]
# literal will be note_implicit_target that is linked from caption and numref.
@ -170,6 +179,8 @@ class LiteralInclude(Directive):
'lines': directives.unchanged_required,
'start-after': directives.unchanged_required,
'end-before': directives.unchanged_required,
'start-at': directives.unchanged_required,
'end-at': directives.unchanged_required,
'prepend': directives.unchanged_required,
'append': directives.unchanged_required,
'emphasize-lines': directives.unchanged_required,
@ -180,11 +191,12 @@ class LiteralInclude(Directive):
}
def read_with_encoding(self, filename, document, codec_info, encoding):
# type: (unicode, nodes.Node, Any, unicode) -> List
try:
with codecs.StreamReaderWriter(open(filename, 'rb'), codec_info[2],
codec_info[3], 'strict') as f:
lines = f.readlines()
lines = dedent_lines(lines, self.options.get('dedent'))
lines = dedent_lines(lines, self.options.get('dedent')) # type: ignore
return lines
except (IOError, OSError):
return [document.reporter.warning(
@ -197,6 +209,7 @@ class LiteralInclude(Directive):
(encoding, filename))]
def run(self):
# type: () -> List[nodes.Node]
document = self.state.document
if not document.settings.file_insertion_enabled:
return [document.reporter.warning('File insertion disabled',
@ -220,6 +233,16 @@ class LiteralInclude(Directive):
'Cannot use "lineno-match" and "append" or "prepend"',
line=self.lineno)]
if 'start-after' in self.options and 'start-at' in self.options:
return [document.reporter.warning(
'Cannot use both "start-after" and "start-at" options',
line=self.lineno)]
if 'end-before' in self.options and 'end-at' in self.options:
return [document.reporter.warning(
'Cannot use both "end-before" and "end-at" options',
line=self.lineno)]
encoding = self.options.get('encoding', env.config.source_encoding)
codec_info = codecs.lookup(encoding)
@ -292,17 +315,29 @@ class LiteralInclude(Directive):
else:
hl_lines = None
startafter = self.options.get('start-after')
endbefore = self.options.get('end-before')
if startafter is not None or endbefore is not None:
use = not startafter
start_str = self.options.get('start-after')
start_inclusive = False
if self.options.get('start-at') is not None:
start_str = self.options.get('start-at')
start_inclusive = True
end_str = self.options.get('end-before')
end_inclusive = False
if self.options.get('end-at') is not None:
end_str = self.options.get('end-at')
end_inclusive = True
if start_str is not None or end_str is not None:
use = not start_str
res = []
for line_number, line in enumerate(lines):
if not use and startafter and startafter in line:
if not use and start_str and start_str in line:
if 'lineno-match' in self.options:
linenostart += line_number + 1
use = True
elif use and endbefore and endbefore in line:
if start_inclusive:
res.append(line)
elif use and end_str and end_str in line:
if end_inclusive:
res.append(line)
break
elif use:
res.append(line)
@ -343,7 +378,7 @@ class LiteralInclude(Directive):
retnode = container_wrapper(self, retnode, caption)
except ValueError as exc:
document = self.state.document
errmsg = _('Invalid caption: %s' % exc[0][0].astext())
errmsg = _('Invalid caption: %s' % exc[0][0].astext()) # type: ignore
return [document.reporter.warning(errmsg, line=self.lineno)]
# retnode will be note_implicit_target that is linked from caption and numref.
@ -354,6 +389,7 @@ class LiteralInclude(Directive):
def setup(app):
# type: (Sphinx) -> None
directives.register_directive('highlight', Highlight)
directives.register_directive('highlightlang', Highlight) # old
directives.register_directive('code-block', CodeBlock)

View File

@ -8,6 +8,7 @@
"""
from six.moves import range
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
@ -21,8 +22,14 @@ from sphinx.util.nodes import explicit_title_re, set_source_info, \
process_index_entry
from sphinx.util.matching import patfilter
if False:
# For type annotation
from typing import Tuple # NOQA
from sphinx.application import Sphinx # NOQA
def int_or_nothing(argument):
# type: (unicode) -> int
if not argument:
return 999
return int(argument)
@ -46,20 +53,19 @@ class TocTree(Directive):
'includehidden': directives.flag,
'numbered': int_or_nothing,
'titlesonly': directives.flag,
'reversed': directives.flag,
}
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
suffixes = env.config.source_suffix
glob = 'glob' in self.options
caption = self.options.get('caption')
if caption:
self.options.setdefault('name', nodes.fully_normalize_name(caption))
ret = []
# (title, ref) pairs, where ref may be a document, or an external link,
# and title may be None if the document's title is to be used
entries = []
entries = [] # type: List[Tuple[unicode, unicode]]
includefiles = []
all_docnames = env.found_docs.copy()
# don't add the currently visited file in catch-all patterns
@ -109,11 +115,13 @@ class TocTree(Directive):
subnode = addnodes.toctree()
subnode['parent'] = env.docname
# entries contains all entries (self references, external links etc.)
if 'reversed' in self.options:
entries.reverse()
subnode['entries'] = entries
# includefiles only entries that are documents
subnode['includefiles'] = includefiles
subnode['maxdepth'] = self.options.get('maxdepth', -1)
subnode['caption'] = caption
subnode['caption'] = self.options.get('caption')
subnode['glob'] = glob
subnode['hidden'] = 'hidden' in self.options
subnode['includehidden'] = 'includehidden' in self.options
@ -136,9 +144,10 @@ class Author(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
if not env.config.show_authors:
return []
@ -168,20 +177,21 @@ class Index(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
arguments = self.arguments[0].split('\n')
env = self.state.document.settings.env
targetid = 'index-%s' % env.new_serialno('index')
targetnode = nodes.target('', '', ids=[targetid])
self.state.document.note_explicit_target(targetnode)
indexnode = addnodes.index()
indexnode['entries'] = ne = []
indexnode['entries'] = []
indexnode['inline'] = False
set_source_info(self, indexnode)
for entry in arguments:
ne.extend(process_index_entry(entry, targetid))
indexnode['entries'].extend(process_index_entry(entry, targetid))
return [indexnode, targetnode]
@ -193,9 +203,10 @@ class VersionChange(Directive):
required_arguments = 1
optional_arguments = 1
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
node = addnodes.versionmodified()
node.document = self.state.document
set_source_info(self, node)
@ -248,9 +259,10 @@ class TabularColumns(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
node = addnodes.tabular_col_spec()
node['spec'] = self.arguments[0]
set_source_info(self, node)
@ -265,9 +277,10 @@ class Centered(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
if not self.arguments:
return []
subnode = addnodes.centered()
@ -285,9 +298,10 @@ class Acks(Directive):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
node = addnodes.acks()
node.document = self.state.document
self.state.nested_parse(self.content, self.content_offset, node)
@ -311,6 +325,7 @@ class HList(Directive):
}
def run(self):
# type: () -> List[nodes.Node]
ncolumns = self.options.get('columns', 2)
node = nodes.paragraph()
node.document = self.state.document
@ -342,9 +357,10 @@ class Only(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
node = addnodes.only()
node.document = self.state.document
set_source_info(self, node)
@ -398,6 +414,7 @@ class Include(BaseInclude):
"""
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
if self.arguments[0].startswith('<') and \
self.arguments[0].endswith('>'):
@ -410,6 +427,7 @@ class Include(BaseInclude):
def setup(app):
# type: (Sphinx) -> None
directives.register_directive('toctree', TocTree)
directives.register_directive('sectionauthor', Author)
directives.register_directive('moduleauthor', Author)

View File

@ -17,6 +17,13 @@ from six import iteritems
from sphinx.errors import SphinxError
from sphinx.locale import _
if False:
# For type annotation
from typing import Any, Callable, Iterable, Tuple, Type, Union # NOQA
from docutils import nodes # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
class ObjType(object):
"""
@ -38,9 +45,10 @@ class ObjType(object):
}
def __init__(self, lname, *roles, **attrs):
self.lname = lname
self.roles = roles
self.attrs = self.known_attrs.copy()
# type: (unicode, Any, Any) -> None
self.lname = lname # type: unicode
self.roles = roles # type: Tuple
self.attrs = self.known_attrs.copy() # type: Dict
self.attrs.update(attrs)
@ -59,17 +67,19 @@ class Index(object):
domains using :meth:`~sphinx.application.Sphinx.add_index_to_domain()`.
"""
name = None
localname = None
shortname = None
name = None # type: unicode
localname = None # type: unicode
shortname = None # type: unicode
def __init__(self, domain):
# type: (Domain) -> None
if self.name is None or self.localname is None:
raise SphinxError('Index subclass %s has no valid name or localname'
% self.__class__.__name__)
self.domain = domain
def generate(self, docnames=None):
# type: (List[unicode]) -> Tuple[List[Tuple[unicode, List[List[Union[unicode, int]]]]], bool] # NOQA
"""Return entries for the index given by *name*. If *docnames* is
given, restrict to entries referring to these docnames.
@ -128,23 +138,26 @@ class Domain(object):
#: domain label: longer, more descriptive (used in messages)
label = ''
#: type (usually directive) name -> ObjType instance
object_types = {}
object_types = {} # type: Dict[unicode, Any]
#: directive name -> directive class
directives = {}
directives = {} # type: Dict[unicode, Any]
#: role name -> role callable
roles = {}
roles = {} # type: Dict[unicode, Callable]
#: a list of Index subclasses
indices = []
indices = [] # type: List[Type[Index]]
#: role name -> a warning message if reference is missing
dangling_warnings = {}
dangling_warnings = {} # type: Dict[unicode, unicode]
#: data value for a fresh environment
initial_data = {}
initial_data = {} # type: Dict
#: data value
data = None # type: Dict
#: data version, bump this when the format of `self.data` changes
data_version = 0
def __init__(self, env):
self.env = env
# type: (BuildEnvironment) -> None
self.env = env # type: BuildEnvironment
if self.name not in env.domaindata:
assert isinstance(self.initial_data, dict)
new_data = copy.deepcopy(self.initial_data)
@ -154,18 +167,19 @@ class Domain(object):
self.data = env.domaindata[self.name]
if self.data['version'] != self.data_version:
raise IOError('data of %r domain out of date' % self.label)
self._role_cache = {}
self._directive_cache = {}
self._role2type = {}
self._type2role = {}
self._role_cache = {} # type: Dict[unicode, Callable]
self._directive_cache = {} # type: Dict[unicode, Callable]
self._role2type = {} # type: Dict[unicode, List[unicode]]
self._type2role = {} # type: Dict[unicode, unicode]
for name, obj in iteritems(self.object_types):
for rolename in obj.roles:
self._role2type.setdefault(rolename, []).append(name)
self._type2role[name] = obj.roles[0] if obj.roles else ''
self.objtypes_for_role = self._role2type.get
self.role_for_objtype = self._type2role.get
self.objtypes_for_role = self._role2type.get # type: Callable[[unicode], List[unicode]] # NOQA
self.role_for_objtype = self._type2role.get # type: Callable[[unicode], unicode]
def role(self, name):
# type: (unicode) -> Callable
"""Return a role adapter function that always gives the registered
role its full name ('domain:name') as the first argument.
"""
@ -183,6 +197,7 @@ class Domain(object):
return role_adapter
def directive(self, name):
# type: (unicode) -> Callable
"""Return a directive adapter class that always gives the registered
directive its full name ('domain:name') as ``self.name``.
"""
@ -193,7 +208,7 @@ class Domain(object):
fullname = '%s:%s' % (self.name, name)
BaseDirective = self.directives[name]
class DirectiveAdapter(BaseDirective):
class DirectiveAdapter(BaseDirective): # type: ignore
def run(self):
self.name = fullname
return BaseDirective.run(self)
@ -203,10 +218,12 @@ class Domain(object):
# methods that should be overwritten
def clear_doc(self, docname):
# type: (unicode) -> None
"""Remove traces of a document in the domain-specific inventories."""
pass
def merge_domaindata(self, docnames, otherdata):
# type: (List[unicode], Dict) -> None
"""Merge in data regarding *docnames* from a different domaindata
inventory (coming from a subprocess in parallel builds).
"""
@ -215,11 +232,13 @@ class Domain(object):
self.__class__)
def process_doc(self, env, docname, document):
# type: (BuildEnvironment, unicode, nodes.Node) -> None
"""Process a document after it is read by the environment."""
pass
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
"""Resolve the pending_xref *node* with the given *typ* and *target*.
This method should return a new node, to replace the xref node,
@ -236,6 +255,7 @@ class Domain(object):
pass
def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, nodes.Node, nodes.Node) -> List[Tuple[unicode, nodes.Node]] # NOQA
"""Resolve the pending_xref *node* with the given *target*.
The reference comes from an "any" or similar role, which means that we
@ -252,6 +272,7 @@ class Domain(object):
raise NotImplementedError
def get_objects(self):
# type: () -> Iterable[Tuple[unicode, unicode, unicode, unicode, unicode, int]]
"""Return an iterable of "object descriptions", which are tuples with
five items:
@ -271,6 +292,7 @@ class Domain(object):
return []
def get_type_name(self, type, primary=False):
# type: (ObjType, bool) -> unicode
"""Return full name for given ObjType."""
if primary:
return type.lname

View File

@ -22,6 +22,13 @@ from sphinx.directives import ObjectDescription
from sphinx.util.nodes import make_refnode
from sphinx.util.docfields import Field, TypedField
if False:
# For type annotation
from typing import Any, Iterator, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
# RE to split at word boundaries
wsplit_re = re.compile(r'(\W+)')
@ -74,8 +81,9 @@ class CObject(ObjectDescription):
))
def _parse_type(self, node, ctype):
# type: (nodes.Node, unicode) -> None
# add cross-ref nodes for all words
for part in [_f for _f in wsplit_re.split(ctype) if _f]:
for part in [_f for _f in wsplit_re.split(ctype) if _f]: # type: ignore
tnode = nodes.Text(part, part)
if part[0] in string.ascii_letters+'_' and \
part not in self.stopwords:
@ -88,11 +96,12 @@ class CObject(ObjectDescription):
node += tnode
def _parse_arglist(self, arglist):
# type: (unicode) -> Iterator[unicode]
while True:
m = c_funcptr_arg_sig_re.match(arglist)
m = c_funcptr_arg_sig_re.match(arglist) # type: ignore
if m:
yield m.group()
arglist = c_funcptr_arg_sig_re.sub('', arglist)
arglist = c_funcptr_arg_sig_re.sub('', arglist) # type: ignore
if ',' in arglist:
_, arglist = arglist.split(',', 1)
else:
@ -106,11 +115,12 @@ class CObject(ObjectDescription):
break
def handle_signature(self, sig, signode):
# type: (unicode, addnodes.desc_signature) -> unicode
"""Transform a C signature into RST nodes."""
# first try the function pointer signature regex, it's more specific
m = c_funcptr_sig_re.match(sig)
m = c_funcptr_sig_re.match(sig) # type: ignore
if m is None:
m = c_sig_re.match(sig)
m = c_sig_re.match(sig) # type: ignore
if m is None:
raise ValueError('no match')
rettype, name, arglist, const = m.groups()
@ -151,7 +161,7 @@ class CObject(ObjectDescription):
arg = arg.strip()
param = addnodes.desc_parameter('', '', noemph=True)
try:
m = c_funcptr_arg_sig_re.match(arg)
m = c_funcptr_arg_sig_re.match(arg) # type: ignore
if m:
self._parse_type(param, m.group(1) + '(')
param += nodes.emphasis(m.group(2), m.group(2))
@ -173,6 +183,7 @@ class CObject(ObjectDescription):
return fullname
def get_index_text(self, name):
# type: (unicode) -> unicode
if self.objtype == 'function':
return _('%s (C function)') % name
elif self.objtype == 'member':
@ -187,6 +198,7 @@ class CObject(ObjectDescription):
return ''
def add_target_and_index(self, name, sig, signode):
# type: (unicode, unicode, addnodes.desc_signature) -> None
# for C API items we add a prefix since names are usually not qualified
# by a module name and so easily clash with e.g. section titles
targetname = 'c.' + name
@ -209,6 +221,7 @@ class CObject(ObjectDescription):
targetname, '', None))
def before_content(self):
# type: () -> None
self.typename_set = False
if self.name == 'c:type':
if self.names:
@ -216,12 +229,14 @@ class CObject(ObjectDescription):
self.typename_set = True
def after_content(self):
# type: () -> None
if self.typename_set:
self.env.ref_context.pop('c:type', None)
class CXRefRole(XRefRole):
def process_link(self, env, refnode, has_explicit_title, title, target):
# type: (BuildEnvironment, nodes.Node, bool, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
if not has_explicit_title:
target = target.lstrip('~') # only has a meaning for the title
# if the first character is a tilde, don't display the module/class
@ -262,14 +277,16 @@ class CDomain(Domain):
}
initial_data = {
'objects': {}, # fullname -> docname, objtype
}
} # type: Dict[unicode, Dict[unicode, Tuple[unicode, Any]]]
def clear_doc(self, docname):
# type: (unicode) -> None
for fullname, (fn, _l) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
def merge_domaindata(self, docnames, otherdata):
# type: (List[unicode], Dict) -> None
# XXX check duplicates
for fullname, (fn, objtype) in otherdata['objects'].items():
if fn in docnames:
@ -277,6 +294,7 @@ class CDomain(Domain):
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
# strip pointer asterisk
target = target.rstrip(' *')
# becase TypedField can generate xrefs
@ -290,6 +308,7 @@ class CDomain(Domain):
def resolve_any_xref(self, env, fromdocname, builder, target,
node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, nodes.Node, nodes.Node) -> List[Tuple[unicode, nodes.Node]] # NOQA
# strip pointer asterisk
target = target.rstrip(' *')
if target not in self.data['objects']:
@ -300,9 +319,11 @@ class CDomain(Domain):
contnode, target))]
def get_objects(self):
# type: () -> Iterator[Tuple[unicode, unicode, unicode, unicode, unicode, int]]
for refname, (docname, type) in list(self.data['objects'].items()):
yield (refname, refname, type, docname, 'c.' + refname, 1)
def setup(app):
# type: (Sphinx) -> None
app.add_domain(CDomain)

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,14 @@ from sphinx.domains.python import _pseudo_parse_arglist
from sphinx.util.nodes import make_refnode
from sphinx.util.docfields import Field, GroupedField, TypedField
if False:
# For type annotation
from typing import Iterator, Tuple # NOQA
from docutils import nodes # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
class JSObject(ObjectDescription):
"""
@ -28,9 +36,10 @@ class JSObject(ObjectDescription):
has_arguments = False
#: what is displayed right before the documentation entry
display_prefix = None
display_prefix = None # type: unicode
def handle_signature(self, sig, signode):
# type: (unicode, addnodes.desc_signature) -> Tuple[unicode, unicode]
sig = sig.strip()
if '(' in sig and sig[-1:] == ')':
prefix, arglist = sig.split('(', 1)
@ -76,6 +85,7 @@ class JSObject(ObjectDescription):
return fullname, nameprefix
def add_target_and_index(self, name_obj, sig, signode):
# type: (Tuple[unicode, unicode], unicode, addnodes.desc_signature) -> None
objectname = self.options.get(
'object', self.env.ref_context.get('js:object'))
fullname = name_obj[0]
@ -100,6 +110,7 @@ class JSObject(ObjectDescription):
'', None))
def get_index_text(self, objectname, name_obj):
# type: (unicode, Tuple[unicode, unicode]) -> unicode
name, obj = name_obj
if self.objtype == 'function':
if not obj:
@ -139,6 +150,7 @@ class JSConstructor(JSCallable):
class JSXRefRole(XRefRole):
def process_link(self, env, refnode, has_explicit_title, title, target):
# type: (BuildEnvironment, nodes.Node, bool, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
# basically what sphinx.domains.python.PyXRefRole does
refnode['js:object'] = env.ref_context.get('js:object')
if not has_explicit_title:
@ -180,20 +192,23 @@ class JavaScriptDomain(Domain):
}
initial_data = {
'objects': {}, # fullname -> docname, objtype
}
} # type: Dict[unicode, Dict[unicode, Tuple[unicode, unicode]]]
def clear_doc(self, docname):
# type: (unicode) -> None
for fullname, (fn, _l) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
def merge_domaindata(self, docnames, otherdata):
# type: (List[unicode], Dict) -> None
# XXX check duplicates
for fullname, (fn, objtype) in otherdata['objects'].items():
if fn in docnames:
self.data['objects'][fullname] = (fn, objtype)
def find_obj(self, env, obj, name, typ, searchorder=0):
# type: (BuildEnvironment, unicode, unicode, unicode, int) -> Tuple[unicode, Tuple[unicode, unicode]] # NOQA
if name[-2:] == '()':
name = name[:-2]
objects = self.data['objects']
@ -212,6 +227,7 @@ class JavaScriptDomain(Domain):
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
objectname = node.get('js:object')
searchorder = node.hasattr('refspecific') and 1 or 0
name, obj = self.find_obj(env, objectname, target, typ, searchorder)
@ -222,6 +238,7 @@ class JavaScriptDomain(Domain):
def resolve_any_xref(self, env, fromdocname, builder, target, node,
contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, nodes.Node, nodes.Node) -> List[Tuple[unicode, nodes.Node]] # NOQA
objectname = node.get('js:object')
name, obj = self.find_obj(env, objectname, target, None, 1)
if not obj:
@ -231,10 +248,12 @@ class JavaScriptDomain(Domain):
name.replace('$', '_S_'), contnode, name))]
def get_objects(self):
# type: () -> Iterator[Tuple[unicode, unicode, unicode, unicode, unicode, int]]
for refname, (docname, type) in list(self.data['objects'].items()):
yield refname, refname, type, docname, \
refname.replace('$', '_S_'), 1
def setup(app):
# type: (Sphinx) -> None
app.add_domain(JavaScriptDomain)

View File

@ -12,6 +12,7 @@
import re
from six import iteritems
from docutils import nodes
from docutils.parsers.rst import directives
@ -24,6 +25,13 @@ from sphinx.util.nodes import make_refnode
from sphinx.util.compat import Directive
from sphinx.util.docfields import Field, GroupedField, TypedField
if False:
# For type annotation
from typing import Any, Iterator, Tuple, Union # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
# REs for Python signatures
py_sig_re = re.compile(
@ -36,6 +44,7 @@ py_sig_re = re.compile(
def _pseudo_parse_arglist(signode, arglist):
# type: (addnodes.desc_signature, unicode) -> None
""""Parse" a list of arguments separated by commas.
Arguments can have "optional" annotations given by enclosing them in
@ -87,7 +96,8 @@ def _pseudo_parse_arglist(signode, arglist):
class PyXrefMixin(object):
def make_xref(self, rolename, domain, target, innernode=nodes.emphasis,
contnode=None):
result = super(PyXrefMixin, self).make_xref(rolename, domain, target,
# type: (unicode, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node
result = super(PyXrefMixin, self).make_xref(rolename, domain, target, # type: ignore
innernode, contnode)
result['refspecific'] = True
if target.startswith(('.', '~')):
@ -103,6 +113,7 @@ class PyXrefMixin(object):
def make_xrefs(self, rolename, domain, target, innernode=nodes.emphasis,
contnode=None):
# type: (unicode, unicode, unicode, nodes.Node, nodes.Node) -> List[nodes.Node]
delims = '(\s*[\[\]\(\),](?:\s*or\s)?\s*|\s+or\s+)'
delims_re = re.compile(delims)
sub_targets = re.split(delims, target)
@ -114,7 +125,7 @@ class PyXrefMixin(object):
if split_contnode:
contnode = nodes.Text(sub_target)
if delims_re.match(sub_target):
if delims_re.match(sub_target): # type: ignore
results.append(contnode or innernode(sub_target, sub_target))
else:
results.append(self.make_xref(rolename, domain, sub_target,
@ -165,18 +176,21 @@ class PyObject(ObjectDescription):
]
def get_signature_prefix(self, sig):
# type: (unicode) -> unicode
"""May return a prefix to put before the object name in the
signature.
"""
return ''
def needs_arglist(self):
# type: () -> bool
"""May return true if an empty argument list is to be generated even if
the document contains none.
"""
return False
def handle_signature(self, sig, signode):
def handle_signature(self, sig, signode): # type: ignore
# type: (unicode, addnodes.desc_signature) -> Tuple[unicode, unicode]
"""Transform a Python signature into RST nodes.
Return (fully qualified name of the thing, classname if any).
@ -185,7 +199,7 @@ class PyObject(ObjectDescription):
* it is stripped from the displayed name if present
* it is added to the full name (return value) if not present
"""
m = py_sig_re.match(sig)
m = py_sig_re.match(sig) # type: ignore
if m is None:
raise ValueError
name_prefix, name, arglist, retann = m.groups()
@ -256,10 +270,12 @@ class PyObject(ObjectDescription):
return fullname, name_prefix
def get_index_text(self, modname, name):
# type: (unicode, unicode) -> unicode
"""Return the text for the index entry of the object."""
raise NotImplementedError('must be implemented in subclasses')
def add_target_and_index(self, name_cls, sig, signode):
# type: (unicode, unicode, addnodes.desc_signature) -> None
modname = self.options.get(
'module', self.env.ref_context.get('py:module'))
fullname = (modname and modname + '.' or '') + name_cls[0]
@ -285,10 +301,12 @@ class PyObject(ObjectDescription):
fullname, '', None))
def before_content(self):
# type: () -> None
# needed for automatic qualification of members (reset in subclasses)
self.clsname_set = False
def after_content(self):
# type: () -> None
if self.clsname_set:
self.env.ref_context.pop('py:class', None)
@ -299,9 +317,11 @@ class PyModulelevel(PyObject):
"""
def needs_arglist(self):
# type: () -> bool
return self.objtype == 'function'
def get_index_text(self, modname, name_cls):
# type: (unicode, unicode) -> unicode
if self.objtype == 'function':
if not modname:
return _('%s() (built-in function)') % name_cls[0]
@ -320,9 +340,11 @@ class PyClasslike(PyObject):
"""
def get_signature_prefix(self, sig):
# type: (unicode) -> unicode
return self.objtype + ' '
def get_index_text(self, modname, name_cls):
# type: (unicode, unicode) -> unicode
if self.objtype == 'class':
if not modname:
return _('%s (built-in class)') % name_cls[0]
@ -333,6 +355,7 @@ class PyClasslike(PyObject):
return ''
def before_content(self):
# type: () -> None
PyObject.before_content(self)
if self.names:
self.env.ref_context['py:class'] = self.names[0][0]
@ -345,9 +368,11 @@ class PyClassmember(PyObject):
"""
def needs_arglist(self):
# type: () -> bool
return self.objtype.endswith('method')
def get_signature_prefix(self, sig):
# type: (unicode) -> unicode
if self.objtype == 'staticmethod':
return 'static '
elif self.objtype == 'classmethod':
@ -355,6 +380,7 @@ class PyClassmember(PyObject):
return ''
def get_index_text(self, modname, name_cls):
# type: (unicode, unicode) -> unicode
name, cls = name_cls
add_modules = self.env.config.add_module_names
if self.objtype == 'method':
@ -411,6 +437,7 @@ class PyClassmember(PyObject):
return ''
def before_content(self):
# type: () -> None
PyObject.before_content(self)
lastname = self.names and self.names[-1][1]
if lastname and not self.env.ref_context.get('py:class'):
@ -423,11 +450,13 @@ class PyDecoratorMixin(object):
Mixin for decorator directives.
"""
def handle_signature(self, sig, signode):
ret = super(PyDecoratorMixin, self).handle_signature(sig, signode)
# type: (unicode, addnodes.desc_signature) -> Tuple[unicode, unicode]
ret = super(PyDecoratorMixin, self).handle_signature(sig, signode) # type: ignore
signode.insert(0, addnodes.desc_addname('@', '@'))
return ret
def needs_arglist(self):
# type: () -> bool
return False
@ -436,6 +465,7 @@ class PyDecoratorFunction(PyDecoratorMixin, PyModulelevel):
Directive to mark functions meant to be used as decorators.
"""
def run(self):
# type: () -> List[nodes.Node]
# a decorator function is a function after all
self.name = 'py:function'
return PyModulelevel.run(self)
@ -446,6 +476,7 @@ class PyDecoratorMethod(PyDecoratorMixin, PyClassmember):
Directive to mark methods meant to be used as decorators.
"""
def run(self):
# type: () -> List[nodes.Node]
self.name = 'py:method'
return PyClassmember.run(self)
@ -467,6 +498,7 @@ class PyModule(Directive):
}
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
modname = self.arguments[0].strip()
noindex = 'noindex' in self.options
@ -502,9 +534,10 @@ class PyCurrentModule(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
modname = self.arguments[0].strip()
if modname == 'None':
@ -516,6 +549,7 @@ class PyCurrentModule(Directive):
class PyXRefRole(XRefRole):
def process_link(self, env, refnode, has_explicit_title, title, target):
# type: (BuildEnvironment, nodes.Node, bool, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
refnode['py:module'] = env.ref_context.get('py:module')
refnode['py:class'] = env.ref_context.get('py:class')
if not has_explicit_title:
@ -546,9 +580,11 @@ class PythonModuleIndex(Index):
shortname = l_('modules')
def generate(self, docnames=None):
content = {}
# type: (List[unicode]) -> Tuple[List[Tuple[unicode, List[List[Union[unicode, int]]]]], bool] # NOQA
content = {} # type: Dict[unicode, List]
# list of prefixes to ignore
ignores = self.domain.env.config['modindex_common_prefix']
ignores = None # type: List[unicode]
ignores = self.domain.env.config['modindex_common_prefix'] # type: ignore
ignores = sorted(ignores, key=len, reverse=True)
# list of all modules, sorted by module name
modules = sorted(iteritems(self.domain.data['modules']),
@ -601,9 +637,9 @@ class PythonModuleIndex(Index):
collapse = len(modules) - num_toplevels < num_toplevels
# sort by first letter
content = sorted(iteritems(content))
sorted_content = sorted(iteritems(content))
return content, collapse
return sorted_content, collapse
class PythonDomain(Domain):
@ -620,7 +656,7 @@ class PythonDomain(Domain):
'staticmethod': ObjType(l_('static method'), 'meth', 'obj'),
'attribute': ObjType(l_('attribute'), 'attr', 'obj'),
'module': ObjType(l_('module'), 'mod', 'obj'),
}
} # type: Dict[unicode, ObjType]
directives = {
'function': PyModulelevel,
@ -650,12 +686,13 @@ class PythonDomain(Domain):
initial_data = {
'objects': {}, # fullname -> docname, objtype
'modules': {}, # modname -> docname, synopsis, platform, deprecated
}
} # type: Dict[unicode, Dict[unicode, Tuple[Any]]]
indices = [
PythonModuleIndex,
]
def clear_doc(self, docname):
# type: (unicode) -> None
for fullname, (fn, _l) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
@ -664,6 +701,7 @@ class PythonDomain(Domain):
del self.data['modules'][modname]
def merge_domaindata(self, docnames, otherdata):
# type: (List[unicode], Dict) -> None
# XXX check duplicates?
for fullname, (fn, objtype) in otherdata['objects'].items():
if fn in docnames:
@ -673,6 +711,7 @@ class PythonDomain(Domain):
self.data['modules'][modname] = data
def find_obj(self, env, modname, classname, name, type, searchmode=0):
# type: (BuildEnvironment, unicode, unicode, unicode, unicode, int) -> List[Tuple[unicode, Any]] # NOQA
"""Find a Python object for "name", perhaps using the given module
and/or classname. Returns a list of (name, object entry) tuples.
"""
@ -684,7 +723,7 @@ class PythonDomain(Domain):
return []
objects = self.data['objects']
matches = []
matches = [] # type: List[Tuple[unicode, Any]]
newname = None
if searchmode == 1:
@ -737,6 +776,7 @@ class PythonDomain(Domain):
def resolve_xref(self, env, fromdocname, builder,
type, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
modname = node.get('py:module')
clsname = node.get('py:class')
searchmode = node.hasattr('refspecific') and 1 or 0
@ -760,9 +800,10 @@ class PythonDomain(Domain):
def resolve_any_xref(self, env, fromdocname, builder, target,
node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, nodes.Node, nodes.Node) -> List[Tuple[unicode, nodes.Node]] # NOQA
modname = node.get('py:module')
clsname = node.get('py:class')
results = []
results = [] # type: List[Tuple[unicode, nodes.Node]]
# always search in "refspecific" mode with the :any: role
matches = self.find_obj(env, modname, clsname, target, None, 1)
@ -778,6 +819,7 @@ class PythonDomain(Domain):
return results
def _make_module_refnode(self, builder, fromdocname, name, contnode):
# type: (Builder, unicode, unicode, nodes.Node) -> nodes.Node
# get additional info for modules
docname, synopsis, platform, deprecated = self.data['modules'][name]
title = name
@ -791,6 +833,7 @@ class PythonDomain(Domain):
'module-' + name, contnode, title)
def get_objects(self):
# type: () -> Iterator[Tuple[unicode, unicode, unicode, unicode, unicode, int]]
for modname, info in iteritems(self.data['modules']):
yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
for refname, (docname, type) in iteritems(self.data['objects']):
@ -799,4 +842,5 @@ class PythonDomain(Domain):
def setup(app):
# type: (Sphinx) -> None
app.add_domain(PythonDomain)

View File

@ -20,6 +20,14 @@ from sphinx.directives import ObjectDescription
from sphinx.roles import XRefRole
from sphinx.util.nodes import make_refnode
if False:
# For type annotation
from typing import Iterator, Tuple # NOQA
from docutils import nodes # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
dir_sig_re = re.compile(r'\.\. (.+?)::(.*)$')
@ -30,6 +38,7 @@ class ReSTMarkup(ObjectDescription):
"""
def add_target_and_index(self, name, sig, signode):
# type: (unicode, unicode, addnodes.desc_signature) -> None
targetname = self.objtype + '-' + name
if targetname not in self.state.document.ids:
signode['names'].append(targetname)
@ -51,6 +60,7 @@ class ReSTMarkup(ObjectDescription):
targetname, '', None))
def get_index_text(self, objectname, name):
# type: (unicode, unicode) -> unicode
if self.objtype == 'directive':
return _('%s (directive)') % name
elif self.objtype == 'role':
@ -59,6 +69,7 @@ class ReSTMarkup(ObjectDescription):
def parse_directive(d):
# type: (unicode) -> Tuple[unicode, unicode]
"""Parse a directive signature.
Returns (directive, arguments) string tuple. If no arguments are given,
@ -68,7 +79,7 @@ def parse_directive(d):
if not dir.startswith('.'):
# Assume it is a directive without syntax
return (dir, '')
m = dir_sig_re.match(dir)
m = dir_sig_re.match(dir) # type: ignore
if not m:
return (dir, '')
parsed_dir, parsed_args = m.groups()
@ -80,6 +91,7 @@ class ReSTDirective(ReSTMarkup):
Description of a reST directive.
"""
def handle_signature(self, sig, signode):
# type: (unicode, addnodes.desc_signature) -> unicode
name, args = parse_directive(sig)
desc_name = '.. %s::' % name
signode += addnodes.desc_name(desc_name, desc_name)
@ -93,6 +105,7 @@ class ReSTRole(ReSTMarkup):
Description of a reST role.
"""
def handle_signature(self, sig, signode):
# type: (unicode, addnodes.desc_signature) -> unicode
signode += addnodes.desc_name(':%s:' % sig, ':%s:' % sig)
return sig
@ -116,14 +129,16 @@ class ReSTDomain(Domain):
}
initial_data = {
'objects': {}, # fullname -> docname, objtype
}
} # type: Dict[unicode, Dict[unicode, Tuple[unicode, ObjType]]]
def clear_doc(self, docname):
# type: (unicode) -> None
for (typ, name), doc in list(self.data['objects'].items()):
if doc == docname:
del self.data['objects'][typ, name]
def merge_domaindata(self, docnames, otherdata):
# type: (List[unicode], Dict) -> None
# XXX check duplicates
for (typ, name), doc in otherdata['objects'].items():
if doc in docnames:
@ -131,6 +146,7 @@ class ReSTDomain(Domain):
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
objects = self.data['objects']
objtypes = self.objtypes_for_role(typ)
for objtype in objtypes:
@ -142,6 +158,7 @@ class ReSTDomain(Domain):
def resolve_any_xref(self, env, fromdocname, builder, target,
node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, nodes.Node, nodes.Node) -> List[nodes.Node] # NOQA
objects = self.data['objects']
results = []
for objtype in self.object_types:
@ -154,9 +171,11 @@ class ReSTDomain(Domain):
return results
def get_objects(self):
# type: () -> Iterator[Tuple[unicode, unicode, unicode, unicode, unicode, int]]
for (typ, name), docname in iteritems(self.data['objects']):
yield name, name, typ, docname, typ + '-' + name, 1
def setup(app):
# type: (Sphinx) -> None
app.add_domain(ReSTDomain)

View File

@ -12,7 +12,8 @@
import re
import unicodedata
from six import iteritems
from six import PY3, iteritems
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
@ -26,6 +27,21 @@ from sphinx.util import ws_re
from sphinx.util.nodes import clean_astext, make_refnode
from sphinx.util.compat import Directive
if False:
# For type annotation
from typing import Any, Callable, Dict, Iterator, List, Tuple, Type, Union # NOQA
from docutils.parsers.rst.states import Inliner # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.util.typing import Role # NOQA
if PY3:
unicode = str
RoleFunction = Callable[[unicode, unicode, unicode, int, Inliner, Dict, List[unicode]],
Tuple[List[nodes.Node], List[nodes.Node]]]
# RE for option descriptions
option_desc_re = re.compile(r'((?:/|--|-|\+)?[-\.?@#_a-zA-Z0-9]+)(=?\s*.*)')
@ -38,9 +54,10 @@ class GenericObject(ObjectDescription):
A generic x-ref directive registered with Sphinx.add_object_type().
"""
indextemplate = ''
parse_node = None
parse_node = None # type: Callable[[GenericObject, BuildEnvironment, unicode, addnodes.desc_signature], unicode] # NOQA
def handle_signature(self, sig, signode):
# type: (unicode, addnodes.desc_signature) -> unicode
if self.parse_node:
name = self.parse_node(self.env, sig, signode)
else:
@ -51,6 +68,7 @@ class GenericObject(ObjectDescription):
return name
def add_target_and_index(self, name, sig, signode):
# type: (unicode, unicode, addnodes.desc_signature) -> None
targetname = '%s-%s' % (self.objtype, name)
signode['ids'].append(targetname)
self.state.document.note_explicit_target(signode)
@ -78,6 +96,7 @@ class EnvVarXRefRole(XRefRole):
"""
def result_nodes(self, document, env, node, is_ref):
# type: (nodes.Node, BuildEnvironment, nodes.Node, bool) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
if not is_ref:
return [node], []
varname = node['reftarget']
@ -102,9 +121,10 @@ class Target(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
# normalize whitespace in fullname like XRefRole does
fullname = ws_re.sub(' ', self.arguments[0].strip())
@ -136,12 +156,13 @@ class Cmdoption(ObjectDescription):
"""
def handle_signature(self, sig, signode):
# type: (unicode, addnodes.desc_signature) -> unicode
"""Transform an option description into RST nodes."""
count = 0
firstname = ''
for potential_option in sig.split(', '):
potential_option = potential_option.strip()
m = option_desc_re.match(potential_option)
m = option_desc_re.match(potential_option) # type: ignore
if not m:
self.env.warn(
self.env.docname,
@ -166,6 +187,7 @@ class Cmdoption(ObjectDescription):
return firstname
def add_target_and_index(self, firstname, sig, signode):
# type: (unicode, unicode, addnodes.desc_signature) -> None
currprogram = self.env.ref_context.get('std:program')
for optname in signode.get('allnames', []):
targetname = optname.replace('/', '-')
@ -174,16 +196,18 @@ class Cmdoption(ObjectDescription):
if currprogram:
targetname = '-' + currprogram + targetname
targetname = 'cmdoption' + targetname
signode['ids'].append(targetname)
self.state.document.note_explicit_target(signode)
signode['names'].append(targetname)
self.state.document.note_explicit_target(signode)
for optname in signode.get('allnames', []):
self.env.domaindata['std']['progoptions'][currprogram, optname] = \
self.env.docname, targetname
self.env.docname, signode['ids'][0]
# create only one index entry for the whole option
if optname == firstname:
self.indexnode['entries'].append(
('pair', _('%scommand line option; %s') %
((currprogram and currprogram + ' ' or ''), sig),
targetname, '', None))
signode['ids'][0], '', None))
class Program(Directive):
@ -195,9 +219,10 @@ class Program(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
program = ws_re.sub('-', self.arguments[0].strip())
if program == 'None':
@ -209,17 +234,20 @@ class Program(Directive):
class OptionXRefRole(XRefRole):
def process_link(self, env, refnode, has_explicit_title, title, target):
# type: (BuildEnvironment, nodes.Node, bool, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
refnode['std:program'] = env.ref_context.get('std:program')
return title, target
def split_term_classifiers(line):
# type: (unicode) -> List[Union[unicode, None]]
# split line into a term and classifiers. if no classifier, None is used..
parts = re.split(' +: +', line) + [None]
return parts
def make_glossary_term(env, textnodes, index_key, source, lineno, new_id=None):
# type: (BuildEnvironment, List[nodes.Node], unicode, unicode, int, unicode) -> nodes.term
# get a text-only representation of the term and register it
# as a cross-reference target
term = nodes.term('', '', *textnodes)
@ -263,6 +291,7 @@ class Glossary(Directive):
}
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
node = addnodes.glossary()
node.document = self.state.document
@ -273,7 +302,7 @@ class Glossary(Directive):
# be* a definition list.
# first, collect single entries
entries = []
entries = [] # type: List[Tuple[List[Tuple[unicode, unicode, int]], ViewList]]
in_definition = True
was_empty = True
messages = []
@ -327,7 +356,7 @@ class Glossary(Directive):
for terms, definition in entries:
termtexts = []
termnodes = []
system_messages = []
system_messages = [] # type: List[unicode]
for line, source, lineno in terms:
parts = split_term_classifiers(line)
# parse the term with inline markup
@ -363,9 +392,10 @@ class Glossary(Directive):
def token_xrefs(text):
# type: (unicode) -> List[nodes.Node]
retnodes = []
pos = 0
for m in token_re.finditer(text):
for m in token_re.finditer(text): # type: ignore
if m.start() > pos:
txt = text[pos:m.start()]
retnodes.append(nodes.Text(txt, txt))
@ -388,13 +418,14 @@ class ProductionList(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
objects = env.domaindata['std']['objects']
node = addnodes.productionlist()
messages = []
messages = [] # type: List[nodes.Node]
i = 0
for rule in self.arguments[0].split('\n'):
@ -435,7 +466,7 @@ class StandardDomain(Domain):
searchprio=-1),
'envvar': ObjType(l_('environment variable'), 'envvar'),
'cmdoption': ObjType(l_('program option'), 'option'),
}
} # type: Dict[unicode, ObjType]
directives = {
'program': Program,
@ -444,7 +475,7 @@ class StandardDomain(Domain):
'envvar': EnvVar,
'glossary': Glossary,
'productionlist': ProductionList,
}
} # type: Dict[unicode, Type[Directive]]
roles = {
'option': OptionXRefRole(warn_dangling=True),
'envvar': EnvVarXRefRole(),
@ -461,7 +492,7 @@ class StandardDomain(Domain):
warn_dangling=True),
# links to labels, without a different title
'keyword': XRefRole(warn_dangling=True),
}
} # type: Dict[unicode, Union[RoleFunction, XRefRole]]
initial_data = {
'progoptions': {}, # (program, name) -> docname, labelid
@ -493,9 +524,10 @@ class StandardDomain(Domain):
nodes.figure: ('figure', None),
nodes.table: ('table', None),
nodes.container: ('code-block', None),
}
} # type: Dict[nodes.Node, Tuple[unicode, Callable]]
def clear_doc(self, docname):
# type: (unicode) -> None
for key, (fn, _l) in list(self.data['progoptions'].items()):
if fn == docname:
del self.data['progoptions'][key]
@ -513,6 +545,7 @@ class StandardDomain(Domain):
del self.data['anonlabels'][key]
def merge_domaindata(self, docnames, otherdata):
# type: (List[unicode], Dict) -> None
# XXX duplicates?
for key, data in otherdata['progoptions'].items():
if data[0] in docnames:
@ -531,10 +564,12 @@ class StandardDomain(Domain):
self.data['anonlabels'][key] = data
def process_doc(self, env, docname, document):
# type: (BuildEnvironment, unicode, nodes.Node) -> None
self.note_citations(env, docname, document)
self.note_labels(env, docname, document)
def note_citations(self, env, docname, document):
# type: (BuildEnvironment, unicode, nodes.Node) -> None
for node in document.traverse(nodes.citation):
label = node[0].astext()
if label in self.data['citations']:
@ -544,6 +579,7 @@ class StandardDomain(Domain):
self.data['citations'][label] = (docname, node['ids'][0])
def note_labels(self, env, docname, document):
# type: (BuildEnvironment, unicode, nodes.Node) -> None
labels, anonlabels = self.data['labels'], self.data['anonlabels']
for name, explicit in iteritems(document.nametypes):
if not explicit:
@ -583,6 +619,7 @@ class StandardDomain(Domain):
def build_reference_node(self, fromdocname, builder, docname, labelid,
sectname, rolename, **options):
# type: (unicode, Builder, unicode, unicode, unicode, unicode, Any) -> nodes.Node
nodeclass = options.pop('nodeclass', nodes.reference)
newnode = nodeclass('', '', internal=True, **options)
innernode = nodes.inline(sectname, sectname)
@ -606,6 +643,7 @@ class StandardDomain(Domain):
return newnode
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
if typ == 'ref':
resolver = self._resolve_ref_xref
elif typ == 'numref':
@ -622,6 +660,7 @@ class StandardDomain(Domain):
return resolver(env, fromdocname, builder, typ, target, node, contnode)
def _resolve_ref_xref(self, env, fromdocname, builder, typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
if node['refexplicit']:
# reference to anonymous label; the reference uses
# the supplied link caption
@ -639,6 +678,7 @@ class StandardDomain(Domain):
docname, labelid, sectname, 'ref')
def _resolve_numref_xref(self, env, fromdocname, builder, typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
if target in self.data['labels']:
docname, labelid, figname = self.data['labels'].get(target, ('', '', ''))
else:
@ -698,6 +738,7 @@ class StandardDomain(Domain):
title=title)
def _resolve_keyword_xref(self, env, fromdocname, builder, typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
# keywords are oddballs: they are referenced by named labels
docname, labelid, _ = self.data['labels'].get(target, ('', '', ''))
if not docname:
@ -706,13 +747,14 @@ class StandardDomain(Domain):
labelid, contnode)
def _resolve_option_xref(self, env, fromdocname, builder, typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
progname = node.get('std:program')
target = target.strip()
docname, labelid = self.data['progoptions'].get((progname, target), ('', ''))
if not docname:
commands = []
while ws_re.search(target):
subcommand, target = ws_re.split(target, 1)
while ws_re.search(target): # type: ignore
subcommand, target = ws_re.split(target, 1) # type: ignore
commands.append(subcommand)
progname = "-".join(commands)
@ -727,6 +769,7 @@ class StandardDomain(Domain):
labelid, contnode)
def _resolve_citation_xref(self, env, fromdocname, builder, typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
from sphinx.environment import NoUri
docname, labelid = self.data['citations'].get(target, ('', ''))
@ -749,6 +792,7 @@ class StandardDomain(Domain):
raise
def _resolve_obj_xref(self, env, fromdocname, builder, typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
objtypes = self.objtypes_for_role(typ) or []
for objtype in objtypes:
if (objtype, target) in self.data['objects']:
@ -762,7 +806,8 @@ class StandardDomain(Domain):
labelid, contnode)
def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode):
results = []
# type: (BuildEnvironment, unicode, Builder, unicode, nodes.Node, nodes.Node) -> List[Tuple[unicode, nodes.Node]] # NOQA
results = [] # type: List[Tuple[unicode, nodes.Node]]
ltarget = target.lower() # :ref: lowercases its target automatically
for role in ('ref', 'option'): # do not try "keyword"
res = self.resolve_xref(env, fromdocname, builder, role,
@ -783,6 +828,7 @@ class StandardDomain(Domain):
return results
def get_objects(self):
# type: () -> Iterator[Tuple[unicode, unicode, unicode, unicode, unicode, int]]
# handle the special 'doc' reference here
for doc in self.env.all_docs:
yield (doc, clean_astext(self.env.titles[doc]), 'doc', doc, '', -1)
@ -800,13 +846,16 @@ class StandardDomain(Domain):
yield (name, name, 'label', info[0], info[1], -1)
def get_type_name(self, type, primary=False):
# type: (ObjType, bool) -> unicode
# never prepend "Default"
return type.lname
def is_enumerable_node(self, node):
# type: (nodes.Node) -> bool
return node.__class__ in self.enumerable_nodes
def get_numfig_title(self, node):
# type: (nodes.Node) -> unicode
"""Get the title of enumerable nodes to refer them using its title"""
if self.is_enumerable_node(node):
_, title_getter = self.enumerable_nodes.get(node.__class__, (None, None))
@ -820,6 +869,7 @@ class StandardDomain(Domain):
return None
def get_figtype(self, node):
# type: (nodes.Node) -> unicode
"""Get figure type of nodes."""
def has_child(node, cls):
return any(isinstance(child, cls) for child in node)
@ -836,6 +886,7 @@ class StandardDomain(Domain):
return figtype
def get_fignumber(self, env, builder, figtype, docname, target_node):
# type: (BuildEnvironment, Builder, unicode, unicode, nodes.Node) -> Tuple[int, ...]
if figtype == 'section':
if builder.name == 'latex':
return tuple()
@ -859,4 +910,5 @@ class StandardDomain(Domain):
def setup(app):
# type: (Sphinx) -> None
app.add_domain(StandardDomain)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
"""
sphinx.environment.managers
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Manager components for sphinx.environment.
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
if False:
# For type annotation
from typing import Any # NOQA
from docutils import nodes # NOQA
from sphinx.environment import BuildEnvironment # NOQA
class EnvironmentManager(object):
"""Base class for sphinx.environment managers."""
name = None # type: unicode
env = None # type: BuildEnvironment
def __init__(self, env):
# type: (BuildEnvironment) -> None
self.env = env
def attach(self, env):
# type: (BuildEnvironment) -> None
self.env = env
if self.name:
setattr(env, self.name, self)
def detach(self, env):
# type: (BuildEnvironment) -> None
self.env = None
if self.name:
delattr(env, self.name)
def clear_doc(self, docname):
# type: (unicode) -> None
raise NotImplementedError
def merge_other(self, docnames, other):
# type: (List[unicode], Any) -> None
raise NotImplementedError
def process_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
raise NotImplementedError

View File

@ -0,0 +1,183 @@
# -*- coding: utf-8 -*-
"""
sphinx.environment.managers.indexentries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Index entries manager for sphinx.environment.
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re
import bisect
import unicodedata
import string
from itertools import groupby
from six import text_type
from sphinx import addnodes
from sphinx.util import iteritems, split_index_msg, split_into
from sphinx.locale import _
from sphinx.environment.managers import EnvironmentManager
if False:
# For type annotation
from typing import Pattern, Tuple # NOQA
from docutils import nodes # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
class IndexEntries(EnvironmentManager):
name = 'indices'
def __init__(self, env):
# type: (BuildEnvironment) -> None
super(IndexEntries, self).__init__(env)
self.data = env.indexentries
def clear_doc(self, docname):
# type: (unicode) -> None
self.data.pop(docname, None)
def merge_other(self, docnames, other):
# type: (List[unicode], BuildEnvironment) -> None
for docname in docnames:
self.data[docname] = other.indexentries[docname]
def process_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
entries = self.data[docname] = []
for node in doctree.traverse(addnodes.index):
try:
for entry in node['entries']:
split_index_msg(entry[0], entry[1])
except ValueError as exc:
self.env.warn_node(exc, node)
node.parent.remove(node)
else:
for entry in node['entries']:
if len(entry) == 5:
# Since 1.4: new index structure including index_key (5th column)
entries.append(entry)
else:
entries.append(entry + (None,))
def create_index(self, builder, group_entries=True,
_fixre=re.compile(r'(.*) ([(][^()]*[)])')):
# type: (Builder, bool, Pattern) -> List[Tuple[unicode, List[Tuple[unicode, List[unicode]]]]] # NOQA
"""Create the real index from the collected index entries."""
from sphinx.environment import NoUri
new = {} # type: Dict[unicode, List]
def add_entry(word, subword, main, link=True, dic=new, key=None):
# Force the word to be unicode if it's a ASCII bytestring.
# This will solve problems with unicode normalization later.
# For instance the RFC role will add bytestrings at the moment
word = text_type(word)
entry = dic.get(word)
if not entry:
dic[word] = entry = [[], {}, key]
if subword:
add_entry(subword, '', main, link=link, dic=entry[1], key=key)
elif link:
try:
uri = builder.get_relative_uri('genindex', fn) + '#' + tid
except NoUri:
pass
else:
# maintain links in sorted/deterministic order
bisect.insort(entry[0], (main, uri))
for fn, entries in iteritems(self.data):
# new entry types must be listed in directives/other.py!
for type, value, tid, main, index_key in entries:
try:
if type == 'single':
try:
entry, subentry = split_into(2, 'single', value)
except ValueError:
entry, = split_into(1, 'single', value)
subentry = ''
add_entry(entry, subentry, main, key=index_key)
elif type == 'pair':
first, second = split_into(2, 'pair', value)
add_entry(first, second, main, key=index_key)
add_entry(second, first, main, key=index_key)
elif type == 'triple':
first, second, third = split_into(3, 'triple', value)
add_entry(first, second + ' ' + third, main, key=index_key)
add_entry(second, third + ', ' + first, main, key=index_key)
add_entry(third, first + ' ' + second, main, key=index_key)
elif type == 'see':
first, second = split_into(2, 'see', value)
add_entry(first, _('see %s') % second, None,
link=False, key=index_key)
elif type == 'seealso':
first, second = split_into(2, 'see', value)
add_entry(first, _('see also %s') % second, None,
link=False, key=index_key)
else:
self.env.warn(fn, 'unknown index entry type %r' % type)
except ValueError as err:
self.env.warn(fn, str(err))
# sort the index entries; put all symbols at the front, even those
# following the letters in ASCII, this is where the chr(127) comes from
def keyfunc(entry, lcletters=string.ascii_lowercase + '_'):
lckey = unicodedata.normalize('NFD', entry[0].lower())
if lckey[0:1] in lcletters:
lckey = chr(127) + lckey
# ensure a determinstic order *within* letters by also sorting on
# the entry itself
return (lckey, entry[0])
newlist = sorted(new.items(), key=keyfunc)
if group_entries:
# fixup entries: transform
# func() (in module foo)
# func() (in module bar)
# into
# func()
# (in module foo)
# (in module bar)
oldkey = '' # type: unicode
oldsubitems = None # type: Dict[unicode, List]
i = 0
while i < len(newlist):
key, (targets, subitems, _key) = newlist[i]
# cannot move if it has subitems; structure gets too complex
if not subitems:
m = _fixre.match(key)
if m:
if oldkey == m.group(1):
# prefixes match: add entry as subitem of the
# previous entry
oldsubitems.setdefault(m.group(2), [[], {}, _key])[0].\
extend(targets)
del newlist[i]
continue
oldkey = m.group(1)
else:
oldkey = key
oldsubitems = subitems
i += 1
# group the entries by letter
def keyfunc2(item, letters=string.ascii_uppercase + '_'):
# hack: mutating the subitems dicts to a list in the keyfunc
k, v = item
v[1] = sorted((si, se) for (si, (se, void, void)) in iteritems(v[1]))
if v[2] is None:
# now calculate the key
letter = unicodedata.normalize('NFD', k[0])[0].upper()
if letter in letters:
return letter
else:
# get all other symbols under one heading
return _('Symbols')
else:
return v[2]
return [(key_, list(group))
for (key_, group) in groupby(newlist, keyfunc2)]

View File

@ -0,0 +1,580 @@
# -*- coding: utf-8 -*-
"""
sphinx.environment.managers.toctree
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Toctree manager for sphinx.environment.
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from six import iteritems
from docutils import nodes
from sphinx import addnodes
from sphinx.util import url_re
from sphinx.util.nodes import clean_astext, process_only_nodes
from sphinx.transforms import SphinxContentsFilter
from sphinx.environment.managers import EnvironmentManager
if False:
# For type annotation
from typing import Any, Tuple # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
class Toctree(EnvironmentManager):
name = 'toctree'
def __init__(self, env):
# type: (BuildEnvironment) -> None
super(Toctree, self).__init__(env)
self.tocs = env.tocs
self.toc_num_entries = env.toc_num_entries
self.toc_secnumbers = env.toc_secnumbers
self.toc_fignumbers = env.toc_fignumbers
self.toctree_includes = env.toctree_includes
self.files_to_rebuild = env.files_to_rebuild
self.glob_toctrees = env.glob_toctrees
self.numbered_toctrees = env.numbered_toctrees
def clear_doc(self, docname):
# type: (unicode) -> None
self.tocs.pop(docname, None)
self.toc_secnumbers.pop(docname, None)
self.toc_fignumbers.pop(docname, None)
self.toc_num_entries.pop(docname, None)
self.toctree_includes.pop(docname, None)
self.glob_toctrees.discard(docname)
self.numbered_toctrees.discard(docname)
for subfn, fnset in list(self.files_to_rebuild.items()):
fnset.discard(docname)
if not fnset:
del self.files_to_rebuild[subfn]
def merge_other(self, docnames, other):
# type: (List[unicode], BuildEnvironment) -> None
for docname in docnames:
self.tocs[docname] = other.tocs[docname]
self.toc_num_entries[docname] = other.toc_num_entries[docname]
if docname in other.toctree_includes:
self.toctree_includes[docname] = other.toctree_includes[docname]
if docname in other.glob_toctrees:
self.glob_toctrees.add(docname)
if docname in other.numbered_toctrees:
self.numbered_toctrees.add(docname)
for subfn, fnset in other.files_to_rebuild.items():
self.files_to_rebuild.setdefault(subfn, set()).update(fnset & docnames)
def process_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None
"""Build a TOC from the doctree and store it in the inventory."""
numentries = [0] # nonlocal again...
def traverse_in_section(node, cls):
"""Like traverse(), but stay within the same section."""
result = []
if isinstance(node, cls):
result.append(node)
for child in node.children:
if isinstance(child, nodes.section):
continue
result.extend(traverse_in_section(child, cls))
return result
def build_toc(node, depth=1):
entries = []
for sectionnode in node:
# find all toctree nodes in this section and add them
# to the toc (just copying the toctree node which is then
# resolved in self.get_and_resolve_doctree)
if isinstance(sectionnode, addnodes.only):
onlynode = addnodes.only(expr=sectionnode['expr'])
blist = build_toc(sectionnode, depth)
if blist:
onlynode += blist.children
entries.append(onlynode)
continue
if not isinstance(sectionnode, nodes.section):
for toctreenode in traverse_in_section(sectionnode,
addnodes.toctree):
item = toctreenode.copy()
entries.append(item)
# important: do the inventory stuff
self.note_toctree(docname, toctreenode)
continue
title = sectionnode[0]
# copy the contents of the section title, but without references
# and unnecessary stuff
visitor = SphinxContentsFilter(doctree)
title.walkabout(visitor)
nodetext = visitor.get_entry_text()
if not numentries[0]:
# for the very first toc entry, don't add an anchor
# as it is the file's title anyway
anchorname = ''
else:
anchorname = '#' + sectionnode['ids'][0]
numentries[0] += 1
# make these nodes:
# list_item -> compact_paragraph -> reference
reference = nodes.reference(
'', '', internal=True, refuri=docname,
anchorname=anchorname, *nodetext)
para = addnodes.compact_paragraph('', '', reference)
item = nodes.list_item('', para)
sub_item = build_toc(sectionnode, depth + 1)
item += sub_item
entries.append(item)
if entries:
return nodes.bullet_list('', *entries)
return []
toc = build_toc(doctree)
if toc:
self.tocs[docname] = toc
else:
self.tocs[docname] = nodes.bullet_list('')
self.toc_num_entries[docname] = numentries[0]
def note_toctree(self, docname, toctreenode):
# type: (unicode, addnodes.toctree) -> None
"""Note a TOC tree directive in a document and gather information about
file relations from it.
"""
if toctreenode['glob']:
self.glob_toctrees.add(docname)
if toctreenode.get('numbered'):
self.numbered_toctrees.add(docname)
includefiles = toctreenode['includefiles']
for includefile in includefiles:
# note that if the included file is rebuilt, this one must be
# too (since the TOC of the included file could have changed)
self.files_to_rebuild.setdefault(includefile, set()).add(docname)
self.toctree_includes.setdefault(docname, []).extend(includefiles)
def get_toc_for(self, docname, builder):
# type: (unicode, Builder) -> None
"""Return a TOC nodetree -- for use on the same page only!"""
tocdepth = self.env.metadata[docname].get('tocdepth', 0)
try:
toc = self.tocs[docname].deepcopy()
self._toctree_prune(toc, 2, tocdepth)
except KeyError:
# the document does not exist anymore: return a dummy node that
# renders to nothing
return nodes.paragraph()
process_only_nodes(toc, builder.tags, warn_node=self.env.warn_node)
for node in toc.traverse(nodes.reference):
node['refuri'] = node['anchorname'] or '#'
return toc
def get_toctree_for(self, docname, builder, collapse, **kwds):
# type: (unicode, Builder, bool, Any) -> nodes.Node
"""Return the global TOC nodetree."""
doctree = self.env.get_doctree(self.env.config.master_doc)
toctrees = []
if 'includehidden' not in kwds:
kwds['includehidden'] = True
if 'maxdepth' not in kwds:
kwds['maxdepth'] = 0
kwds['collapse'] = collapse
for toctreenode in doctree.traverse(addnodes.toctree):
toctree = self.env.resolve_toctree(docname, builder, toctreenode,
prune=True, **kwds)
if toctree:
toctrees.append(toctree)
if not toctrees:
return None
result = toctrees[0]
for toctree in toctrees[1:]:
result.extend(toctree.children)
return result
def resolve_toctree(self, docname, builder, toctree, prune=True, maxdepth=0,
titles_only=False, collapse=False, includehidden=False):
# type: (unicode, Builder, addnodes.toctree, bool, int, bool, bool, bool) -> nodes.Node
"""Resolve a *toctree* node into individual bullet lists with titles
as items, returning None (if no containing titles are found) or
a new node.
If *prune* is True, the tree is pruned to *maxdepth*, or if that is 0,
to the value of the *maxdepth* option on the *toctree* node.
If *titles_only* is True, only toplevel document titles will be in the
resulting tree.
If *collapse* is True, all branches not containing docname will
be collapsed.
"""
if toctree.get('hidden', False) and not includehidden:
return None
# For reading the following two helper function, it is useful to keep
# in mind the node structure of a toctree (using HTML-like node names
# for brevity):
#
# <ul>
# <li>
# <p><a></p>
# <p><a></p>
# ...
# <ul>
# ...
# </ul>
# </li>
# </ul>
#
# The transformation is made in two passes in order to avoid
# interactions between marking and pruning the tree (see bug #1046).
toctree_ancestors = self.get_toctree_ancestors(docname)
def _toctree_add_classes(node, depth):
"""Add 'toctree-l%d' and 'current' classes to the toctree."""
for subnode in node.children:
if isinstance(subnode, (addnodes.compact_paragraph,
nodes.list_item)):
# for <p> and <li>, indicate the depth level and recurse
subnode['classes'].append('toctree-l%d' % (depth-1))
_toctree_add_classes(subnode, depth)
elif isinstance(subnode, nodes.bullet_list):
# for <ul>, just recurse
_toctree_add_classes(subnode, depth+1)
elif isinstance(subnode, nodes.reference):
# for <a>, identify which entries point to the current
# document and therefore may not be collapsed
if subnode['refuri'] == docname:
if not subnode['anchorname']:
# give the whole branch a 'current' class
# (useful for styling it differently)
branchnode = subnode
while branchnode:
branchnode['classes'].append('current')
branchnode = branchnode.parent
# mark the list_item as "on current page"
if subnode.parent.parent.get('iscurrent'):
# but only if it's not already done
return
while subnode:
subnode['iscurrent'] = True
subnode = subnode.parent
def _entries_from_toctree(toctreenode, parents,
separate=False, subtree=False):
"""Return TOC entries for a toctree node."""
refs = [(e[0], e[1]) for e in toctreenode['entries']]
entries = []
for (title, ref) in refs:
try:
refdoc = None
if url_re.match(ref):
if title is None:
title = ref
reference = nodes.reference('', '', internal=False,
refuri=ref, anchorname='',
*[nodes.Text(title)])
para = addnodes.compact_paragraph('', '', reference)
item = nodes.list_item('', para)
toc = nodes.bullet_list('', item)
elif ref == 'self':
# 'self' refers to the document from which this
# toctree originates
ref = toctreenode['parent']
if not title:
title = clean_astext(self.titles[ref])
reference = nodes.reference('', '', internal=True,
refuri=ref,
anchorname='',
*[nodes.Text(title)])
para = addnodes.compact_paragraph('', '', reference)
item = nodes.list_item('', para)
# don't show subitems
toc = nodes.bullet_list('', item)
else:
if ref in parents:
self.env.warn(ref, 'circular toctree references '
'detected, ignoring: %s <- %s' %
(ref, ' <- '.join(parents)))
continue
refdoc = ref
toc = self.tocs[ref].deepcopy()
maxdepth = self.env.metadata[ref].get('tocdepth', 0)
if ref not in toctree_ancestors or (prune and maxdepth > 0):
self._toctree_prune(toc, 2, maxdepth, collapse)
process_only_nodes(toc, builder.tags, warn_node=self.env.warn_node)
if title and toc.children and len(toc.children) == 1:
child = toc.children[0]
for refnode in child.traverse(nodes.reference):
if refnode['refuri'] == ref and \
not refnode['anchorname']:
refnode.children = [nodes.Text(title)]
if not toc.children:
# empty toc means: no titles will show up in the toctree
self.env.warn_node(
'toctree contains reference to document %r that '
'doesn\'t have a title: no link will be generated'
% ref, toctreenode)
except KeyError:
# this is raised if the included file does not exist
self.env.warn_node(
'toctree contains reference to nonexisting document %r'
% ref, toctreenode)
else:
# if titles_only is given, only keep the main title and
# sub-toctrees
if titles_only:
# delete everything but the toplevel title(s)
# and toctrees
for toplevel in toc:
# nodes with length 1 don't have any children anyway
if len(toplevel) > 1:
subtrees = toplevel.traverse(addnodes.toctree)
if subtrees:
toplevel[1][:] = subtrees
else:
toplevel.pop(1)
# resolve all sub-toctrees
for subtocnode in toc.traverse(addnodes.toctree):
if not (subtocnode.get('hidden', False) and
not includehidden):
i = subtocnode.parent.index(subtocnode) + 1
for item in _entries_from_toctree(
subtocnode, [refdoc] + parents,
subtree=True):
subtocnode.parent.insert(i, item)
i += 1
subtocnode.parent.remove(subtocnode)
if separate:
entries.append(toc)
else:
entries.extend(toc.children)
if not subtree and not separate:
ret = nodes.bullet_list()
ret += entries
return [ret]
return entries
maxdepth = maxdepth or toctree.get('maxdepth', -1)
if not titles_only and toctree.get('titlesonly', False):
titles_only = True
if not includehidden and toctree.get('includehidden', False):
includehidden = True
# NOTE: previously, this was separate=True, but that leads to artificial
# separation when two or more toctree entries form a logical unit, so
# separating mode is no longer used -- it's kept here for history's sake
tocentries = _entries_from_toctree(toctree, [], separate=False)
if not tocentries:
return None
newnode = addnodes.compact_paragraph('', '')
caption = toctree.attributes.get('caption')
if caption:
caption_node = nodes.caption(caption, '', *[nodes.Text(caption)])
caption_node.line = toctree.line
caption_node.source = toctree.source
caption_node.rawsource = toctree['rawcaption']
if hasattr(toctree, 'uid'):
# move uid to caption_node to translate it
caption_node.uid = toctree.uid
del toctree.uid
newnode += caption_node
newnode.extend(tocentries)
newnode['toctree'] = True
# prune the tree to maxdepth, also set toc depth and current classes
_toctree_add_classes(newnode, 1)
self._toctree_prune(newnode, 1, prune and maxdepth or 0, collapse)
if len(newnode[-1]) == 0: # No titles found
return None
# set the target paths in the toctrees (they are not known at TOC
# generation time)
for refnode in newnode.traverse(nodes.reference):
if not url_re.match(refnode['refuri']):
refnode['refuri'] = builder.get_relative_uri(
docname, refnode['refuri']) + refnode['anchorname']
return newnode
def get_toctree_ancestors(self, docname):
# type: (unicode) -> List[unicode]
parent = {}
for p, children in iteritems(self.toctree_includes):
for child in children:
parent[child] = p
ancestors = [] # type: List[unicode]
d = docname
while d in parent and d not in ancestors:
ancestors.append(d)
d = parent[d]
return ancestors
def _toctree_prune(self, node, depth, maxdepth, collapse=False):
# type: (nodes.Node, int, int, bool) -> None
"""Utility: Cut a TOC at a specified depth."""
for subnode in node.children[:]:
if isinstance(subnode, (addnodes.compact_paragraph,
nodes.list_item)):
# for <p> and <li>, just recurse
self._toctree_prune(subnode, depth, maxdepth, collapse)
elif isinstance(subnode, nodes.bullet_list):
# for <ul>, determine if the depth is too large or if the
# entry is to be collapsed
if maxdepth > 0 and depth > maxdepth:
subnode.parent.replace(subnode, [])
else:
# cull sub-entries whose parents aren't 'current'
if (collapse and depth > 1 and
'iscurrent' not in subnode.parent):
subnode.parent.remove(subnode)
else:
# recurse on visible children
self._toctree_prune(subnode, depth+1, maxdepth, collapse)
def assign_section_numbers(self):
# type: () -> List[unicode]
"""Assign a section number to each heading under a numbered toctree."""
# a list of all docnames whose section numbers changed
rewrite_needed = []
assigned = set() # type: Set[unicode]
old_secnumbers = self.toc_secnumbers
self.toc_secnumbers = self.env.toc_secnumbers = {}
def _walk_toc(node, secnums, depth, titlenode=None):
# titlenode is the title of the document, it will get assigned a
# secnumber too, so that it shows up in next/prev/parent rellinks
for subnode in node.children:
if isinstance(subnode, nodes.bullet_list):
numstack.append(0)
_walk_toc(subnode, secnums, depth-1, titlenode)
numstack.pop()
titlenode = None
elif isinstance(subnode, nodes.list_item):
_walk_toc(subnode, secnums, depth, titlenode)
titlenode = None
elif isinstance(subnode, addnodes.only):
# at this stage we don't know yet which sections are going
# to be included; just include all of them, even if it leads
# to gaps in the numbering
_walk_toc(subnode, secnums, depth, titlenode)
titlenode = None
elif isinstance(subnode, addnodes.compact_paragraph):
numstack[-1] += 1
if depth > 0:
number = tuple(numstack)
else:
number = None
secnums[subnode[0]['anchorname']] = \
subnode[0]['secnumber'] = number
if titlenode:
titlenode['secnumber'] = number
titlenode = None
elif isinstance(subnode, addnodes.toctree):
_walk_toctree(subnode, depth)
def _walk_toctree(toctreenode, depth):
if depth == 0:
return
for (title, ref) in toctreenode['entries']:
if url_re.match(ref) or ref == 'self' or ref in assigned:
# don't mess with those
continue
if ref in self.tocs:
secnums = self.toc_secnumbers[ref] = {}
assigned.add(ref)
_walk_toc(self.tocs[ref], secnums, depth,
self.env.titles.get(ref))
if secnums != old_secnumbers.get(ref):
rewrite_needed.append(ref)
for docname in self.numbered_toctrees:
assigned.add(docname)
doctree = self.env.get_doctree(docname)
for toctreenode in doctree.traverse(addnodes.toctree):
depth = toctreenode.get('numbered', 0)
if depth:
# every numbered toctree gets new numbering
numstack = [0]
_walk_toctree(toctreenode, depth)
return rewrite_needed
def assign_figure_numbers(self):
# type: () -> List[unicode]
"""Assign a figure number to each figure under a numbered toctree."""
rewrite_needed = []
assigned = set() # type: Set[unicode]
old_fignumbers = self.toc_fignumbers
self.toc_fignumbers = self.env.toc_fignumbers = {}
fignum_counter = {} # type: Dict[unicode, Dict[Tuple[int], int]]
def get_section_number(docname, section):
anchorname = '#' + section['ids'][0]
secnumbers = self.toc_secnumbers.get(docname, {})
if anchorname in secnumbers:
secnum = secnumbers.get(anchorname)
else:
secnum = secnumbers.get('')
return secnum or tuple()
def get_next_fignumber(figtype, secnum):
counter = fignum_counter.setdefault(figtype, {})
secnum = secnum[:self.env.config.numfig_secnum_depth]
counter[secnum] = counter.get(secnum, 0) + 1
return secnum + (counter[secnum],)
def register_fignumber(docname, secnum, figtype, fignode):
self.toc_fignumbers.setdefault(docname, {})
fignumbers = self.toc_fignumbers[docname].setdefault(figtype, {})
figure_id = fignode['ids'][0]
fignumbers[figure_id] = get_next_fignumber(figtype, secnum)
def _walk_doctree(docname, doctree, secnum):
for subnode in doctree.children:
if isinstance(subnode, nodes.section):
next_secnum = get_section_number(docname, subnode)
if next_secnum:
_walk_doctree(docname, subnode, next_secnum)
else:
_walk_doctree(docname, subnode, secnum)
continue
elif isinstance(subnode, addnodes.toctree):
for title, subdocname in subnode['entries']:
if url_re.match(subdocname) or subdocname == 'self':
# don't mess with those
continue
_walk_doc(subdocname, secnum)
continue
figtype = self.env.get_domain('std').get_figtype(subnode) # type: ignore
if figtype and subnode['ids']:
register_fignumber(docname, secnum, figtype, subnode)
_walk_doctree(docname, subnode, secnum)
def _walk_doc(docname, secnum):
if docname not in assigned:
assigned.add(docname)
doctree = self.env.get_doctree(docname)
_walk_doctree(docname, doctree, secnum)
if self.env.config.numfig:
_walk_doc(self.env.config.master_doc, tuple())
for docname, fignums in iteritems(self.toc_fignumbers):
if fignums != old_fignumbers.get(docname):
rewrite_needed.append(docname)
return rewrite_needed

View File

@ -19,6 +19,7 @@ from types import FunctionType, BuiltinFunctionType, MethodType
from six import PY2, iterkeys, iteritems, itervalues, text_type, class_types, \
string_types, StringIO
from docutils import nodes
from docutils.utils import assemble_option_dict
from docutils.statemachine import ViewList
@ -31,17 +32,29 @@ from sphinx.application import ExtensionError
from sphinx.util.nodes import nested_parse_with_titles
from sphinx.util.compat import Directive
from sphinx.util.inspect import getargspec, isdescriptor, safe_getmembers, \
safe_getattr, object_description, is_builtin_class_method
safe_getattr, object_description, is_builtin_class_method, isenumattribute
from sphinx.util.docstrings import prepare_docstring
if False:
# For type annotation
from typing import Any, Callable, Iterator, Sequence, Tuple, Type, Union # NOQA
from types import ModuleType # NOQA
from docutils.utils import Reporter # NOQA
from sphinx.application import Sphinx # NOQA
try:
if sys.version_info >= (3,):
import typing
else:
typing = None
typing = None # type: ignore
except ImportError:
typing = None
# This type isn't exposed directly in any modules, but can be found
# here in most Python versions
MethodDescriptorType = type(type.__subclasses__)
#: extended signature RE: with explicit module name separated by ::
py_ext_sig_re = re.compile(
r'''^ ([\w.]+::)? # explicit module name
@ -56,28 +69,33 @@ py_ext_sig_re = re.compile(
class DefDict(dict):
"""A dict that returns a default on nonexisting keys."""
def __init__(self, default):
# type: (Any) -> None
dict.__init__(self)
self.default = default
def __getitem__(self, key):
# type: (Any) -> Any
try:
return dict.__getitem__(self, key)
except KeyError:
return self.default
def __bool__(self):
# type: () -> bool
# docutils check "if option_spec"
return True
__nonzero__ = __bool__ # for python2 compatibility
def identity(x):
# type: (Any) -> Any
return x
class Options(dict):
"""A dict/attribute hybrid that returns None on nonexisting keys."""
def __getattr__(self, name):
# type: (unicode) -> Any
try:
return self[name.replace('_', '-')]
except KeyError:
@ -90,19 +108,26 @@ class _MockModule(object):
__path__ = '/dev/null'
def __init__(self, *args, **kwargs):
self.__all__ = []
# type: (Any, Any) -> None
self.__all__ = [] # type: List[str]
def __call__(self, *args, **kwargs):
# type: (Any, Any) -> _MockModule
if args and type(args[0]) in [FunctionType, MethodType]:
# Appears to be a decorator, pass through unchanged
return args[0]
return _MockModule()
def _append_submodule(self, submod):
# type: (str) -> None
self.__all__.append(submod)
@classmethod
def __getattr__(cls, name):
# type: (unicode) -> Any
if name[0] == name[0].upper():
# Not very good, we assume Uppercase names are classes...
mocktype = type(name, (), {})
mocktype = type(name, (), {}) # type: ignore
mocktype.__module__ = __name__
return mocktype
else:
@ -110,15 +135,16 @@ class _MockModule(object):
def mock_import(modname):
# type: (str) -> None
if '.' in modname:
pkg, _n, mods = modname.rpartition('.')
mock_import(pkg)
if isinstance(sys.modules[pkg], _MockModule):
sys.modules[pkg]._append_submodule(mods)
sys.modules[pkg]._append_submodule(mods) # type: ignore
if modname not in sys.modules:
mod = _MockModule()
sys.modules[modname] = mod
sys.modules[modname] = mod # type: ignore
ALL = object()
@ -126,6 +152,7 @@ INSTANCEATTR = object()
def members_option(arg):
# type: (Any) -> Union[object, List[unicode]]
"""Used to convert the :members: option to auto directives."""
if arg is None:
return ALL
@ -133,15 +160,18 @@ def members_option(arg):
def members_set_option(arg):
# type: (Any) -> Union[object, Set[unicode]]
"""Used to convert the :members: option to auto directives."""
if arg is None:
return ALL
return set(x.strip() for x in arg.split(','))
SUPPRESS = object()
def annotation_option(arg):
# type: (Any) -> Any
if arg is None:
# suppress showing the representation of the object
return SUPPRESS
@ -150,6 +180,7 @@ def annotation_option(arg):
def bool_option(arg):
# type: (Any) -> bool
"""Used to convert flag options to auto directives. (Instead of
directives.flag(), which returns None).
"""
@ -162,13 +193,16 @@ class AutodocReporter(object):
and line number to a system message, as recorded in a ViewList.
"""
def __init__(self, viewlist, reporter):
# type: (ViewList, Reporter) -> None
self.viewlist = viewlist
self.reporter = reporter
def __getattr__(self, name):
# type: (unicode) -> Any
return getattr(self.reporter, name)
def system_message(self, level, message, *children, **kwargs):
# type: (int, unicode, Any, Any) -> nodes.system_message
if 'line' in kwargs and 'source' not in kwargs:
try:
source, line = self.viewlist.items[kwargs['line']]
@ -181,25 +215,31 @@ class AutodocReporter(object):
*children, **kwargs)
def debug(self, *args, **kwargs):
# type: (Any, Any) -> nodes.system_message
if self.reporter.debug_flag:
return self.system_message(0, *args, **kwargs)
def info(self, *args, **kwargs):
# type: (Any, Any) -> nodes.system_message
return self.system_message(1, *args, **kwargs)
def warning(self, *args, **kwargs):
# type: (Any, Any) -> nodes.system_message
return self.system_message(2, *args, **kwargs)
def error(self, *args, **kwargs):
# type: (Any, Any) -> nodes.system_message
return self.system_message(3, *args, **kwargs)
def severe(self, *args, **kwargs):
# type: (Any, Any) -> nodes.system_message
return self.system_message(4, *args, **kwargs)
# Some useful event listener factories for autodoc-process-docstring.
def cut_lines(pre, post=0, what=None):
# type: (int, int, unicode) -> Callable
"""Return a listener that removes the first *pre* and last *post*
lines of every docstring. If *what* is a sequence of strings,
only docstrings of a type in *what* will be processed.
@ -212,6 +252,7 @@ def cut_lines(pre, post=0, what=None):
This can (and should) be used in place of :confval:`automodule_skip_lines`.
"""
def process(app, what_, name, obj, options, lines):
# type: (Sphinx, unicode, unicode, Any, Any, List[unicode]) -> None
if what and what_ not in what:
return
del lines[:pre]
@ -227,6 +268,7 @@ def cut_lines(pre, post=0, what=None):
def between(marker, what=None, keepempty=False, exclude=False):
# type: (unicode, Sequence[unicode], bool, bool) -> Callable
"""Return a listener that either keeps, or if *exclude* is True excludes,
lines between lines that match the *marker* regular expression. If no line
matches, the resulting docstring would be empty, so no change will be made
@ -238,6 +280,7 @@ def between(marker, what=None, keepempty=False, exclude=False):
marker_re = re.compile(marker)
def process(app, what_, name, obj, options, lines):
# type: (Sphinx, unicode, unicode, Any, Any, List[unicode]) -> None
if what and what_ not in what:
return
deleted = 0
@ -261,6 +304,7 @@ def between(marker, what=None, keepempty=False, exclude=False):
def format_annotation(annotation):
# type: (Any) -> str
"""Return formatted representation of a type annotation.
Show qualified names for types and additional details for types from
@ -268,16 +312,18 @@ def format_annotation(annotation):
Displaying complex types from ``typing`` relies on its private API.
"""
if typing and isinstance(annotation, typing.TypeVar):
if typing and isinstance(annotation, typing.TypeVar): # type: ignore
return annotation.__name__
if annotation == Ellipsis:
return '...'
if not isinstance(annotation, type):
return repr(annotation)
qualified_name = (annotation.__module__ + '.' + annotation.__qualname__
qualified_name = (annotation.__module__ + '.' + annotation.__qualname__ # type: ignore
if annotation else repr(annotation))
if annotation.__module__ == 'builtins':
return annotation.__qualname__
return annotation.__qualname__ # type: ignore
elif typing:
if hasattr(typing, 'GenericMeta') and \
isinstance(annotation, typing.GenericMeta):
@ -288,7 +334,12 @@ def format_annotation(annotation):
# arguments are in __parameters__.
params = None
if hasattr(annotation, '__args__'):
params = annotation.__args__
if annotation.__args__ is None or len(annotation.__args__) <= 2:
params = annotation.__args__
else: # typing.Callable
args = ', '.join(format_annotation(a) for a in annotation.__args__[:-1])
result = format_annotation(annotation.__args__[-1])
return '%s[[%s], %s]' % (qualified_name, args, result)
elif hasattr(annotation, '__parameters__'):
params = annotation.__parameters__
if params is not None:
@ -303,10 +354,13 @@ def format_annotation(annotation):
return '%s[%s]' % (qualified_name, param_str)
elif hasattr(typing, 'CallableMeta') and \
isinstance(annotation, typing.CallableMeta) and \
hasattr(annotation, '__args__') and \
getattr(annotation, '__args__', None) is not None and \
hasattr(annotation, '__result__'):
# Skipped in the case of plain typing.Callable
args = annotation.__args__
if args is Ellipsis:
if args is None:
return qualified_name
elif args is Ellipsis:
args_str = '...'
else:
formatted_args = (format_annotation(a) for a in args)
@ -330,6 +384,7 @@ def format_annotation(annotation):
def formatargspec(function, args, varargs=None, varkw=None, defaults=None,
kwonlyargs=(), kwonlydefaults={}, annotations={}):
# type: (Callable, Tuple[str, ...], str, str, Any, Tuple, Dict, Dict[str, Any]) -> str
"""Return a string representation of an ``inspect.FullArgSpec`` tuple.
An enhanced version of ``inspect.formatargspec()`` that handles typing
@ -337,18 +392,20 @@ def formatargspec(function, args, varargs=None, varkw=None, defaults=None,
"""
def format_arg_with_annotation(name):
# type: (str) -> str
if name in annotations:
return '%s: %s' % (name, format_annotation(get_annotation(name)))
return name
def get_annotation(name):
# type: (str) -> str
value = annotations[name]
if isinstance(value, string_types):
return introspected_hints.get(name, value)
else:
return value
introspected_hints = (typing.get_type_hints(function)
introspected_hints = (typing.get_type_hints(function) # type: ignore
if typing and hasattr(function, '__code__') else {})
fd = StringIO()
@ -362,20 +419,22 @@ def formatargspec(function, args, varargs=None, varkw=None, defaults=None,
arg_fd.write(format_arg_with_annotation(arg))
if defaults and i >= defaults_start:
arg_fd.write(' = ' if arg in annotations else '=')
arg_fd.write(object_description(defaults[i - defaults_start]))
arg_fd.write(object_description(defaults[i - defaults_start])) # type: ignore
formatted.append(arg_fd.getvalue())
if varargs:
formatted.append('*' + format_arg_with_annotation(varargs))
if kwonlyargs:
formatted.append('*')
if not varargs:
formatted.append('*')
for kwarg in kwonlyargs:
arg_fd = StringIO()
arg_fd.write(format_arg_with_annotation(kwarg))
if kwonlydefaults and kwarg in kwonlydefaults:
arg_fd.write(' = ' if kwarg in annotations else '=')
arg_fd.write(object_description(kwonlydefaults[kwarg]))
arg_fd.write(object_description(kwonlydefaults[kwarg])) # type: ignore
formatted.append(arg_fd.getvalue())
if varkw:
@ -422,6 +481,7 @@ class Documenter(object):
@staticmethod
def get_attr(obj, name, *defargs):
# type: (Any, unicode, Any) -> Any
"""getattr() override for types such as Zope interfaces."""
for typ, func in iteritems(AutoDirective._special_attrgetters):
if isinstance(obj, typ):
@ -430,10 +490,12 @@ class Documenter(object):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
"""Called to see if a member can be documented by this documenter."""
raise NotImplementedError('must be implemented in subclasses')
def __init__(self, directive, name, indent=u''):
# type: (Directive, unicode, unicode) -> None
self.directive = directive
self.env = directive.env
self.options = directive.genopt
@ -441,27 +503,29 @@ class Documenter(object):
self.indent = indent
# the module and object path within the module, and the fully
# qualified name (all set after resolve_name succeeds)
self.modname = None
self.module = None
self.objpath = None
self.fullname = None
self.modname = None # type: str
self.module = None # type: ModuleType
self.objpath = None # type: List[unicode]
self.fullname = None # type: unicode
# extra signature items (arguments and return annotation,
# also set after resolve_name succeeds)
self.args = None
self.retann = None
self.args = None # type: unicode
self.retann = None # type: unicode
# the object to document (set after import_object succeeds)
self.object = None
self.object_name = None
self.object = None # type: Any
self.object_name = None # type: unicode
# the parent/owner of the object to document
self.parent = None
self.parent = None # type: Any
# the module analyzer to get at attribute docs, or None
self.analyzer = None
self.analyzer = None # type: Any
def add_line(self, line, source, *lineno):
# type: (unicode, unicode, int) -> None
"""Append one line of generated reST to the output."""
self.directive.result.append(self.indent + line, source, *lineno)
def resolve_name(self, modname, parents, path, base):
# type: (str, Any, str, Any) -> Tuple[str, List[unicode]]
"""Resolve the module and name of the object to document given by the
arguments and the current module/class.
@ -472,6 +536,7 @@ class Documenter(object):
raise NotImplementedError('must be implemented in subclasses')
def parse_name(self):
# type: () -> bool
"""Determine what module to import and what attribute to document.
Returns True and sets *self.modname*, *self.objpath*, *self.fullname*,
@ -482,7 +547,7 @@ class Documenter(object):
# an autogenerated one
try:
explicit_modname, path, base, args, retann = \
py_ext_sig_re.match(self.name).groups()
py_ext_sig_re.match(self.name).groups() # type: ignore
except AttributeError:
self.directive.warn('invalid signature for auto%s (%r)' %
(self.objtype, self.name))
@ -496,8 +561,7 @@ class Documenter(object):
modname = None
parents = []
self.modname, self.objpath = \
self.resolve_name(modname, parents, path, base)
self.modname, self.objpath = self.resolve_name(modname, parents, path, base)
if not self.modname:
return False
@ -509,6 +573,7 @@ class Documenter(object):
return True
def import_object(self):
# type: () -> bool
"""Import the object given by *self.modname* and *self.objpath* and set
it as *self.object*.
@ -552,13 +617,14 @@ class Documenter(object):
errmsg += '; the following exception was raised:\n%s' % \
traceback.format_exc()
if PY2:
errmsg = errmsg.decode('utf-8')
errmsg = errmsg.decode('utf-8') # type: ignore
dbg(errmsg)
self.directive.warn(errmsg)
self.env.note_reread()
return False
def get_real_modname(self):
# type: () -> str
"""Get the real module name of an object to document.
It can differ from the name of the module through which the object was
@ -567,6 +633,7 @@ class Documenter(object):
return self.get_attr(self.object, '__module__', None) or self.modname
def check_module(self):
# type: () -> bool
"""Check if *self.object* is really defined in the module given by
*self.modname*.
"""
@ -579,6 +646,7 @@ class Documenter(object):
return True
def format_args(self):
# type: () -> unicode
"""Format the argument signature of *self.object*.
Should return None if the object does not have a signature.
@ -586,6 +654,7 @@ class Documenter(object):
return None
def format_name(self):
# type: () -> unicode
"""Format the name of *self.object*.
This normally should be something that can be parsed by the generated
@ -597,13 +666,14 @@ class Documenter(object):
return '.'.join(self.objpath) or self.modname
def format_signature(self):
# type: () -> unicode
"""Format the signature (arguments and return annotation) of the object.
Let the user process it via the ``autodoc-process-signature`` event.
"""
if self.args is not None:
# signature given explicitly
args = "(%s)" % self.args
args = "(%s)" % self.args # type: unicode
else:
# try to introspect the signature
try:
@ -627,6 +697,7 @@ class Documenter(object):
return ''
def add_directive_header(self, sig):
# type: (unicode) -> None
"""Add the directive header and options to the generated content."""
domain = getattr(self, 'domain', 'py')
directive = getattr(self, 'directivetype', self.objtype)
@ -642,6 +713,7 @@ class Documenter(object):
self.add_line(u' :module: %s' % self.modname, sourcename)
def get_doc(self, encoding=None, ignore=1):
# type: (unicode, int) -> List[List[unicode]]
"""Decode and return lines of the docstring(s) for the object."""
docstring = self.get_attr(self.object, '__doc__', None)
# make sure we have Unicode docstrings, then sanitize and split
@ -655,6 +727,7 @@ class Documenter(object):
return []
def process_doc(self, docstrings):
# type: (List[List[unicode]]) -> Iterator[unicode]
"""Let the user process the docstrings before adding them."""
for docstringlines in docstrings:
if self.env.app:
@ -666,6 +739,7 @@ class Documenter(object):
yield line
def get_sourcename(self):
# type: () -> unicode
if self.analyzer:
# prevent encoding errors when the file name is non-ASCII
if not isinstance(self.analyzer.srcname, text_type):
@ -677,6 +751,7 @@ class Documenter(object):
return u'docstring of %s' % self.fullname
def add_content(self, more_content, no_docstring=False):
# type: (Any, bool) -> None
"""Add content from docstrings, attribute documentation and user."""
# set sourcename and add content from attribute documentation
sourcename = self.get_sourcename()
@ -708,6 +783,7 @@ class Documenter(object):
self.add_line(line, src[0], src[1])
def get_object_members(self, want_all):
# type: (bool) -> Tuple[bool, List[Tuple[unicode, object]]]
"""Return `(members_check_module, members)` where `members` is a
list of `(membername, member)` pairs of the members of *self.object*.
@ -759,6 +835,7 @@ class Documenter(object):
return False, sorted(members)
def filter_members(self, members, want_all):
# type: (List[Tuple[unicode, Any]], bool) -> List[Tuple[unicode, Any, bool]]
"""Filter the given member list.
Members are skipped if
@ -836,6 +913,7 @@ class Documenter(object):
return ret
def document_members(self, all_members=False):
# type: (bool) -> None
"""Generate reST for member documentation.
If *all_members* is True, do all members, else those given by
@ -857,7 +935,7 @@ class Documenter(object):
if membername not in self.options.exclude_members]
# document non-skipped members
memberdocumenters = []
memberdocumenters = [] # type: List[Tuple[Documenter, bool]]
for (mname, member, isattr) in self.filter_members(members, want_all):
classes = [cls for cls in itervalues(AutoDirective._registry)
if cls.can_document_member(member, mname, isattr, self)]
@ -898,6 +976,7 @@ class Documenter(object):
def generate(self, more_content=None, real_modname=None,
check_module=False, all_members=False):
# type: (Any, str, bool, bool) -> None
"""Generate reST for the object given by *self.name*, and possibly for
its members.
@ -991,15 +1070,18 @@ class ModuleDocumenter(Documenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
# don't document submodules automatically
return False
def resolve_name(self, modname, parents, path, base):
# type: (str, Any, str, Any) -> Tuple[str, List[unicode]]
if modname is not None:
self.directive.warn('"::" in automodule name doesn\'t make sense')
return (path or '') + base, []
def parse_name(self):
# type: () -> bool
ret = Documenter.parse_name(self)
if self.args or self.retann:
self.directive.warn('signature arguments or return annotation '
@ -1007,6 +1089,7 @@ class ModuleDocumenter(Documenter):
return ret
def add_directive_header(self, sig):
# type: (unicode) -> None
Documenter.add_directive_header(self, sig)
sourcename = self.get_sourcename()
@ -1022,6 +1105,7 @@ class ModuleDocumenter(Documenter):
self.add_line(u' :deprecated:', sourcename)
def get_object_members(self, want_all):
# type: (bool) -> Tuple[bool, List[Tuple[unicode, object]]]
if want_all:
if not hasattr(self.object, '__all__'):
# for implicit module members, check __module__ to avoid
@ -1058,6 +1142,7 @@ class ModuleLevelDocumenter(Documenter):
classes, data/constants).
"""
def resolve_name(self, modname, parents, path, base):
# type: (str, Any, str, Any) -> Tuple[str, List[unicode]]
if modname is None:
if path:
modname = path.rstrip('.')
@ -1078,6 +1163,7 @@ class ClassLevelDocumenter(Documenter):
attributes).
"""
def resolve_name(self, modname, parents, path, base):
# type: (str, Any, str, Any) -> Tuple[str, List[unicode]]
if modname is None:
if path:
mod_cls = path.rstrip('.')
@ -1111,6 +1197,7 @@ class DocstringSignatureMixin(object):
"""
def _find_signature(self, encoding=None):
# type: (unicode) -> Tuple[str, str]
docstrings = self.get_doc(encoding)
self._new_docstrings = docstrings[:]
result = None
@ -1119,12 +1206,12 @@ class DocstringSignatureMixin(object):
if not doclines:
continue
# match first line of docstring against signature RE
match = py_ext_sig_re.match(doclines[0])
match = py_ext_sig_re.match(doclines[0]) # type: ignore
if not match:
continue
exmod, path, base, args, retann = match.groups()
# the base name must match ours
valid_names = [self.objpath[-1]]
valid_names = [self.objpath[-1]] # type: ignore
if isinstance(self, ClassDocumenter):
valid_names.append('__init__')
if hasattr(self.object, '__mro__'):
@ -1139,19 +1226,21 @@ class DocstringSignatureMixin(object):
return result
def get_doc(self, encoding=None, ignore=1):
# type: (unicode, int) -> List[List[unicode]]
lines = getattr(self, '_new_docstrings', None)
if lines is not None:
return lines
return Documenter.get_doc(self, encoding, ignore)
return Documenter.get_doc(self, encoding, ignore) # type: ignore
def format_signature(self):
if self.args is None and self.env.config.autodoc_docstring_signature:
# type: () -> unicode
if self.args is None and self.env.config.autodoc_docstring_signature: # type: ignore
# only act if a signature is not explicitly given already, and if
# the feature is enabled
result = self._find_signature()
if result is not None:
self.args, self.retann = result
return Documenter.format_signature(self)
return Documenter.format_signature(self) # type: ignore
class DocstringStripSignatureMixin(DocstringSignatureMixin):
@ -1160,7 +1249,8 @@ class DocstringStripSignatureMixin(DocstringSignatureMixin):
feature of stripping any function signature from the docstring.
"""
def format_signature(self):
if self.args is None and self.env.config.autodoc_docstring_signature:
# type: () -> unicode
if self.args is None and self.env.config.autodoc_docstring_signature: # type: ignore
# only act if a signature is not explicitly given already, and if
# the feature is enabled
result = self._find_signature()
@ -1169,10 +1259,10 @@ class DocstringStripSignatureMixin(DocstringSignatureMixin):
# DocstringSignatureMixin.format_signature.
# Documenter.format_signature use self.args value to format.
_args, self.retann = result
return Documenter.format_signature(self)
return Documenter.format_signature(self) # type: ignore
class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: ignore
"""
Specialized Documenter subclass for functions.
"""
@ -1181,9 +1271,11 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
return isinstance(member, (FunctionType, BuiltinFunctionType))
def format_args(self):
# type: () -> unicode
if inspect.isbuiltin(self.object) or \
inspect.ismethoddescriptor(self.object):
# cannot introspect arguments of a C function or method
@ -1210,10 +1302,11 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
return args
def document_members(self, all_members=False):
# type: (bool) -> None
pass
class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: ignore
"""
Specialized Documenter subclass for classes.
"""
@ -1229,9 +1322,11 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
return isinstance(member, class_types)
def import_object(self):
# type: () -> Any
ret = ModuleLevelDocumenter.import_object(self)
# if the class is documented under another name, document it
# as data/attribute
@ -1243,6 +1338,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
return ret
def format_args(self):
# type: () -> unicode
# for classes, the relevant signature is the __init__ method's
initmeth = self.get_attr(self.object, '__init__', None)
# classes without __init__ method, default __init__ or
@ -1262,12 +1358,14 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
return formatargspec(initmeth, *argspec)
def format_signature(self):
# type: () -> unicode
if self.doc_as_attr:
return ''
return DocstringSignatureMixin.format_signature(self)
def add_directive_header(self, sig):
# type: (unicode) -> None
if self.doc_as_attr:
self.directivetype = 'attribute'
Documenter.add_directive_header(self, sig)
@ -1285,6 +1383,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
sourcename)
def get_doc(self, encoding=None, ignore=1):
# type: (unicode, int) -> List[List[unicode]]
lines = getattr(self, '_new_docstrings', None)
if lines is not None:
return lines
@ -1330,6 +1429,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
return doc
def add_content(self, more_content, no_docstring=False):
# type: (Any, bool) -> None
if self.doc_as_attr:
classname = safe_getattr(self.object, '__name__', None)
if classname:
@ -1341,6 +1441,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
ModuleLevelDocumenter.add_content(self, more_content)
def document_members(self, all_members=False):
# type: (bool) -> None
if self.doc_as_attr:
return
ModuleLevelDocumenter.document_members(self, all_members)
@ -1358,8 +1459,9 @@ class ExceptionDocumenter(ClassDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
return isinstance(member, class_types) and \
issubclass(member, BaseException)
issubclass(member, BaseException) # type: ignore
class DataDocumenter(ModuleLevelDocumenter):
@ -1374,9 +1476,11 @@ class DataDocumenter(ModuleLevelDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
return isinstance(parent, ModuleDocumenter) and isattr
def add_directive_header(self, sig):
# type: (unicode) -> None
ModuleLevelDocumenter.add_directive_header(self, sig)
sourcename = self.get_sourcename()
if not self.options.annotation:
@ -1393,10 +1497,11 @@ class DataDocumenter(ModuleLevelDocumenter):
sourcename)
def document_members(self, all_members=False):
# type: (bool) -> None
pass
class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type: ignore
"""
Specialized Documenter subclass for methods (normal, static and class).
"""
@ -1406,10 +1511,12 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
return inspect.isroutine(member) and \
not isinstance(parent, ModuleDocumenter)
def import_object(self):
# type: () -> Any
ret = ClassLevelDocumenter.import_object(self)
if not ret:
return ret
@ -1417,11 +1524,11 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
# to distinguish classmethod/staticmethod
obj = self.parent.__dict__.get(self.object_name)
if isinstance(obj, classmethod):
if isinstance(obj, classmethod): # type: ignore
self.directivetype = 'classmethod'
# document class and static members before ordinary ones
self.member_order = self.member_order - 1
elif isinstance(obj, staticmethod):
elif isinstance(obj, staticmethod): # type: ignore
self.directivetype = 'staticmethod'
# document class and static members before ordinary ones
self.member_order = self.member_order - 1
@ -1430,6 +1537,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
return ret
def format_args(self):
# type: () -> unicode
if inspect.isbuiltin(self.object) or \
inspect.ismethoddescriptor(self.object):
# can never get arguments of a C function or method
@ -1443,10 +1551,11 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
return args
def document_members(self, all_members=False):
# type: (bool) -> None
pass
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore
"""
Specialized Documenter subclass for attributes.
"""
@ -1463,19 +1572,27 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
non_attr_types = cls.method_types + (type, MethodDescriptorType)
isdatadesc = isdescriptor(member) and not \
isinstance(member, cls.method_types) and not \
type(member).__name__ in ("type", "method_descriptor",
"instancemethod")
isinstance(member, non_attr_types) and not \
type(member).__name__ == "instancemethod"
# That last condition addresses an obscure case of C-defined
# methods using a deprecated type in Python 3, that is not otherwise
# exported anywhere by Python
return isdatadesc or (not isinstance(parent, ModuleDocumenter) and
not inspect.isroutine(member) and
not isinstance(member, class_types))
def document_members(self, all_members=False):
# type: (bool) -> None
pass
def import_object(self):
# type: () -> Any
ret = ClassLevelDocumenter.import_object(self)
if isenumattribute(self.object):
self.object = self.object.value
if isdescriptor(self.object) and \
not isinstance(self.object, self.method_types):
self._datadescriptor = True
@ -1485,10 +1602,12 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
return ret
def get_real_modname(self):
# type: () -> str
return self.get_attr(self.parent or self.object, '__module__', None) \
or self.modname
def add_directive_header(self, sig):
# type: (unicode) -> None
ClassLevelDocumenter.add_directive_header(self, sig)
sourcename = self.get_sourcename()
if not self.options.annotation:
@ -1506,6 +1625,7 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
sourcename)
def add_content(self, more_content, no_docstring=False):
# type: (Any, bool) -> None
if not self._datadescriptor:
# if it's not a data descriptor, its docstring is very probably the
# wrong thing to display
@ -1527,10 +1647,12 @@ class InstanceAttributeDocumenter(AttributeDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
"""This documents only INSTANCEATTR members."""
return isattr and (member is INSTANCEATTR)
def import_object(self):
# type: () -> bool
"""Never import anything."""
# disguise as an attribute
self.objtype = 'attribute'
@ -1538,6 +1660,7 @@ class InstanceAttributeDocumenter(AttributeDocumenter):
return True
def add_content(self, more_content, no_docstring=False):
# type: (Any, bool) -> None
"""Never try to get a docstring from the object."""
AttributeDocumenter.add_content(self, more_content, no_docstring=True)
@ -1558,10 +1681,10 @@ class AutoDirective(Directive):
attributes of the parents.
"""
# a registry of objtype -> documenter class
_registry = {}
_registry = {} # type: Dict[unicode, Type[Documenter]]
# a registry of type -> getattr function
_special_attrgetters = {}
_special_attrgetters = {} # type: Dict[Type, Callable]
# flags that can be given in autodoc_default_flags
_default_flags = set([
@ -1579,13 +1702,16 @@ class AutoDirective(Directive):
option_spec = DefDict(identity)
def warn(self, msg):
# type: (unicode) -> None
self.warnings.append(self.reporter.warning(msg, line=self.lineno))
def run(self):
self.filename_set = set() # a set of dependent filenames
# type: () -> List[nodes.Node]
self.filename_set = set() # type: Set[unicode]
# a set of dependent filenames
self.reporter = self.state.document.reporter
self.env = self.state.document.settings.env
self.warnings = []
self.warnings = [] # type: List[unicode]
self.result = ViewList()
try:
@ -1649,6 +1775,7 @@ class AutoDirective(Directive):
def add_documenter(cls):
# type: (Type[Documenter]) -> None
"""Register a new Documenter."""
if not issubclass(cls, Documenter):
raise ExtensionError('autodoc documenter %r must be a subclass '
@ -1661,6 +1788,7 @@ def add_documenter(cls):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_autodocumenter(ModuleDocumenter)
app.add_autodocumenter(ClassDocumenter)
app.add_autodocumenter(ExceptionDocumenter)

View File

@ -62,6 +62,7 @@ from six import string_types
from types import ModuleType
from six import text_type
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
from docutils import nodes
@ -73,6 +74,14 @@ from sphinx.util.compat import Directive
from sphinx.pycode import ModuleAnalyzer, PycodeError
from sphinx.ext.autodoc import Options
if False:
# For type annotation
from typing import Any, Tuple, Type, Union # NOQA
from docutils.utils import Inliner # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.ext.autodoc import Documenter # NOQA
# -- autosummary_toc node ------------------------------------------------------
@ -81,6 +90,7 @@ class autosummary_toc(nodes.comment):
def process_autosummary_toc(app, doctree):
# type: (Sphinx, nodes.Node) -> None
"""Insert items described in autosummary:: to the TOC tree, but do
not generate the toctree:: list.
"""
@ -105,11 +115,13 @@ def process_autosummary_toc(app, doctree):
def autosummary_toc_visit_html(self, node):
# type: (nodes.NodeVisitor, autosummary_toc) -> None
"""Hide autosummary toctree list in HTML output."""
raise nodes.SkipNode
def autosummary_noop(self, node):
# type: (nodes.NodeVisitor, nodes.Node) -> None
pass
@ -120,6 +132,7 @@ class autosummary_table(nodes.comment):
def autosummary_table_visit_html(self, node):
# type: (nodes.NodeVisitor, autosummary_table) -> None
"""Make the first column of the table non-breaking."""
try:
tbody = node[0][0][-1]
@ -138,11 +151,12 @@ def autosummary_table_visit_html(self, node):
# -- autodoc integration -------------------------------------------------------
class FakeDirective(object):
env = {}
env = {} # type: Dict
genopt = Options()
def get_documenter(obj, parent):
# type: (Any, Any) -> Type[Documenter]
"""Get an autodoc.Documenter class suitable for documenting the given
object.
@ -198,13 +212,15 @@ class Autosummary(Directive):
}
def warn(self, msg):
# type: (unicode) -> None
self.warnings.append(self.state.document.reporter.warning(
msg, line=self.lineno))
def run(self):
# type: () -> List[nodes.Node]
self.env = env = self.state.document.settings.env
self.genopt = Options()
self.warnings = []
self.warnings = [] # type: List[nodes.Node]
self.result = ViewList()
names = [x.strip().split()[0] for x in self.content
@ -237,6 +253,7 @@ class Autosummary(Directive):
return self.warnings + nodes
def get_items(self, names):
# type: (List[unicode]) -> List[Tuple[unicode, unicode, unicode, unicode]]
"""Try to import the given names, and return a list of
``[(name, signature, summary_string, real_name), ...]``.
"""
@ -244,7 +261,7 @@ class Autosummary(Directive):
prefixes = get_import_prefixes_from_env(env)
items = []
items = [] # type: List[Tuple[unicode, unicode, unicode, unicode]]
max_item_chars = 50
@ -334,6 +351,7 @@ class Autosummary(Directive):
return items
def get_table(self, items):
# type: (List[Tuple[unicode, unicode, unicode, unicode]]) -> List[Union[addnodes.tabular_col_spec, autosummary_table]] # NOQA
"""Generate a proper list of table nodes for autosummary:: directive.
*items* is a list produced by :meth:`get_items`.
@ -352,6 +370,7 @@ class Autosummary(Directive):
group.append(body)
def append_row(*column_texts):
# type: (unicode) -> None
row = nodes.row('')
for text in column_texts:
node = nodes.paragraph('')
@ -369,7 +388,7 @@ class Autosummary(Directive):
for name, sig, summary, real_name in items:
qualifier = 'obj'
if 'nosignatures' not in self.options:
col1 = ':%s:`%s <%s>`\ %s' % (qualifier, name, real_name, rst.escape(sig))
col1 = ':%s:`%s <%s>`\ %s' % (qualifier, name, real_name, rst.escape(sig)) # type: unicode # NOQA
else:
col1 = ':%s:`%s <%s>`' % (qualifier, name, real_name)
col2 = summary
@ -379,6 +398,7 @@ class Autosummary(Directive):
def mangle_signature(sig, max_chars=30):
# type: (unicode, int) -> unicode
"""Reformat a function signature to a more compact form."""
s = re.sub(r"^\((.*)\)$", r"\1", sig).strip()
@ -388,12 +408,12 @@ def mangle_signature(sig, max_chars=30):
s = re.sub(r"'[^']*'", "", s)
# Parse the signature to arguments + options
args = []
opts = []
args = [] # type: List[unicode]
opts = [] # type: List[unicode]
opt_re = re.compile(r"^(.*, |)([a-zA-Z0-9_*]+)=")
while s:
m = opt_re.search(s)
m = opt_re.search(s) # type: ignore
if not m:
# The rest are arguments
args = s.split(', ')
@ -415,6 +435,7 @@ def mangle_signature(sig, max_chars=30):
def limited_join(sep, items, max_chars=30, overflow_marker="..."):
# type: (unicode, List[unicode], int, unicode) -> unicode
"""Join a number of strings to one, limiting the length to *max_chars*.
If the string overflows this limit, replace the last fitting item by
@ -441,11 +462,12 @@ def limited_join(sep, items, max_chars=30, overflow_marker="..."):
# -- Importing items -----------------------------------------------------------
def get_import_prefixes_from_env(env):
# type: (BuildEnvironment) -> List
"""
Obtain current Python import prefixes (for `import_by_name`)
from ``document.env``
"""
prefixes = [None]
prefixes = [None] # type: List
currmodule = env.ref_context.get('py:module')
if currmodule:
@ -462,6 +484,7 @@ def get_import_prefixes_from_env(env):
def import_by_name(name, prefixes=[None]):
# type: (unicode, List) -> Tuple[unicode, Any, Any, unicode]
"""Import a Python object that has the given *name*, under one of the
*prefixes*. The first name that succeeds is used.
"""
@ -480,6 +503,7 @@ def import_by_name(name, prefixes=[None]):
def _import_by_name(name):
# type: (str) -> Tuple[Any, Any, unicode]
"""Import a Python object given its full name."""
try:
name_parts = name.split('.')
@ -524,6 +548,7 @@ def _import_by_name(name):
def autolink_role(typ, rawtext, etext, lineno, inliner,
options={}, content=[]):
# type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
"""Smart linking role.
Expands to ':obj:`text`' if `text` is an object that can be imported;
@ -539,21 +564,24 @@ def autolink_role(typ, rawtext, etext, lineno, inliner,
name, obj, parent, modname = import_by_name(pnode['reftarget'], prefixes)
except ImportError:
content = pnode[0]
r[0][0] = nodes.emphasis(rawtext, content[0].astext(),
classes=content['classes'])
r[0][0] = nodes.emphasis(rawtext, content[0].astext(), # type: ignore
classes=content['classes']) # type: ignore
return r
def get_rst_suffix(app):
# type: (Sphinx) -> unicode
def get_supported_format(suffix):
# type: (unicode) -> Tuple[unicode]
parser_class = app.config.source_parsers.get(suffix)
if parser_class is None:
return ('restructuredtext',)
if isinstance(parser_class, string_types):
parser_class = import_object(parser_class, 'source parser')
parser_class = import_object(parser_class, 'source parser') # type: ignore
return parser_class.supported
for suffix in app.config.source_suffix:
suffix = None # type: unicode
for suffix in app.config.source_suffix: # type: ignore
if 'restructuredtext' in get_supported_format(suffix):
return suffix
@ -561,6 +589,7 @@ def get_rst_suffix(app):
def process_generate_options(app):
# type: (Sphinx) -> None
genfiles = app.config.autosummary_generate
if genfiles and not hasattr(genfiles, '__len__'):
@ -589,6 +618,7 @@ def process_generate_options(app):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
# I need autodoc
app.setup_extension('sphinx.ext.autodoc')
app.add_node(autosummary_toc,

View File

@ -49,8 +49,16 @@ add_documenter(MethodDocumenter)
add_documenter(AttributeDocumenter)
add_documenter(InstanceAttributeDocumenter)
if False:
# For type annotation
from typing import Any, Callable, Tuple # NOQA
from sphinx import addnodes # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
def main(argv=sys.argv):
# type: (List[str]) -> None
usage = """%prog [OPTIONS] SOURCEFILE ..."""
p = optparse.OptionParser(usage.strip())
p.add_option("-o", "--output-dir", action="store", type="string",
@ -73,10 +81,12 @@ def main(argv=sys.argv):
def _simple_info(msg):
# type: (unicode) -> None
print(msg)
def _simple_warn(msg):
# type: (unicode) -> None
print('WARNING: ' + msg, file=sys.stderr)
@ -85,6 +95,7 @@ def _simple_warn(msg):
def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
warn=_simple_warn, info=_simple_info,
base_path=None, builder=None, template_dir=None):
# type: (List[unicode], unicode, unicode, Callable, Callable, unicode, Builder, unicode) -> None # NOQA
showed_sources = list(sorted(sources))
if len(showed_sources) > 20:
@ -99,6 +110,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
sources = [os.path.join(base_path, filename) for filename in sources]
# create our own templating environment
template_dirs = None # type: List[unicode]
template_dirs = [os.path.join(package_dir, 'ext',
'autosummary', 'templates')]
if builder is not None:
@ -154,7 +166,8 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
template = template_env.get_template('autosummary/base.rst')
def get_members(obj, typ, include_public=[]):
items = []
# type: (Any, unicode, List[unicode]) -> Tuple[List[unicode], List[unicode]]
items = [] # type: List[unicode]
for name in dir(obj):
try:
documenter = get_documenter(safe_getattr(obj, name),
@ -167,7 +180,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
if x in include_public or not x.startswith('_')]
return public, items
ns = {}
ns = {} # type: Dict[unicode, Any]
if doc.objtype == 'module':
ns['members'] = dir(obj)
@ -215,21 +228,23 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
# -- Finding documented entries in files ---------------------------------------
def find_autosummary_in_files(filenames):
# type: (List[unicode]) -> List[Tuple[unicode, unicode, unicode]]
"""Find out what items are documented in source/*.rst.
See `find_autosummary_in_lines`.
"""
documented = []
documented = [] # type: List[Tuple[unicode, unicode, unicode]]
for filename in filenames:
with codecs.open(filename, 'r', encoding='utf-8',
with codecs.open(filename, 'r', encoding='utf-8', # type: ignore
errors='ignore') as f:
lines = f.read().splitlines()
documented.extend(find_autosummary_in_lines(lines,
documented.extend(find_autosummary_in_lines(lines, # type: ignore
filename=filename))
return documented
def find_autosummary_in_docstring(name, module=None, filename=None):
# type: (unicode, Any, unicode) -> List[Tuple[unicode, unicode, unicode]]
"""Find out what items are documented in the given object's docstring.
See `find_autosummary_in_lines`.
@ -249,6 +264,7 @@ def find_autosummary_in_docstring(name, module=None, filename=None):
def find_autosummary_in_lines(lines, module=None, filename=None):
# type: (List[unicode], Any, unicode) -> List[Tuple[unicode, unicode, unicode]]
"""Find out what items appear in autosummary:: directives in the
given lines.
@ -268,9 +284,9 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$')
template_arg_re = re.compile(r'^\s+:template:\s*(.*?)\s*$')
documented = []
documented = [] # type: List[Tuple[unicode, unicode, unicode]]
toctree = None
toctree = None # type: unicode
template = None
current_module = module
in_autosummary = False
@ -278,7 +294,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
for line in lines:
if in_autosummary:
m = toctree_arg_re.match(line)
m = toctree_arg_re.match(line) # type: ignore
if m:
toctree = m.group(1)
if filename:
@ -286,7 +302,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
toctree)
continue
m = template_arg_re.match(line)
m = template_arg_re.match(line) # type: ignore
if m:
template = m.group(1).strip()
continue
@ -294,7 +310,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
if line.strip().startswith(':'):
continue # skip options
m = autosummary_item_re.match(line)
m = autosummary_item_re.match(line) # type: ignore
if m:
name = m.group(1).strip()
if name.startswith('~'):
@ -310,7 +326,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
in_autosummary = False
m = autosummary_re.match(line)
m = autosummary_re.match(line) # type: ignore
if m:
in_autosummary = True
base_indent = m.group(1)
@ -318,7 +334,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
template = None
continue
m = automodule_re.search(line)
m = automodule_re.search(line) # type: ignore
if m:
current_module = m.group(1).strip()
# recurse into the automodule docstring
@ -326,7 +342,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
current_module, filename=filename))
continue
m = module_re.match(line)
m = module_re.match(line) # type: ignore
if m:
current_module = m.group(2)
continue

View File

@ -22,14 +22,21 @@ import sphinx
from sphinx.builders import Builder
from sphinx.util.inspect import safe_getattr
if False:
# For type annotation
from typing import Any, Callable, IO, Pattern, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
# utility
def write_header(f, text, char='-'):
# type:(IO, unicode, unicode) -> None
f.write(text + '\n')
f.write(char * len(text) + '\n')
def compile_regex_list(name, exps, warnfunc):
# type: (unicode, unicode, Callable) -> List[Pattern]
lst = []
for exp in exps:
try:
@ -44,19 +51,20 @@ class CoverageBuilder(Builder):
name = 'coverage'
def init(self):
self.c_sourcefiles = []
# type: () -> None
self.c_sourcefiles = [] # type: List[unicode]
for pattern in self.config.coverage_c_path:
pattern = path.join(self.srcdir, pattern)
self.c_sourcefiles.extend(glob.glob(pattern))
self.c_regexes = []
self.c_regexes = [] # type: List[Tuple[unicode, Pattern]]
for (name, exp) in self.config.coverage_c_regexes.items():
try:
self.c_regexes.append((name, re.compile(exp)))
except Exception:
self.warn('invalid regex %r in coverage_c_regexes' % exp)
self.c_ignorexps = {}
self.c_ignorexps = {} # type: Dict[unicode, List[Pattern]]
for (name, exps) in iteritems(self.config.coverage_ignore_c_items):
self.c_ignorexps[name] = compile_regex_list(
'coverage_ignore_c_items', exps, self.warn)
@ -71,18 +79,21 @@ class CoverageBuilder(Builder):
self.warn)
def get_outdated_docs(self):
# type: () -> unicode
return 'coverage overview'
def write(self, *ignored):
self.py_undoc = {}
# type: (Any) -> None
self.py_undoc = {} # type: Dict[unicode, Dict[unicode, Any]]
self.build_py_coverage()
self.write_py_coverage()
self.c_undoc = {}
self.c_undoc = {} # type: Dict[unicode, Set[Tuple[unicode, unicode]]]
self.build_c_coverage()
self.write_c_coverage()
def build_c_coverage(self):
# type: () -> None
# Fetch all the info from the header files
c_objects = self.env.domaindata['c']['objects']
for filename in self.c_sourcefiles:
@ -94,7 +105,7 @@ class CoverageBuilder(Builder):
if match:
name = match.groups()[0]
if name not in c_objects:
for exp in self.c_ignorexps.get(key, ()):
for exp in self.c_ignorexps.get(key, []):
if exp.match(name):
break
else:
@ -104,6 +115,7 @@ class CoverageBuilder(Builder):
self.c_undoc[filename] = undoc
def write_c_coverage(self):
# type: () -> None
output_file = path.join(self.outdir, 'c.txt')
with open(output_file, 'w') as op:
if self.config.coverage_write_headline:
@ -117,6 +129,7 @@ class CoverageBuilder(Builder):
op.write('\n')
def build_py_coverage(self):
# type: () -> None
objects = self.env.domaindata['py']['objects']
modules = self.env.domaindata['py']['modules']
@ -140,7 +153,7 @@ class CoverageBuilder(Builder):
continue
funcs = []
classes = {}
classes = {} # type: Dict[unicode, List[unicode]]
for name, obj in inspect.getmembers(mod):
# diverse module attributes are ignored:
@ -177,7 +190,7 @@ class CoverageBuilder(Builder):
classes[name] = []
continue
attrs = []
attrs = [] # type: List[unicode]
for attr_name in dir(obj):
if attr_name not in obj.__dict__:
@ -207,6 +220,7 @@ class CoverageBuilder(Builder):
self.py_undoc[mod_name] = {'funcs': funcs, 'classes': classes}
def write_py_coverage(self):
# type: () -> None
output_file = path.join(self.outdir, 'python.txt')
failed = []
with open(output_file, 'w') as op:
@ -242,6 +256,7 @@ class CoverageBuilder(Builder):
op.writelines(' * %s -- %s\n' % x for x in failed)
def finish(self):
# type: () -> None
# dump the coverage data to a pickle file too
picklepath = path.join(self.outdir, 'undoc.pickle')
with open(picklepath, 'wb') as dumpfile:
@ -249,6 +264,7 @@ class CoverageBuilder(Builder):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_builder(CoverageBuilder)
app.add_config_value('coverage_ignore_modules', [], False)
app.add_config_value('coverage_ignore_functions', [], False)

View File

@ -19,6 +19,7 @@ from os import path
import doctest
from six import itervalues, StringIO, binary_type, text_type, PY2
from docutils import nodes
from docutils.parsers.rst import directives
@ -27,14 +28,20 @@ from sphinx.builders import Builder
from sphinx.util import force_decode
from sphinx.util.nodes import set_source_info
from sphinx.util.compat import Directive
from sphinx.util.console import bold
from sphinx.util.console import bold # type: ignore
from sphinx.util.osutil import fs_encoding
if False:
# For type annotation
from typing import Any, Callable, IO, Iterable, Sequence, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
blankline_re = re.compile(r'^\s*<BLANKLINE>', re.MULTILINE)
doctestopt_re = re.compile(r'#\s*doctest:.+$', re.MULTILINE)
if PY2:
def doctest_encode(text, encoding):
# type: (str, unicode) -> unicode
if isinstance(text, text_type):
text = text.encode(encoding)
if text.startswith(codecs.BOM_UTF8):
@ -42,6 +49,7 @@ if PY2:
return text
else:
def doctest_encode(text, encoding):
# type: (unicode, unicode) -> unicode
return text
@ -58,6 +66,7 @@ class TestDirective(Directive):
final_argument_whitespace = True
def run(self):
# type: () -> List[nodes.Node]
# use ordinary docutils nodes for test code: they get special attributes
# so that our builder recognizes them, and the other builders are happy.
code = '\n'.join(self.content)
@ -92,20 +101,20 @@ class TestDirective(Directive):
option_strings = self.options['options'].replace(',', ' ').split()
for option in option_strings:
if (option[0] not in '+-' or option[1:] not in
doctest.OPTIONFLAGS_BY_NAME):
doctest.OPTIONFLAGS_BY_NAME): # type: ignore
# XXX warn?
continue
flag = doctest.OPTIONFLAGS_BY_NAME[option[1:]]
flag = doctest.OPTIONFLAGS_BY_NAME[option[1:]] # type: ignore
node['options'][flag] = (option[0] == '+')
return [node]
class TestsetupDirective(TestDirective):
option_spec = {}
option_spec = {} # type: Dict
class TestcleanupDirective(TestDirective):
option_spec = {}
option_spec = {} # type: Dict
class DoctestDirective(TestDirective):
@ -128,19 +137,21 @@ class TestoutputDirective(TestDirective):
}
parser = doctest.DocTestParser()
parser = doctest.DocTestParser() # type: ignore
# helper classes
class TestGroup(object):
def __init__(self, name):
# type: (unicode) -> None
self.name = name
self.setup = []
self.tests = []
self.cleanup = []
self.setup = [] # type: List[TestCode]
self.tests = [] # type: List[List[TestCode]]
self.cleanup = [] # type: List[TestCode]
def add_code(self, code, prepend=False):
# type: (TestCode, bool) -> None
if code.type == 'testsetup':
if prepend:
self.setup.insert(0, code)
@ -158,30 +169,34 @@ class TestGroup(object):
else:
raise RuntimeError('invalid TestCode type')
def __repr__(self):
def __repr__(self): # type: ignore
# type: () -> unicode
return 'TestGroup(name=%r, setup=%r, cleanup=%r, tests=%r)' % (
self.name, self.setup, self.cleanup, self.tests)
class TestCode(object):
def __init__(self, code, type, lineno, options=None):
# type: (unicode, unicode, int, Dict) -> None
self.code = code
self.type = type
self.lineno = lineno
self.options = options or {}
def __repr__(self):
def __repr__(self): # type: ignore
# type: () -> unicode
return 'TestCode(%r, %r, %r, options=%r)' % (
self.code, self.type, self.lineno, self.options)
class SphinxDocTestRunner(doctest.DocTestRunner):
class SphinxDocTestRunner(doctest.DocTestRunner): # type: ignore
def summarize(self, out, verbose=None):
# type: (Callable, bool) -> Tuple[int, int]
string_io = StringIO()
old_stdout = sys.stdout
sys.stdout = string_io
try:
res = doctest.DocTestRunner.summarize(self, verbose)
res = doctest.DocTestRunner.summarize(self, verbose) # type: ignore
finally:
sys.stdout = old_stdout
out(string_io.getvalue())
@ -189,6 +204,7 @@ class SphinxDocTestRunner(doctest.DocTestRunner):
def _DocTestRunner__patched_linecache_getlines(self, filename,
module_globals=None):
# type: (unicode, Any) -> Any
# this is overridden from DocTestRunner adding the try-except below
m = self._DocTestRunner__LINECACHE_FILENAME_RE.match(filename)
if m and m.group('name') == self.test.name:
@ -213,6 +229,7 @@ class DocTestBuilder(Builder):
name = 'doctest'
def init(self):
# type: () -> None
# default options
self.opt = self.config.doctest_default_flags
@ -221,7 +238,7 @@ class DocTestBuilder(Builder):
# for doctest examples but unusable for multi-statement code such
# as setup code -- to be able to use doctest error reporting with
# that code nevertheless, we monkey-patch the "compile" it uses.
doctest.compile = self.compile
doctest.compile = self.compile # type: ignore
sys.path[0:0] = self.config.doctest_path
@ -236,7 +253,8 @@ class DocTestBuilder(Builder):
date = time.strftime('%Y-%m-%d %H:%M:%S')
self.outfile = codecs.open(path.join(self.outdir, 'output.txt'),
self.outfile = None # type: IO
self.outfile = codecs.open(path.join(self.outdir, 'output.txt'), # type: ignore
'w', encoding='utf-8')
self.outfile.write('''\
Results of doctest builder run on %s
@ -244,10 +262,12 @@ Results of doctest builder run on %s
''' % (date, '='*len(date)))
def _out(self, text):
# type: (unicode) -> None
self.info(text, nonl=True)
self.outfile.write(text)
def _warn_out(self, text):
# type: (unicode) -> None
if self.app.quiet or self.app.warningiserror:
self.warn(text)
else:
@ -257,14 +277,18 @@ Results of doctest builder run on %s
self.outfile.write(text)
def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode
return ''
def get_outdated_docs(self):
# type: () -> Set[unicode]
return self.env.found_docs
def finish(self):
# type: () -> None
# write executive summary
def s(v):
# type: (int) -> unicode
return v != 1 and 's' or ''
repl = (self.total_tries, s(self.total_tries),
self.total_failures, s(self.total_failures),
@ -284,6 +308,7 @@ Doctest summary
self.app.statuscode = 1
def write(self, build_docnames, updated_docnames, method='update'):
# type: (Iterable[unicode], Sequence[unicode], unicode) -> None
if build_docnames is None:
build_docnames = sorted(self.env.all_docs)
@ -294,7 +319,8 @@ Doctest summary
self.test_doc(docname, doctree)
def test_doc(self, docname, doctree):
groups = {}
# type: (unicode, nodes.Node) -> None
groups = {} # type: Dict[unicode, TestGroup]
add_to_all_groups = []
self.setup_runner = SphinxDocTestRunner(verbose=False,
optionflags=self.opt)
@ -308,11 +334,13 @@ Doctest summary
if self.config.doctest_test_doctest_blocks:
def condition(node):
# type: (nodes.Node) -> bool
return (isinstance(node, (nodes.literal_block, nodes.comment)) and
'testnodetype' in node) or \
isinstance(node, nodes.doctest_block)
else:
def condition(node):
# type: (nodes.Node) -> bool
return isinstance(node, (nodes.literal_block, nodes.comment)) \
and 'testnodetype' in node
for node in doctree.traverse(condition):
@ -366,26 +394,29 @@ Doctest summary
self.cleanup_tries += res_t
def compile(self, code, name, type, flags, dont_inherit):
# type: (unicode, unicode, unicode, Any, bool) -> Any
return compile(code, name, self.type, flags, dont_inherit)
def test_group(self, group, filename):
# type: (TestGroup, unicode) -> None
if PY2:
filename_str = filename.encode(fs_encoding)
else:
filename_str = filename
ns = {}
ns = {} # type: Dict
def run_setup_cleanup(runner, testcodes, what):
# type: (Any, List[TestCode], Any) -> bool
examples = []
for testcode in testcodes:
examples.append(doctest.Example(
doctest_encode(testcode.code, self.env.config.source_encoding), '',
examples.append(doctest.Example( # type: ignore
doctest_encode(testcode.code, self.env.config.source_encoding), '', # type: ignore # NOQA
lineno=testcode.lineno))
if not examples:
return True
# simulate a doctest with the code
sim_doctest = doctest.DocTest(examples, {},
sim_doctest = doctest.DocTest(examples, {}, # type: ignore
'%s (%s code)' % (group.name, what),
filename_str, 0, None)
sim_doctest.globs = ns
@ -407,7 +438,7 @@ Doctest summary
# ordinary doctests (code/output interleaved)
try:
test = parser.get_doctest(
doctest_encode(code[0].code, self.env.config.source_encoding), {},
doctest_encode(code[0].code, self.env.config.source_encoding), {}, # type: ignore # NOQA
group.name, filename_str, code[0].lineno)
except Exception:
self.warn('ignoring invalid doctest code: %r' %
@ -427,19 +458,19 @@ Doctest summary
output = code[1] and code[1].code or ''
options = code[1] and code[1].options or {}
# disable <BLANKLINE> processing as it is not needed
options[doctest.DONT_ACCEPT_BLANKLINE] = True
options[doctest.DONT_ACCEPT_BLANKLINE] = True # type: ignore
# find out if we're testing an exception
m = parser._EXCEPTION_RE.match(output)
if m:
exc_msg = m.group('msg')
else:
exc_msg = None
example = doctest.Example(
doctest_encode(code[0].code, self.env.config.source_encoding), output,
example = doctest.Example( # type: ignore
doctest_encode(code[0].code, self.env.config.source_encoding), output, # type: ignore # NOQA
exc_msg=exc_msg,
lineno=code[0].lineno,
options=options)
test = doctest.DocTest([example], {}, group.name,
test = doctest.DocTest([example], {}, group.name, # type: ignore
filename_str, code[0].lineno, None)
self.type = 'exec' # multiple statements again
# DocTest.__init__ copies the globs namespace, which we don't want
@ -452,6 +483,7 @@ Doctest summary
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_directive('testsetup', TestsetupDirective)
app.add_directive('testcleanup', TestcleanupDirective)
app.add_directive('doctest', DoctestDirective)
@ -465,6 +497,6 @@ def setup(app):
app.add_config_value('doctest_global_cleanup', '', False)
app.add_config_value(
'doctest_default_flags',
doctest.DONT_ACCEPT_TRUE_FOR_1 | doctest.ELLIPSIS | doctest.IGNORE_EXCEPTION_DETAIL,
doctest.DONT_ACCEPT_TRUE_FOR_1 | doctest.ELLIPSIS | doctest.IGNORE_EXCEPTION_DETAIL, # type: ignore # NOQA
False)
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}

View File

@ -18,6 +18,7 @@ from subprocess import Popen, PIPE
from hashlib import sha1
from six import text_type
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
@ -29,6 +30,11 @@ from sphinx.util.i18n import search_image_for_language
from sphinx.util.osutil import ensuredir, ENOENT, EPIPE, EINVAL
from sphinx.util.compat import Directive
if False:
# For type annotation
from typing import Any, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
mapname_re = re.compile(r'<map id="(.*?)"')
@ -42,6 +48,7 @@ class graphviz(nodes.General, nodes.Inline, nodes.Element):
def figure_wrapper(directive, node, caption):
# type: (Directive, nodes.Node, unicode) -> nodes.figure
figure_node = nodes.figure('', node)
if 'align' in node:
figure_node['align'] = node.attributes.pop('align')
@ -58,6 +65,7 @@ def figure_wrapper(directive, node, caption):
def align_spec(argument):
# type: (Any) -> bool
return directives.choice(argument, ('left', 'center', 'right'))
@ -75,9 +83,11 @@ class Graphviz(Directive):
'inline': directives.flag,
'caption': directives.unchanged,
'graphviz_dot': directives.unchanged,
'name': directives.unchanged,
}
def run(self):
# type: () -> List[nodes.Node]
if self.arguments:
document = self.state.document
if self.content:
@ -117,6 +127,7 @@ class Graphviz(Directive):
if caption:
node = figure_wrapper(self, node, caption)
self.add_name(node)
return [node]
@ -134,9 +145,11 @@ class GraphvizSimple(Directive):
'inline': directives.flag,
'caption': directives.unchanged,
'graphviz_dot': directives.unchanged,
'name': directives.unchanged,
}
def run(self):
# type: () -> List[nodes.Node]
node = graphviz()
node['code'] = '%s %s {\n%s\n}\n' % \
(self.name, self.arguments[0], '\n'.join(self.content))
@ -154,10 +167,12 @@ class GraphvizSimple(Directive):
if caption:
node = figure_wrapper(self, node, caption)
self.add_name(node)
return [node]
def render_dot(self, code, options, format, prefix='graphviz'):
# type: (nodes.NodeVisitor, unicode, Dict, unicode, unicode) -> Tuple[unicode, unicode]
"""Render graphviz code into a PNG or PDF output file."""
graphviz_dot = options.get('graphviz_dot', self.builder.config.graphviz_dot)
hashkey = (code + str(options) + str(graphviz_dot) +
@ -217,6 +232,7 @@ def render_dot(self, code, options, format, prefix='graphviz'):
def warn_for_deprecated_option(self, node):
# type: (nodes.NodeVisitor, graphviz) -> None
if hasattr(self.builder, '_graphviz_warned_inline'):
return
@ -227,6 +243,7 @@ def warn_for_deprecated_option(self, node):
def render_dot_html(self, node, code, options, prefix='graphviz',
imgcls=None, alt=None):
# type: (nodes.NodeVisitor, graphviz, unicode, Dict, unicode, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
format = self.builder.config.graphviz_output_format
try:
if format not in ('png', 'svg'):
@ -259,7 +276,7 @@ def render_dot_html(self, node, code, options, prefix='graphviz',
(fname, alt, imgcss))
else:
# has a map: get the name of the map and connect the parts
mapname = mapname_re.match(imgmap[0].decode('utf-8')).group(1)
mapname = mapname_re.match(imgmap[0].decode('utf-8')).group(1) # type: ignore
self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' %
(fname, alt, mapname, imgcss))
self.body.extend([item.decode('utf-8') for item in imgmap])
@ -270,11 +287,13 @@ def render_dot_html(self, node, code, options, prefix='graphviz',
def html_visit_graphviz(self, node):
# type: (nodes.NodeVisitor, graphviz) -> None
warn_for_deprecated_option(self, node)
render_dot_html(self, node, node['code'], node['options'])
def render_dot_latex(self, node, code, options, prefix='graphviz'):
# type: (nodes.NodeVisitor, graphviz, unicode, Dict, unicode) -> None
try:
fname, outfn = render_dot(self, code, options, 'pdf', prefix)
except GraphvizError as exc:
@ -288,7 +307,7 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'):
para_separator = '\n'
if fname is not None:
post = None
post = None # type: unicode
if not is_inline and 'align' in node:
if node['align'] == 'left':
self.body.append('{')
@ -305,11 +324,13 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'):
def latex_visit_graphviz(self, node):
# type: (nodes.NodeVisitor, graphviz) -> None
warn_for_deprecated_option(self, node)
render_dot_latex(self, node, node['code'], node['options'])
def render_dot_texinfo(self, node, code, options, prefix='graphviz'):
# type: (nodes.NodeVisitor, graphviz, unicode, Dict, unicode) -> None
try:
fname, outfn = render_dot(self, code, options, 'png', prefix)
except GraphvizError as exc:
@ -321,11 +342,13 @@ def render_dot_texinfo(self, node, code, options, prefix='graphviz'):
def texinfo_visit_graphviz(self, node):
# type: (nodes.NodeVisitor, graphviz) -> None
warn_for_deprecated_option(self, node)
render_dot_texinfo(self, node, node['code'], node['options'])
def text_visit_graphviz(self, node):
# type: (nodes.NodeVisitor, graphviz) -> None
warn_for_deprecated_option(self, node)
if 'alt' in node.attributes:
self.add_text(_('[graph: %s]') % node['alt'])
@ -335,6 +358,7 @@ def text_visit_graphviz(self, node):
def man_visit_graphviz(self, node):
# type: (nodes.NodeVisitor, graphviz) -> None
warn_for_deprecated_option(self, node)
if 'alt' in node.attributes:
self.body.append(_('[graph: %s]') % node['alt'])
@ -344,6 +368,7 @@ def man_visit_graphviz(self, node):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_node(graphviz,
html=(html_visit_graphviz, None),
latex=(latex_visit_graphviz, None),

View File

@ -26,6 +26,11 @@ import sphinx
from sphinx.util.nodes import set_source_info
from sphinx.util.compat import Directive
if False:
# For type annotation
from typing import Any # NOQA
from sphinx.application import Sphinx # NOQA
class ifconfig(nodes.Element):
pass
@ -37,9 +42,10 @@ class IfConfig(Directive):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
node = ifconfig()
node.document = self.state.document
set_source_info(self, node)
@ -50,16 +56,17 @@ class IfConfig(Directive):
def process_ifconfig_nodes(app, doctree, docname):
# type: (Sphinx, nodes.Node, unicode) -> None
ns = dict((k, app.config[k]) for k in app.config.values)
ns.update(app.config.__dict__.copy())
ns['builder'] = app.builder.name
for node in doctree.traverse(ifconfig):
try:
res = eval(node['expr'], ns)
res = eval(node['expr'], ns) # type: ignore
except Exception as err:
# handle exceptions in a clean fashion
from traceback import format_exception_only
msg = ''.join(format_exception_only(err.__class__, err))
msg = ''.join(format_exception_only(err.__class__, err)) # type: ignore
newnode = doctree.reporter.error('Exception occured in '
'ifconfig expression: \n%s' %
msg, base_node=node)
@ -72,6 +79,7 @@ def process_ifconfig_nodes(app, doctree, docname):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_node(ifconfig)
app.add_directive('ifconfig', IfConfig)
app.connect('doctree-resolved', process_ifconfig_nodes)

View File

@ -19,6 +19,7 @@ from subprocess import Popen, PIPE
from hashlib import sha1
from six import text_type
from docutils import nodes
import sphinx
@ -29,11 +30,18 @@ from sphinx.util.osutil import ensuredir, ENOENT, cd
from sphinx.util.pycompat import sys_encoding
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
if False:
# For type annotation
from typing import Any, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.ext.mathbase import math as math_node, displaymath # NOQA
class MathExtError(SphinxError):
category = 'Math extension error'
def __init__(self, msg, stderr=None, stdout=None):
# type: (unicode, unicode, unicode) -> None
if stderr:
msg += '\n[stderr]\n' + stderr.decode(sys_encoding, 'replace')
if stdout:
@ -72,6 +80,7 @@ depth_re = re.compile(br'\[\d+ depth=(-?\d+)\]')
def render_math(self, math):
# type: (nodes.NodeVisitor, unicode) -> Tuple[unicode, int]
"""Render the LaTeX math expression *math* using latex and dvipng or
dvisvgm.
@ -116,9 +125,8 @@ def render_math(self, math):
else:
tempdir = self.builder._imgmath_tempdir
tf = codecs.open(path.join(tempdir, 'math.tex'), 'w', 'utf-8')
tf.write(latex)
tf.close()
with codecs.open(path.join(tempdir, 'math.tex'), 'w', 'utf-8') as tf: # type: ignore
tf.write(latex)
# build latex command; old versions of latex don't have the
# --output-directory option, so we have to manually chdir to the
@ -199,23 +207,26 @@ def render_math(self, math):
def cleanup_tempdir(app, exc):
# type: (Sphinx, Exception) -> None
if exc:
return
if not hasattr(app.builder, '_imgmath_tempdir'):
return
try:
shutil.rmtree(app.builder._mathpng_tempdir)
shutil.rmtree(app.builder._mathpng_tempdir) # type: ignore
except Exception:
pass
def get_tooltip(self, node):
# type: (nodes.NodeVisitor, math_node) -> unicode
if self.builder.config.imgmath_add_tooltips:
return ' alt="%s"' % self.encode(node['latex']).strip()
return ''
def html_visit_math(self, node):
# type: (nodes.NodeVisitor, math_node) -> None
try:
fname, depth = render_math(self, '$'+node['latex']+'$')
except MathExtError as exc:
@ -238,6 +249,7 @@ def html_visit_math(self, node):
def html_visit_displaymath(self, node):
# type: (nodes.NodeVisitor, displaymath) -> None
if node['nowrap']:
latex = node['latex']
else:
@ -246,10 +258,11 @@ def html_visit_displaymath(self, node):
try:
fname, depth = render_math(self, latex)
except MathExtError as exc:
sm = nodes.system_message(str(exc), type='WARNING', level=2,
msg = text_type(exc)
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
self.builder.warn('inline latex %r: ' % node['latex'] + str(exc))
self.builder.warn('inline latex %r: ' % node['latex'] + msg)
raise nodes.SkipNode
self.body.append(self.starttag(node, 'div', CLASS='math'))
self.body.append('<p>')
@ -268,6 +281,7 @@ def html_visit_displaymath(self, node):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
except ExtensionError:

View File

@ -42,10 +42,10 @@ import inspect
try:
from hashlib import md5
except ImportError:
from md5 import md5
from md5 import md5 # type: ignore
from six import text_type
from six.moves import builtins
from six.moves import builtins # type: ignore
from docutils import nodes
from docutils.parsers.rst import directives
@ -57,10 +57,70 @@ from sphinx.pycode import ModuleAnalyzer
from sphinx.util import force_decode
from sphinx.util.compat import Directive
if False:
# For type annotation
from typing import Any, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
class_sig_re = re.compile(r'''^([\w.]*\.)? # module names
(\w+) \s* $ # class/final module name
''', re.VERBOSE)
module_sig_re = re.compile(r'''^(?:([\w.]*)\.)? # module names
(\w+) \s* $ # class/final module name
''', re.VERBOSE)
def try_import(objname):
# type: (unicode) -> Any
"""Import a object or module using *name* and *currentmodule*.
*name* should be a relative name from *currentmodule* or
a fully-qualified name.
Returns imported object or module. If failed, returns None value.
"""
try:
__import__(objname)
return sys.modules.get(objname) # type: ignore
except ImportError:
modname, attrname = module_sig_re.match(objname).groups() # type: ignore
if modname is None:
return None
try:
__import__(modname)
return getattr(sys.modules.get(modname), attrname, None)
except ImportError:
return None
def import_classes(name, currmodule):
# type: (unicode, unicode) -> Any
"""Import a class using its fully-qualified *name*."""
target = None
# import class or module using currmodule
if currmodule:
target = try_import(currmodule + '.' + name)
# import class or module without currmodule
if target is None:
target = try_import(name)
if target is None:
raise InheritanceException(
'Could not import class or module %r specified for '
'inheritance diagram' % name)
if inspect.isclass(target):
# If imported object is a class, just return it
return [target]
elif inspect.ismodule(target):
# If imported object is a module, return classes defined on it
classes = []
for cls in target.__dict__.values():
if inspect.isclass(cls) and cls.__module__ == target.__name__:
classes.append(cls)
return classes
raise InheritanceException('%r specified for inheritance diagram is '
'not a class or module' % name)
class InheritanceException(Exception):
@ -75,6 +135,7 @@ class InheritanceGraph(object):
"""
def __init__(self, class_names, currmodule, show_builtins=False,
private_bases=False, parts=0):
# type: (unicode, str, bool, bool, int) -> None
"""*class_names* is a list of child classes to show bases from.
If *show_builtins* is True, then Python builtins will be shown
@ -88,59 +149,16 @@ class InheritanceGraph(object):
raise InheritanceException('No classes found for '
'inheritance diagram')
def _import_class_or_module(self, name, currmodule):
"""Import a class using its fully-qualified *name*."""
try:
path, base = class_sig_re.match(name).groups()
except (AttributeError, ValueError):
raise InheritanceException('Invalid class or module %r specified '
'for inheritance diagram' % name)
fullname = (path or '') + base
path = (path and path.rstrip('.') or '')
# two possibilities: either it is a module, then import it
try:
__import__(fullname)
todoc = sys.modules[fullname]
except ImportError:
# else it is a class, then import the module
if not path:
if currmodule:
# try the current module
path = currmodule
else:
raise InheritanceException(
'Could not import class %r specified for '
'inheritance diagram' % base)
try:
__import__(path)
todoc = getattr(sys.modules[path], base)
except (ImportError, AttributeError):
raise InheritanceException(
'Could not import class or module %r specified for '
'inheritance diagram' % (path + '.' + base))
# If a class, just return it
if inspect.isclass(todoc):
return [todoc]
elif inspect.ismodule(todoc):
classes = []
for cls in todoc.__dict__.values():
if inspect.isclass(cls) and cls.__module__ == todoc.__name__:
classes.append(cls)
return classes
raise InheritanceException('%r specified for inheritance diagram is '
'not a class or module' % name)
def _import_classes(self, class_names, currmodule):
# type: (unicode, str) -> List[Any]
"""Import a list of classes."""
classes = []
classes = [] # type: List[Any]
for name in class_names:
classes.extend(self._import_class_or_module(name, currmodule))
classes.extend(import_classes(name, currmodule))
return classes
def _class_info(self, classes, show_builtins, private_bases, parts):
# type: (List[Any], bool, bool, int) -> List[Tuple[unicode, unicode, List[unicode], unicode]] # NOQA
"""Return name and bases for all classes that are ancestors of
*classes*.
@ -151,6 +169,7 @@ class InheritanceGraph(object):
py_builtins = vars(builtins).values()
def recurse(cls):
# type: (Any) -> None
if not show_builtins and cls in py_builtins:
return
if not private_bases and cls.__name__.startswith('_'):
@ -172,7 +191,7 @@ class InheritanceGraph(object):
except Exception: # might raise AttributeError for strange classes
pass
baselist = []
baselist = [] # type: List[unicode]
all_classes[cls] = (nodename, fullname, baselist, tooltip)
for base in cls.__bases__:
if not show_builtins and base in py_builtins:
@ -189,6 +208,7 @@ class InheritanceGraph(object):
return list(all_classes.values())
def class_name(self, cls, parts=0):
# type: (Any, int) -> unicode
"""Given a class object, return a fully-qualified name.
This works for things I've tested in matplotlib so far, but may not be
@ -205,8 +225,9 @@ class InheritanceGraph(object):
return '.'.join(name_parts[-parts:])
def get_all_class_names(self):
# type: () -> List[unicode]
"""Get all of the class names involved in the graph."""
return [fullname for (_, fullname, _, _) in self.class_info]
return [fullname for (_, fullname, _, _) in self.class_info] # type: ignore
# These are the default attrs for graphviz
default_graph_attrs = {
@ -227,13 +248,16 @@ class InheritanceGraph(object):
}
def _format_node_attrs(self, attrs):
# type: (Dict) -> unicode
return ','.join(['%s=%s' % x for x in sorted(attrs.items())])
def _format_graph_attrs(self, attrs):
# type: (Dict) -> unicode
return ''.join(['%s=%s;\n' % x for x in sorted(attrs.items())])
def generate_dot(self, name, urls={}, env=None,
graph_attrs={}, node_attrs={}, edge_attrs={}):
# type: (unicode, Dict, BuildEnvironment, Dict, Dict, Dict) -> unicode
"""Generate a graphviz dot graph from the classes that were passed in
to __init__.
@ -255,7 +279,7 @@ class InheritanceGraph(object):
n_attrs.update(env.config.inheritance_node_attrs)
e_attrs.update(env.config.inheritance_edge_attrs)
res = []
res = [] # type: List[unicode]
res.append('digraph %s {\n' % name)
res.append(self._format_graph_attrs(g_attrs))
@ -301,6 +325,7 @@ class InheritanceDiagram(Directive):
}
def run(self):
# type: () -> List[nodes.Node]
node = inheritance_diagram()
node.document = self.state.document
env = self.state.document.settings.env
@ -340,11 +365,13 @@ class InheritanceDiagram(Directive):
def get_graph_hash(node):
# type: (inheritance_diagram) -> unicode
encoded = (node['content'] + str(node['parts'])).encode('utf-8')
return md5(encoded).hexdigest()[-10:]
def html_visit_inheritance_diagram(self, node):
# type: (nodes.NodeVisitor, inheritance_diagram) -> None
"""
Output the graph for HTML. This will insert a PNG with clickable
image map.
@ -377,6 +404,7 @@ def html_visit_inheritance_diagram(self, node):
def latex_visit_inheritance_diagram(self, node):
# type: (nodes.NodeVisitor, inheritance_diagram) -> None
"""
Output the graph for LaTeX. This will insert a PDF.
"""
@ -392,6 +420,7 @@ def latex_visit_inheritance_diagram(self, node):
def texinfo_visit_inheritance_diagram(self, node):
# type: (nodes.NodeVisitor, inheritance_diagram) -> None
"""
Output the graph for Texinfo. This will insert a PNG.
"""
@ -407,10 +436,12 @@ def texinfo_visit_inheritance_diagram(self, node):
def skip(self, node):
# type: (nodes.NodeVisitor, inheritance_diagram) -> None
raise nodes.SkipNode
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.setup_extension('sphinx.ext.graphviz')
app.add_node(
inheritance_diagram,
@ -420,7 +451,7 @@ def setup(app):
man=(skip, None),
texinfo=(texinfo_visit_inheritance_diagram, None))
app.add_directive('inheritance-diagram', InheritanceDiagram)
app.add_config_value('inheritance_graph_attrs', {}, False),
app.add_config_value('inheritance_node_attrs', {}, False),
app.add_config_value('inheritance_edge_attrs', {}, False),
app.add_config_value('inheritance_graph_attrs', {}, False)
app.add_config_value('inheritance_node_attrs', {}, False)
app.add_config_value('inheritance_edge_attrs', {}, False)
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}

View File

@ -33,23 +33,37 @@ import posixpath
from os import path
import re
from six import iteritems, string_types
from six import PY3, iteritems, string_types
from six.moves.urllib.parse import urlsplit, urlunsplit
from docutils import nodes
from docutils.utils import relative_path
import sphinx
from sphinx.locale import _
from sphinx.builders.html import INVENTORY_FILENAME
from sphinx.util.requests import requests, useragent_header
from sphinx.util import requests
if False:
# For type annotation
from typing import Any, Callable, Dict, IO, Iterator, Tuple, Union # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
from sphinx.environment import BuildEnvironment # NOQA
if PY3:
unicode = str
Inventory = Dict[unicode, Dict[unicode, Tuple[unicode, unicode, unicode, unicode]]]
UTF8StreamReader = codecs.lookup('utf-8')[2]
def read_inventory_v1(f, uri, join):
# type: (IO, unicode, Callable) -> Inventory
f = UTF8StreamReader(f)
invdata = {}
invdata = {} # type: Inventory
line = next(f)
projname = line.rstrip()[11:]
line = next(f)
@ -69,7 +83,8 @@ def read_inventory_v1(f, uri, join):
def read_inventory_v2(f, uri, join, bufsize=16*1024):
invdata = {}
# type: (IO, unicode, Callable, int) -> Inventory
invdata = {} # type: Inventory
line = f.readline()
projname = line.rstrip()[11:].decode('utf-8')
line = f.readline()
@ -79,12 +94,14 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024):
raise ValueError
def read_chunks():
# type: () -> Iterator[bytes]
decompressor = zlib.decompressobj()
for chunk in iter(lambda: f.read(bufsize), b''):
yield decompressor.decompress(chunk)
yield decompressor.flush()
def split_lines(iter):
# type: (Iterator[bytes]) -> Iterator[unicode]
buf = b''
for chunk in iter:
buf += chunk
@ -117,6 +134,7 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024):
def read_inventory(f, uri, join, bufsize=16*1024):
# type: (IO, unicode, Callable, int) -> Inventory
line = f.readline().rstrip().decode('utf-8')
if line == '# Sphinx inventory version 1':
return read_inventory_v1(f, uri, join)
@ -125,6 +143,7 @@ def read_inventory(f, uri, join, bufsize=16*1024):
def _strip_basic_auth(url):
# type: (unicode) -> unicode
"""Returns *url* with basic auth credentials removed. Also returns the
basic auth username and password if they're present in *url*.
@ -145,7 +164,8 @@ def _strip_basic_auth(url):
return urlunsplit(frags)
def _read_from_url(url, timeout=None):
def _read_from_url(url, config=None):
# type: (unicode, Config) -> IO
"""Reads data from *url* with an HTTP *GET*.
This function supports fetching from resources which use basic HTTP auth as
@ -161,13 +181,14 @@ def _read_from_url(url, timeout=None):
:return: data read from resource described by *url*
:rtype: ``file``-like object
"""
r = requests.get(url, stream=True, timeout=timeout, headers=dict(useragent_header))
r = requests.get(url, stream=True, config=config, timeout=config.intersphinx_timeout)
r.raise_for_status()
r.raw.url = r.url
return r.raw
def _get_safe_url(url):
# type: (unicode) -> unicode
"""Gets version of *url* with basic auth passwords obscured. This function
returns results suitable for printing and logging.
@ -193,6 +214,7 @@ def _get_safe_url(url):
def fetch_inventory(app, uri, inv):
# type: (Sphinx, unicode, Any) -> Any
"""Fetch, parse and return an intersphinx inventory file."""
# both *uri* (base URI of the links to generate) and *inv* (actual
# location of the inventory file) can be local or remote URIs
@ -202,7 +224,7 @@ def fetch_inventory(app, uri, inv):
uri = _strip_basic_auth(uri)
try:
if '://' in inv:
f = _read_from_url(inv, timeout=app.config.intersphinx_timeout)
f = _read_from_url(inv, config=app.config)
else:
f = open(path.join(app.srcdir, inv), 'rb')
except Exception as err:
@ -211,7 +233,7 @@ def fetch_inventory(app, uri, inv):
return
try:
if hasattr(f, 'url'):
newinv = f.url
newinv = f.url # type: ignore
if inv != newinv:
app.info('intersphinx inventory has moved: %s -> %s' % (inv, newinv))
@ -231,17 +253,22 @@ def fetch_inventory(app, uri, inv):
def load_mappings(app):
# type: (Sphinx) -> None
"""Load all intersphinx mappings into the environment."""
now = int(time.time())
cache_time = now - app.config.intersphinx_cache_limit * 86400
env = app.builder.env
if not hasattr(env, 'intersphinx_cache'):
env.intersphinx_cache = {}
env.intersphinx_inventory = {}
env.intersphinx_named_inventory = {}
cache = env.intersphinx_cache
env.intersphinx_cache = {} # type: ignore
env.intersphinx_inventory = {} # type: ignore
env.intersphinx_named_inventory = {} # type: ignore
cache = env.intersphinx_cache # type: ignore
update = False
for key, value in iteritems(app.config.intersphinx_mapping):
name = None # type: unicode
uri = None # type: unicode
inv = None # type: Union[unicode, Tuple[unicode, ...]]
if isinstance(value, tuple):
# new format
name, (uri, inv) = key, value
@ -257,7 +284,7 @@ def load_mappings(app):
if not isinstance(inv, tuple):
invs = (inv, )
else:
invs = inv
invs = inv # type: ignore
for inv in invs:
if not inv:
@ -266,7 +293,7 @@ def load_mappings(app):
# files; remote ones only if the cache time is expired
if '://' not in inv or uri not in cache \
or cache[uri][1] < cache_time:
safe_inv_url = _get_safe_url(inv)
safe_inv_url = _get_safe_url(inv) # type: ignore
app.info(
'loading intersphinx inventory from %s...' % safe_inv_url)
invdata = fetch_inventory(app, uri, inv)
@ -276,8 +303,8 @@ def load_mappings(app):
break
if update:
env.intersphinx_inventory = {}
env.intersphinx_named_inventory = {}
env.intersphinx_inventory = {} # type: ignore
env.intersphinx_named_inventory = {} # type: ignore
# Duplicate values in different inventories will shadow each
# other; which one will override which can vary between builds
# since they are specified using an unordered dict. To make
@ -290,15 +317,17 @@ def load_mappings(app):
unnamed_vals = [v for v in cached_vals if not v[0]]
for name, _x, invdata in named_vals + unnamed_vals:
if name:
env.intersphinx_named_inventory[name] = invdata
env.intersphinx_named_inventory[name] = invdata # type: ignore
for type, objects in iteritems(invdata):
env.intersphinx_inventory.setdefault(
env.intersphinx_inventory.setdefault( # type: ignore
type, {}).update(objects)
def missing_reference(app, env, node, contnode):
# type: (Sphinx, BuildEnvironment, nodes.Node, nodes.Node) -> None
"""Attempt to resolve a missing reference via intersphinx references."""
target = node['reftarget']
objtypes = None # type: List[unicode]
if node['reftype'] == 'any':
# we search anything!
objtypes = ['%s:%s' % (domain.name, objtype)
@ -313,18 +342,18 @@ def missing_reference(app, env, node, contnode):
if not domain:
# only objects in domains are in the inventory
return
objtypes = env.domains[domain].objtypes_for_role(node['reftype'])
objtypes = env.get_domain(domain).objtypes_for_role(node['reftype'])
if not objtypes:
return
objtypes = ['%s:%s' % (domain, objtype) for objtype in objtypes]
to_try = [(env.intersphinx_inventory, target)]
to_try = [(env.intersphinx_inventory, target)] # type: ignore
in_set = None
if ':' in target:
# first part may be the foreign doc set name
setname, newtarget = target.split(':', 1)
if setname in env.intersphinx_named_inventory:
if setname in env.intersphinx_named_inventory: # type: ignore
in_set = setname
to_try.append((env.intersphinx_named_inventory[setname], newtarget))
to_try.append((env.intersphinx_named_inventory[setname], newtarget)) # type: ignore # NOQA
for inventory, target in to_try:
for objtype in objtypes:
if objtype not in inventory or target not in inventory[objtype]:
@ -358,6 +387,7 @@ def missing_reference(app, env, node, contnode):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_config_value('intersphinx_mapping', {}, True)
app.add_config_value('intersphinx_cache_limit', 5, False)
app.add_config_value('intersphinx_timeout', None, False)
@ -377,7 +407,7 @@ if __name__ == '__main__':
print(msg, file=sys.stderr)
filename = sys.argv[1]
invdata = fetch_inventory(MockApp(), '', filename)
invdata = fetch_inventory(MockApp(), '', filename) # type: ignore
for key in sorted(invdata or {}):
print(key)
for entry, einfo in sorted(invdata[key].items()):

View File

@ -16,12 +16,18 @@ from sphinx import addnodes
from sphinx.locale import _
from sphinx.errors import SphinxError
if False:
# For type annotation
from typing import Any # NOQA
from sphinx.application import Sphinx # NOQA
class LinkcodeError(SphinxError):
category = "linkcode error"
def doctree_read(app, doctree):
# type: (Sphinx, nodes.Node) -> None
env = app.builder.env
resolve_target = getattr(env.config, 'linkcode_resolve', None)
@ -38,7 +44,7 @@ def doctree_read(app, doctree):
for objnode in doctree.traverse(addnodes.desc):
domain = objnode.get('domain')
uris = set()
uris = set() # type: Set[unicode]
for signode in objnode:
if not isinstance(signode, addnodes.desc_signature):
continue
@ -72,6 +78,7 @@ def doctree_read(app, doctree):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.connect('doctree-read', doctree_read)
app.add_config_value('linkcode_resolve', None, '')
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}

View File

@ -18,6 +18,14 @@ from sphinx.domains import Domain
from sphinx.util.nodes import make_refnode, set_source_info
from sphinx.util.compat import Directive
if False:
# For type annotation
from typing import Any, Callable, Iterable, Tuple # NOQA
from docutils.parsers.rst.states import Inliner # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
class math(nodes.Inline, nodes.TextElement):
pass
@ -33,6 +41,7 @@ class eqref(nodes.Inline, nodes.TextElement):
class EqXRefRole(XRefRole):
def result_nodes(self, document, env, node, is_ref):
# type: (nodes.Node, BuildEnvironment, nodes.Node, bool) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
node['refdomain'] = 'math'
return [node], []
@ -44,22 +53,25 @@ class MathDomain(Domain):
initial_data = {
'objects': {}, # labelid -> (docname, eqno)
}
} # type: Dict[unicode, Dict[unicode, Tuple[unicode, int]]]
dangling_warnings = {
'eq': 'equation not found: %(target)s',
}
def clear_doc(self, docname):
# type: (unicode) -> None
for labelid, (doc, eqno) in list(self.data['objects'].items()):
if doc == docname:
del self.data['objects'][labelid]
def merge_domaindata(self, docnames, otherdata):
# type: (Iterable[unicode], Dict) -> None
for labelid, (doc, eqno) in otherdata['objects'].items():
if doc in docnames:
self.data['objects'][labelid] = doc
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
assert typ == 'eq'
docname, number = self.data['objects'].get(target, (None, None))
if docname:
@ -76,6 +88,7 @@ class MathDomain(Domain):
return None
def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode):
# type: (BuildEnvironment, unicode, Builder, unicode, nodes.Node, nodes.Node) -> List[nodes.Node] # NOQA
refnode = self.resolve_xref(env, fromdocname, builder, 'eq', target, node, contnode)
if refnode is None:
return []
@ -83,9 +96,11 @@ class MathDomain(Domain):
return [refnode]
def get_objects(self):
# type: () -> List
return []
def add_equation(self, env, docname, labelid):
# type: (BuildEnvironment, unicode, unicode) -> int
equations = self.data['objects']
if labelid in equations:
path = env.doc2path(equations[labelid][0])
@ -97,12 +112,15 @@ class MathDomain(Domain):
return eqno
def get_next_equation_number(self, docname):
# type: (unicode) -> int
targets = [eq for eq in self.data['objects'].values() if eq[0] == docname]
return len(targets) + 1
def wrap_displaymath(math, label, numbering):
# type: (unicode, unicode, bool) -> unicode
def is_equation(part):
# type: (unicode) -> unicode
return part.strip()
if label is None:
@ -137,11 +155,13 @@ def wrap_displaymath(math, label, numbering):
def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
# type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
latex = utils.unescape(text, restore_backslashes=True)
return [math(latex=latex)], []
def is_in_section_title(node):
# type: (nodes.Node) -> bool
"""Determine whether the node is in a section title"""
from sphinx.util.nodes import traverse_parent
@ -165,6 +185,7 @@ class MathDirective(Directive):
}
def run(self):
# type: () -> List[nodes.Node]
latex = '\n'.join(self.content)
if self.arguments and self.arguments[0]:
latex = self.arguments[0] + '\n\n' + latex
@ -186,6 +207,7 @@ class MathDirective(Directive):
return ret
def add_target(self, ret):
# type: (List[nodes.Node]) -> None
node = ret[0]
env = self.state.document.settings.env
@ -209,10 +231,11 @@ class MathDirective(Directive):
self.state.document.note_explicit_target(target)
ret.insert(0, target)
except UserWarning as exc:
self.state_machine.reporter.warning(exc[0], line=self.lineno)
self.state_machine.reporter.warning(exc.args[0], line=self.lineno)
def latex_visit_math(self, node):
# type: (nodes.NodeVisitor, math) -> None
if is_in_section_title(node):
protect = r'\protect'
else:
@ -223,6 +246,7 @@ def latex_visit_math(self, node):
def latex_visit_displaymath(self, node):
# type: (nodes.NodeVisitor, displaymath) -> None
if not node['label']:
label = None
else:
@ -239,17 +263,20 @@ def latex_visit_displaymath(self, node):
def latex_visit_eqref(self, node):
# type: (nodes.NodeVisitor, eqref) -> None
label = "equation:%s:%s" % (node['docname'], node['target'])
self.body.append('\\eqref{%s}' % label)
raise nodes.SkipNode
def text_visit_math(self, node):
# type: (nodes.NodeVisitor, math) -> None
self.add_text(node['latex'])
raise nodes.SkipNode
def text_visit_displaymath(self, node):
# type: (nodes.NodeVisitor, displaymath) -> None
self.new_state()
self.add_text(node['latex'])
self.end_state()
@ -257,24 +284,29 @@ def text_visit_displaymath(self, node):
def man_visit_math(self, node):
# type: (nodes.NodeVisitor, math) -> None
self.body.append(node['latex'])
raise nodes.SkipNode
def man_visit_displaymath(self, node):
# type: (nodes.NodeVisitor, displaymath) -> None
self.visit_centered(node)
def man_depart_displaymath(self, node):
# type: (nodes.NodeVisitor, displaymath) -> None
self.depart_centered(node)
def texinfo_visit_math(self, node):
# type: (nodes.NodeVisitor, math) -> None
self.body.append('@math{' + self.escape_arg(node['latex']) + '}')
raise nodes.SkipNode
def texinfo_visit_displaymath(self, node):
# type: (nodes.NodeVisitor, displaymath) -> None
if node.get('label'):
self.add_anchor(node['label'], node)
self.body.append('\n\n@example\n%s\n@end example\n\n' %
@ -282,10 +314,12 @@ def texinfo_visit_displaymath(self, node):
def texinfo_depart_displaymath(self, node):
# type: (nodes.NodeVisitor, displaymath) -> None
pass
def setup_math(app, htmlinlinevisitors, htmldisplayvisitors):
# type: (Sphinx, Tuple[Callable, Any], Tuple[Callable, Any]) -> None
app.add_config_value('math_number_all', False, 'env')
app.add_domain(MathDomain)
app.add_node(math, override=True,

View File

@ -14,8 +14,13 @@ import sys
from six import PY2, iteritems
import sphinx
from sphinx.application import Sphinx
from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring
if False:
# For type annotation
from typing import Any # NOQA
class Config(object):
"""Sphinx napoleon extension settings in `conf.py`.
@ -254,6 +259,7 @@ class Config(object):
}
def __init__(self, **settings):
# type: (Any) -> None
for name, (default, rebuild) in iteritems(self._config_values):
setattr(self, name, default)
for name, value in iteritems(settings):
@ -261,6 +267,7 @@ class Config(object):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
"""Sphinx extension setup function.
When the extension is loaded, Sphinx imports this module and executes
@ -282,9 +289,9 @@ def setup(app):
`The Extension API <http://sphinx-doc.org/extdev/appapi.html>`_
"""
from sphinx.application import Sphinx
if not isinstance(app, Sphinx):
return # probably called by tests
return # type: ignore
# probably called by tests
_patch_python_domain()
@ -297,13 +304,14 @@ def setup(app):
def _patch_python_domain():
# type: () -> None
try:
from sphinx.domains.python import PyTypedField
except ImportError:
pass
else:
import sphinx.domains.python
import sphinx.locale
import sphinx.locale # type: ignore
l_ = sphinx.locale.lazy_gettext
for doc_field in sphinx.domains.python.PyObject.doc_field_types:
if doc_field.name == 'parameter':
@ -317,6 +325,7 @@ def _patch_python_domain():
def _process_docstring(app, what, name, obj, options, lines):
# type: (Sphinx, unicode, unicode, Any, Any, List[unicode]) -> None
"""Process the docstring for a given python object.
Called when autodoc has read and processed a docstring. `lines` is a list
@ -353,6 +362,7 @@ def _process_docstring(app, what, name, obj, options, lines):
"""
result_lines = lines
docstring = None # type: GoogleDocstring
if app.config.napoleon_numpy_docstring:
docstring = NumpyDocstring(result_lines, app.config, app, what, name,
obj, options)
@ -365,6 +375,7 @@ def _process_docstring(app, what, name, obj, options, lines):
def _skip_member(app, what, name, obj, skip, options):
# type: (Sphinx, unicode, unicode, Any, bool, Any) -> bool
"""Determine if private and special class members are included in docs.
The following settings in conf.py determine if private and special class
@ -453,4 +464,4 @@ def _skip_member(app, what, name, obj, skip, options):
(is_private and inc_private) or
(is_init and inc_init)):
return False
return skip
return None

View File

@ -21,13 +21,19 @@ from six.moves import range
from sphinx.ext.napoleon.iterators import modify_iter
from sphinx.util.pycompat import UnicodeMixin
if False:
# For type annotation
from typing import Any, Callable, Tuple, Union # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config as SphinxConfig # NOQA
_directive_regex = re.compile(r'\.\. \S+::')
_google_section_regex = re.compile(r'^(\s|\w)+:\s*$')
_google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.*[^\s]+)\s*\)')
_numpy_section_regex = re.compile(r'^[=\-`:\'"~^_*+#<>]{2,}\s*$')
_single_colon_regex = re.compile(r'(?<!:):(?!:)')
_xref_regex = re.compile(r'(:\w+:\S+:`.+?`|:\S+:`.+?`|`.+?`)')
_xref_regex = re.compile(r'(:(?:[a-zA-Z0-9]+[\-_+:.])*[a-zA-Z0-9]+:`.+?`)')
_bullet_list_regex = re.compile(r'^(\*|\+|\-)(\s+\S|\s*$)')
_enumerated_list_regex = re.compile(
r'^(?P<paren>\()?'
@ -99,19 +105,20 @@ class GoogleDocstring(UnicodeMixin):
"""
def __init__(self, docstring, config=None, app=None, what='', name='',
obj=None, options=None):
# type: (Union[unicode, List[unicode]], SphinxConfig, Sphinx, unicode, unicode, Any, Any) -> None # NOQA
self._config = config
self._app = app
if not self._config:
from sphinx.ext.napoleon import Config
self._config = self._app and self._app.config or Config()
self._config = self._app and self._app.config or Config() # type: ignore
if not what:
if inspect.isclass(obj):
what = 'class'
elif inspect.ismodule(obj):
what = 'module'
elif isinstance(obj, collections.Callable):
elif isinstance(obj, collections.Callable): # type: ignore
what = 'function'
else:
what = 'object'
@ -121,14 +128,14 @@ class GoogleDocstring(UnicodeMixin):
self._obj = obj
self._opt = options
if isinstance(docstring, string_types):
docstring = docstring.splitlines()
docstring = docstring.splitlines() # type: ignore
self._lines = docstring
self._line_iter = modify_iter(docstring, modifier=lambda s: s.rstrip())
self._parsed_lines = []
self._parsed_lines = [] # type: List[unicode]
self._is_in_section = False
self._section_indent = 0
if not hasattr(self, '_directive_sections'):
self._directive_sections = []
self._directive_sections = [] # type: List[unicode]
if not hasattr(self, '_sections'):
self._sections = {
'args': self._parse_parameters_section,
@ -154,10 +161,11 @@ class GoogleDocstring(UnicodeMixin):
'warns': self._parse_warns_section,
'yield': self._parse_yields_section,
'yields': self._parse_yields_section,
}
} # type: Dict[unicode, Callable]
self._parse()
def __unicode__(self):
# type: () -> unicode
"""Return the parsed docstring in reStructuredText format.
Returns
@ -169,6 +177,7 @@ class GoogleDocstring(UnicodeMixin):
return u('\n').join(self.lines())
def lines(self):
# type: () -> List[unicode]
"""Return the parsed lines of the docstring in reStructuredText format.
Returns
@ -180,38 +189,42 @@ class GoogleDocstring(UnicodeMixin):
return self._parsed_lines
def _consume_indented_block(self, indent=1):
# type: (int) -> List[unicode]
lines = []
line = self._line_iter.peek()
while(not self._is_section_break() and
(not line or self._is_indented(line, indent))):
lines.append(next(self._line_iter))
lines.append(next(self._line_iter)) # type: ignore
line = self._line_iter.peek()
return lines
def _consume_contiguous(self):
# type: () -> List[unicode]
lines = []
while (self._line_iter.has_next() and
self._line_iter.peek() and
not self._is_section_header()):
lines.append(next(self._line_iter))
lines.append(next(self._line_iter)) # type: ignore
return lines
def _consume_empty(self):
# type: () -> List[unicode]
lines = []
line = self._line_iter.peek()
while self._line_iter.has_next() and not line:
lines.append(next(self._line_iter))
lines.append(next(self._line_iter)) # type: ignore
line = self._line_iter.peek()
return lines
def _consume_field(self, parse_type=True, prefer_type=False):
line = next(self._line_iter)
# type: (bool, bool) -> Tuple[unicode, unicode, List[unicode]]
line = next(self._line_iter) # type: ignore
before, colon, after = self._partition_field_on_colon(line)
_name, _type, _desc = before, '', after
_name, _type, _desc = before, '', after # type: unicode, unicode, unicode
if parse_type:
match = _google_typed_arg_regex.match(before)
match = _google_typed_arg_regex.match(before) # type: ignore
if match:
_name = match.group(1)
_type = match.group(2)
@ -221,11 +234,12 @@ class GoogleDocstring(UnicodeMixin):
if prefer_type and not _type:
_type, _name = _name, _type
indent = self._get_indent(line) + 1
_desc = [_desc] + self._dedent(self._consume_indented_block(indent))
_desc = [_desc] + self._dedent(self._consume_indented_block(indent)) # type: ignore
_desc = self.__class__(_desc, self._config).lines()
return _name, _type, _desc
return _name, _type, _desc # type: ignore
def _consume_fields(self, parse_type=True, prefer_type=False):
# type: (bool, bool) -> List[Tuple[unicode, unicode, List[unicode]]]
self._consume_empty()
fields = []
while not self._is_section_break():
@ -235,19 +249,21 @@ class GoogleDocstring(UnicodeMixin):
return fields
def _consume_inline_attribute(self):
line = next(self._line_iter)
# type: () -> Tuple[unicode, List[unicode]]
line = next(self._line_iter) # type: ignore
_type, colon, _desc = self._partition_field_on_colon(line)
if not colon:
_type, _desc = _desc, _type
_desc = [_desc] + self._dedent(self._consume_to_end())
_desc = [_desc] + self._dedent(self._consume_to_end()) # type: ignore
_desc = self.__class__(_desc, self._config).lines()
return _type, _desc
return _type, _desc # type: ignore
def _consume_returns_section(self):
# type: () -> List[Tuple[unicode, unicode, List[unicode]]]
lines = self._dedent(self._consume_to_next_section())
if lines:
before, colon, after = self._partition_field_on_colon(lines[0])
_name, _type, _desc = '', '', lines
_name, _type, _desc = '', '', lines # type: unicode, unicode, List[unicode]
if colon:
if after:
@ -263,30 +279,35 @@ class GoogleDocstring(UnicodeMixin):
return []
def _consume_usage_section(self):
# type: () -> List[unicode]
lines = self._dedent(self._consume_to_next_section())
return lines
def _consume_section_header(self):
section = next(self._line_iter)
# type: () -> unicode
section = next(self._line_iter) # type: ignore
stripped_section = section.strip(':')
if stripped_section.lower() in self._sections:
section = stripped_section
return section
def _consume_to_end(self):
# type: () -> List[unicode]
lines = []
while self._line_iter.has_next():
lines.append(next(self._line_iter))
lines.append(next(self._line_iter)) # type: ignore
return lines
def _consume_to_next_section(self):
# type: () -> List[unicode]
self._consume_empty()
lines = []
while not self._is_section_break():
lines.append(next(self._line_iter))
lines.append(next(self._line_iter)) # type: ignore
return lines + self._consume_empty()
def _dedent(self, lines, full=False):
# type: (List[unicode], bool) -> List[unicode]
if full:
return [line.lstrip() for line in lines]
else:
@ -294,6 +315,7 @@ class GoogleDocstring(UnicodeMixin):
return [line[min_indent:] for line in lines]
def _escape_args_and_kwargs(self, name):
# type: (unicode) -> unicode
if name[:2] == '**':
return r'\*\*' + name[2:]
elif name[:1] == '*':
@ -302,29 +324,32 @@ class GoogleDocstring(UnicodeMixin):
return name
def _fix_field_desc(self, desc):
# type: (List[unicode]) -> List[unicode]
if self._is_list(desc):
desc = [''] + desc
desc = [''] + desc # type: ignore
elif desc[0].endswith('::'):
desc_block = desc[1:]
indent = self._get_indent(desc[0])
block_indent = self._get_initial_indent(desc_block)
if block_indent > indent:
desc = [''] + desc
desc = [''] + desc # type: ignore
else:
desc = ['', desc[0]] + self._indent(desc_block, 4)
return desc
def _format_admonition(self, admonition, lines):
# type: (unicode, List[unicode]) -> List[unicode]
lines = self._strip_empty(lines)
if len(lines) == 1:
return ['.. %s:: %s' % (admonition, lines[0].strip()), '']
elif lines:
lines = self._indent(self._dedent(lines), 3)
return ['.. %s::' % admonition, ''] + lines + ['']
return ['.. %s::' % admonition, ''] + lines + [''] # type: ignore
else:
return ['.. %s::' % admonition, '']
def _format_block(self, prefix, lines, padding=None):
# type: (unicode, List[unicode], unicode) -> List[unicode]
if lines:
if padding is None:
padding = ' ' * len(prefix)
@ -342,6 +367,7 @@ class GoogleDocstring(UnicodeMixin):
def _format_docutils_params(self, fields, field_role='param',
type_role='type'):
# type: (List[Tuple[unicode, unicode, List[unicode]]], unicode, unicode) -> List[unicode] # NOQA
lines = []
for _name, _type, _desc in fields:
_desc = self._strip_empty(_desc)
@ -357,13 +383,14 @@ class GoogleDocstring(UnicodeMixin):
return lines + ['']
def _format_field(self, _name, _type, _desc):
# type: (unicode, unicode, List[unicode]) -> List[unicode]
_desc = self._strip_empty(_desc)
has_desc = any(_desc)
separator = has_desc and ' -- ' or ''
if _name:
if _type:
if '`' in _type:
field = '**%s** (%s)%s' % (_name, _type, separator)
field = '**%s** (%s)%s' % (_name, _type, separator) # type: unicode
else:
field = '**%s** (*%s*)%s' % (_name, _type, separator)
else:
@ -386,10 +413,11 @@ class GoogleDocstring(UnicodeMixin):
return [field]
def _format_fields(self, field_type, fields):
# type: (unicode, List[Tuple[unicode, unicode, List[unicode]]]) -> List[unicode]
field_type = ':%s:' % field_type.strip()
padding = ' ' * len(field_type)
multi = len(fields) > 1
lines = []
lines = [] # type: List[unicode]
for _name, _type, _desc in fields:
field = self._format_field(_name, _type, _desc)
if multi:
@ -404,6 +432,7 @@ class GoogleDocstring(UnicodeMixin):
return lines
def _get_current_indent(self, peek_ahead=0):
# type: (int) -> int
line = self._line_iter.peek(peek_ahead + 1)[peek_ahead]
while line != self._line_iter.sentinel:
if line:
@ -413,18 +442,21 @@ class GoogleDocstring(UnicodeMixin):
return 0
def _get_indent(self, line):
# type: (unicode) -> int
for i, s in enumerate(line):
if not s.isspace():
return i
return len(line)
def _get_initial_indent(self, lines):
# type: (List[unicode]) -> int
for line in lines:
if line:
return self._get_indent(line)
return 0
def _get_min_indent(self, lines):
# type: (List[unicode]) -> int
min_indent = None
for line in lines:
if line:
@ -436,9 +468,11 @@ class GoogleDocstring(UnicodeMixin):
return min_indent or 0
def _indent(self, lines, n=4):
# type: (List[unicode], int) -> List[unicode]
return [(' ' * n) + line for line in lines]
def _is_indented(self, line, indent=1):
# type: (unicode, int) -> bool
for i, s in enumerate(line):
if i >= indent:
return True
@ -447,11 +481,12 @@ class GoogleDocstring(UnicodeMixin):
return False
def _is_list(self, lines):
# type: (List[unicode]) -> bool
if not lines:
return False
if _bullet_list_regex.match(lines[0]):
if _bullet_list_regex.match(lines[0]): # type: ignore
return True
if _enumerated_list_regex.match(lines[0]):
if _enumerated_list_regex.match(lines[0]): # type: ignore
return True
if len(lines) < 2 or lines[0].endswith('::'):
return False
@ -464,6 +499,7 @@ class GoogleDocstring(UnicodeMixin):
return next_indent > indent
def _is_section_header(self):
# type: () -> bool
section = self._line_iter.peek().lower()
match = _google_section_regex.match(section)
if match and section.strip(':') in self._sections:
@ -478,6 +514,7 @@ class GoogleDocstring(UnicodeMixin):
return False
def _is_section_break(self):
# type: () -> bool
line = self._line_iter.peek()
return (not self._line_iter.has_next() or
self._is_section_header() or
@ -486,6 +523,7 @@ class GoogleDocstring(UnicodeMixin):
not self._is_indented(line, self._section_indent)))
def _parse(self):
# type: () -> None
self._parsed_lines = self._consume_empty()
if self._name and (self._what == 'attribute' or self._what == 'data'):
@ -498,7 +536,7 @@ class GoogleDocstring(UnicodeMixin):
section = self._consume_section_header()
self._is_in_section = True
self._section_indent = self._get_current_indent()
if _directive_regex.match(section):
if _directive_regex.match(section): # type: ignore
lines = [section] + self._consume_to_next_section()
else:
lines = self._sections[section.lower()](section)
@ -513,42 +551,47 @@ class GoogleDocstring(UnicodeMixin):
self._parsed_lines.extend(lines)
def _parse_attribute_docstring(self):
# type: () -> List[unicode]
_type, _desc = self._consume_inline_attribute()
return self._format_field('', _type, _desc)
def _parse_attributes_section(self, section):
# type: (unicode) -> List[unicode]
lines = []
for _name, _type, _desc in self._consume_fields():
if self._config.napoleon_use_ivar:
field = ':ivar %s: ' % _name
field = ':ivar %s: ' % _name # type: unicode
lines.extend(self._format_block(field, _desc))
if _type:
lines.append(':vartype %s: %s' % (_name, _type))
else:
lines.extend(['.. attribute:: ' + _name, ''])
field = self._format_field('', _type, _desc)
lines.extend(self._indent(field, 3))
field = self._format_field('', _type, _desc) # type: ignore
lines.extend(self._indent(field, 3)) # type: ignore
lines.append('')
if self._config.napoleon_use_ivar:
lines.append('')
return lines
def _parse_examples_section(self, section):
# type: (unicode) -> List[unicode]
use_admonition = self._config.napoleon_use_admonition_for_examples
return self._parse_generic_section(section, use_admonition)
def _parse_usage_section(self, section):
header = ['.. rubric:: Usage:', '']
block = ['.. code-block:: python', '']
# type: (unicode) -> List[unicode]
header = ['.. rubric:: Usage:', ''] # type: List[unicode]
block = ['.. code-block:: python', ''] # type: List[unicode]
lines = self._consume_usage_section()
lines = self._indent(lines, 3)
return header + block + lines + ['']
def _parse_generic_section(self, section, use_admonition):
# type: (unicode, bool) -> List[unicode]
lines = self._strip_empty(self._consume_to_next_section())
lines = self._dedent(lines)
if use_admonition:
header = '.. admonition:: %s' % section
header = '.. admonition:: %s' % section # type: unicode
lines = self._indent(lines, 3)
else:
header = '.. rubric:: %s' % section
@ -558,6 +601,7 @@ class GoogleDocstring(UnicodeMixin):
return [header, '']
def _parse_keyword_arguments_section(self, section):
# type: (unicode) -> List[unicode]
fields = self._consume_fields()
if self._config.napoleon_use_keyword:
return self._format_docutils_params(
@ -568,26 +612,31 @@ class GoogleDocstring(UnicodeMixin):
return self._format_fields('Keyword Arguments', fields)
def _parse_methods_section(self, section):
lines = []
# type: (unicode) -> List[unicode]
lines = [] # type: List[unicode]
for _name, _, _desc in self._consume_fields(parse_type=False):
lines.append('.. method:: %s' % _name)
if _desc:
lines.extend([''] + self._indent(_desc, 3))
lines.extend([''] + self._indent(_desc, 3)) # type: ignore
lines.append('')
return lines
def _parse_note_section(self, section):
# type: (unicode) -> List[unicode]
lines = self._consume_to_next_section()
return self._format_admonition('note', lines)
def _parse_notes_section(self, section):
# type: (unicode) -> List[unicode]
use_admonition = self._config.napoleon_use_admonition_for_notes
return self._parse_generic_section('Notes', use_admonition)
def _parse_other_parameters_section(self, section):
# type: (unicode) -> List[unicode]
return self._format_fields('Other Parameters', self._consume_fields())
def _parse_parameters_section(self, section):
# type: (unicode) -> List[unicode]
fields = self._consume_fields()
if self._config.napoleon_use_param:
return self._format_docutils_params(fields)
@ -595,11 +644,12 @@ class GoogleDocstring(UnicodeMixin):
return self._format_fields('Parameters', fields)
def _parse_raises_section(self, section):
# type: (unicode) -> List[unicode]
fields = self._consume_fields(parse_type=False, prefer_type=True)
field_type = ':raises:'
padding = ' ' * len(field_type)
multi = len(fields) > 1
lines = []
lines = [] # type: List[unicode]
for _, _type, _desc in fields:
_desc = self._strip_empty(_desc)
has_desc = any(_desc)
@ -633,10 +683,12 @@ class GoogleDocstring(UnicodeMixin):
return lines
def _parse_references_section(self, section):
# type: (unicode) -> List[unicode]
use_admonition = self._config.napoleon_use_admonition_for_references
return self._parse_generic_section('References', use_admonition)
def _parse_returns_section(self, section):
# type: (unicode) -> List[unicode]
fields = self._consume_returns_section()
multi = len(fields) > 1
if multi:
@ -644,7 +696,7 @@ class GoogleDocstring(UnicodeMixin):
else:
use_rtype = self._config.napoleon_use_rtype
lines = []
lines = [] # type: List[unicode]
for _name, _type, _desc in fields:
if use_rtype:
field = self._format_field(_name, '', _desc)
@ -665,30 +717,36 @@ class GoogleDocstring(UnicodeMixin):
return lines
def _parse_see_also_section(self, section):
# type: (unicode) -> List[unicode]
lines = self._consume_to_next_section()
return self._format_admonition('seealso', lines)
def _parse_todo_section(self, section):
# type: (unicode) -> List[unicode]
lines = self._consume_to_next_section()
return self._format_admonition('todo', lines)
def _parse_warning_section(self, section):
# type: (unicode) -> List[unicode]
lines = self._consume_to_next_section()
return self._format_admonition('warning', lines)
def _parse_warns_section(self, section):
# type: (unicode) -> List[unicode]
return self._format_fields('Warns', self._consume_fields())
def _parse_yields_section(self, section):
# type: (unicode) -> List[unicode]
fields = self._consume_returns_section()
return self._format_fields('Yields', fields)
def _partition_field_on_colon(self, line):
# type: (unicode) -> Tuple[unicode, unicode, unicode]
before_colon = []
after_colon = []
colon = ''
found_colon = False
for i, source in enumerate(_xref_regex.split(line)):
for i, source in enumerate(_xref_regex.split(line)): # type: ignore
if found_colon:
after_colon.append(source)
else:
@ -706,6 +764,7 @@ class GoogleDocstring(UnicodeMixin):
"".join(after_colon).strip())
def _strip_empty(self, lines):
# type: (List[unicode]) -> List[unicode]
if lines:
start = -1
for i, line in enumerate(lines):
@ -820,12 +879,14 @@ class NumpyDocstring(GoogleDocstring):
"""
def __init__(self, docstring, config=None, app=None, what='', name='',
obj=None, options=None):
# type: (Union[unicode, List[unicode]], SphinxConfig, Sphinx, unicode, unicode, Any, Any) -> None # NOQA
self._directive_sections = ['.. index::']
super(NumpyDocstring, self).__init__(docstring, config, app, what,
name, obj, options)
def _consume_field(self, parse_type=True, prefer_type=False):
line = next(self._line_iter)
# type: (bool, bool) -> Tuple[unicode, unicode, List[unicode]]
line = next(self._line_iter) # type: ignore
if parse_type:
_name, _, _type = self._partition_field_on_colon(line)
else:
@ -841,16 +902,19 @@ class NumpyDocstring(GoogleDocstring):
return _name, _type, _desc
def _consume_returns_section(self):
# type: () -> List[Tuple[unicode, unicode, List[unicode]]]
return self._consume_fields(prefer_type=True)
def _consume_section_header(self):
section = next(self._line_iter)
# type: () -> unicode
section = next(self._line_iter) # type: ignore
if not _directive_regex.match(section):
# Consume the header underline
next(self._line_iter)
next(self._line_iter) # type: ignore
return section
def _is_section_break(self):
# type: () -> bool
line1, line2 = self._line_iter.peek(2)
return (not self._line_iter.has_next() or
self._is_section_header() or
@ -860,10 +924,11 @@ class NumpyDocstring(GoogleDocstring):
not self._is_indented(line1, self._section_indent)))
def _is_section_header(self):
# type: () -> bool
section, underline = self._line_iter.peek(2)
section = section.lower()
if section in self._sections and isinstance(underline, string_types):
return bool(_numpy_section_regex.match(underline))
return bool(_numpy_section_regex.match(underline)) # type: ignore
elif self._directive_sections:
if _directive_regex.match(section):
for directive_section in self._directive_sections:
@ -875,6 +940,7 @@ class NumpyDocstring(GoogleDocstring):
r" (?P<name2>[a-zA-Z0-9_.-]+))\s*", re.X)
def _parse_see_also_section(self, section):
# type: (unicode) -> List[unicode]
lines = self._consume_to_next_section()
try:
return self._parse_numpydoc_see_also_section(lines)
@ -882,6 +948,7 @@ class NumpyDocstring(GoogleDocstring):
return self._format_admonition('seealso', lines)
def _parse_numpydoc_see_also_section(self, content):
# type: (List[unicode]) -> List[unicode]
"""
Derived from the NumpyDoc implementation of _parse_see_also.
@ -914,13 +981,13 @@ class NumpyDocstring(GoogleDocstring):
del rest[:]
current_func = None
rest = []
rest = [] # type: List[unicode]
for line in content:
if not line.strip():
continue
m = self._name_rgx.match(line)
m = self._name_rgx.match(line) # type: ignore
if m and line[m.end():].strip().startswith(':'):
push_item(current_func, rest)
current_func, line = line[:m.end()], line[m.end():]
@ -960,12 +1027,12 @@ class NumpyDocstring(GoogleDocstring):
'const': 'const',
'attribute': 'attr',
'attr': 'attr'
}
} # type: Dict[unicode, unicode]
if self._what is None:
func_role = 'obj'
func_role = 'obj' # type: unicode
else:
func_role = roles.get(self._what, '')
lines = []
lines = [] # type: List[unicode]
last_had_desc = True
for func, desc, role in items:
if role:

View File

@ -13,6 +13,10 @@
import collections
if False:
# For type annotation
from typing import Any, Iterable # NOQA
class peek_iter(object):
"""An iterator object that supports peeking ahead.
@ -48,34 +52,39 @@ class peek_iter(object):
"""
def __init__(self, *args):
# type: (Any) -> None
"""__init__(o, sentinel=None)"""
self._iterable = iter(*args)
self._cache = collections.deque()
self._iterable = iter(*args) # type: Iterable
self._cache = collections.deque() # type: collections.deque
if len(args) == 2:
self.sentinel = args[1]
else:
self.sentinel = object()
def __iter__(self):
# type: () -> peek_iter
return self
def __next__(self, n=None):
# type: (int) -> Any
# note: prevent 2to3 to transform self.next() in next(self) which
# causes an infinite loop !
return getattr(self, 'next')(n)
def _fillcache(self, n):
# type: (int) -> None
"""Cache `n` items. If `n` is 0 or None, then 1 item is cached."""
if not n:
n = 1
try:
while len(self._cache) < n:
self._cache.append(next(self._iterable))
self._cache.append(next(self._iterable)) # type: ignore
except StopIteration:
while len(self._cache) < n:
self._cache.append(self.sentinel)
def has_next(self):
# type: () -> bool
"""Determine if iterator is exhausted.
Returns
@ -91,6 +100,7 @@ class peek_iter(object):
return self.peek() != self.sentinel
def next(self, n=None):
# type: (int) -> Any
"""Get the next item or `n` items of the iterator.
Parameters
@ -126,6 +136,7 @@ class peek_iter(object):
return result
def peek(self, n=None):
# type: (int) -> Any
"""Preview the next item or `n` items of the iterator.
The iterator is not advanced when peek is called.
@ -209,6 +220,7 @@ class modify_iter(peek_iter):
"""
def __init__(self, *args, **kwargs):
# type: (Any, Any) -> None
"""__init__(o, sentinel=None, modifier=lambda x: x)"""
if 'modifier' in kwargs:
self.modifier = kwargs['modifier']
@ -223,6 +235,7 @@ class modify_iter(peek_iter):
super(modify_iter, self).__init__(*args)
def _fillcache(self, n):
# type: (int) -> None
"""Cache `n` modified items. If `n` is 0 or None, 1 item is cached.
Each item returned by the iterator is passed through the
@ -233,7 +246,7 @@ class modify_iter(peek_iter):
n = 1
try:
while len(self._cache) < n:
self._cache.append(self.modifier(next(self._iterable)))
self._cache.append(self.modifier(next(self._iterable))) # type: ignore
except StopIteration:
while len(self._cache) < n:
self._cache.append(self.sentinel)

View File

@ -20,6 +20,7 @@ from subprocess import Popen, PIPE
from hashlib import sha1
from six import text_type
from docutils import nodes
import sphinx
@ -29,11 +30,18 @@ from sphinx.util.osutil import ensuredir, ENOENT, cd
from sphinx.util.pycompat import sys_encoding
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
if False:
# For type annotation
from typing import Any, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.ext.mathbase import math as math_node, displaymath # NOQA
class MathExtError(SphinxError):
category = 'Math extension error'
def __init__(self, msg, stderr=None, stdout=None):
# type: (unicode, unicode, unicode) -> None
if stderr:
msg += '\n[stderr]\n' + stderr.decode(sys_encoding, 'replace')
if stdout:
@ -71,6 +79,7 @@ depth_re = re.compile(br'\[\d+ depth=(-?\d+)\]')
def render_math(self, math):
# type: (nodes.NodeVisitor, unicode) -> Tuple[unicode, int]
"""Render the LaTeX math expression *math* using latex and dvipng.
Return the filename relative to the built document and the "depth",
@ -107,9 +116,8 @@ def render_math(self, math):
else:
tempdir = self.builder._mathpng_tempdir
tf = codecs.open(path.join(tempdir, 'math.tex'), 'w', 'utf-8')
tf.write(latex)
tf.close()
with codecs.open(path.join(tempdir, 'math.tex'), 'w', 'utf-8') as tf: # type: ignore
tf.write(latex)
# build latex command; old versions of latex don't have the
# --output-directory option, so we have to manually chdir to the
@ -171,23 +179,26 @@ def render_math(self, math):
def cleanup_tempdir(app, exc):
# type: (Sphinx, Exception) -> None
if exc:
return
if not hasattr(app.builder, '_mathpng_tempdir'):
return
try:
shutil.rmtree(app.builder._mathpng_tempdir)
shutil.rmtree(app.builder._mathpng_tempdir) # type: ignore
except Exception:
pass
def get_tooltip(self, node):
# type: (nodes.NodeVisitor, math_node) -> unicode
if self.builder.config.pngmath_add_tooltips:
return ' alt="%s"' % self.encode(node['latex']).strip()
return ''
def html_visit_math(self, node):
# type: (nodes.NodeVisitor, math_node) -> None
try:
fname, depth = render_math(self, '$'+node['latex']+'$')
except MathExtError as exc:
@ -210,6 +221,7 @@ def html_visit_math(self, node):
def html_visit_displaymath(self, node):
# type: (nodes.NodeVisitor, displaymath) -> None
if node['nowrap']:
latex = node['latex']
else:
@ -218,10 +230,11 @@ def html_visit_displaymath(self, node):
try:
fname, depth = render_math(self, latex)
except MathExtError as exc:
sm = nodes.system_message(str(exc), type='WARNING', level=2,
msg = text_type(exc)
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
self.builder.warn('inline latex %r: ' % node['latex'] + str(exc))
self.builder.warn('inline latex %r: ' % node['latex'] + msg)
raise nodes.SkipNode
self.body.append(self.starttag(node, 'div', CLASS='math'))
self.body.append('<p>')
@ -238,6 +251,7 @@ def html_visit_displaymath(self, node):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.warn('sphinx.ext.pngmath has been deprecated. Please use sphinx.ext.imgmath instead.')
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))

View File

@ -22,6 +22,12 @@ from sphinx.util.nodes import set_source_info
from docutils.parsers.rst import Directive
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
if False:
# For type annotation
from typing import Any, Iterable # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
class todo_node(nodes.Admonition, nodes.Element):
pass
@ -46,6 +52,7 @@ class Todo(BaseAdmonition):
}
def run(self):
# type: () -> List[nodes.Node]
if not self.options.get('class'):
self.options['class'] = ['admonition-todo']
@ -63,12 +70,13 @@ class Todo(BaseAdmonition):
def process_todos(app, doctree):
# type: (Sphinx, nodes.Node) -> None
# collect all todos in the environment
# this is not done in the directive itself because it some transformations
# must have already been run, e.g. substitutions
env = app.builder.env
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
env.todo_all_todos = [] # type: ignore
for node in doctree.traverse(todo_node):
app.emit('todo-defined', node)
@ -80,7 +88,7 @@ def process_todos(app, doctree):
targetnode = None
newnode = node.deepcopy()
del newnode['ids']
env.todo_all_todos.append({
env.todo_all_todos.append({ # type: ignore
'docname': env.docname,
'source': node.source or env.doc2path(env.docname),
'lineno': node.line,
@ -101,15 +109,17 @@ class TodoList(Directive):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec = {}
option_spec = {} # type: Dict
def run(self):
# type: () -> List[todolist]
# Simply insert an empty todolist node which will be replaced later
# when process_todo_nodes is called
return [todolist('')]
def process_todo_nodes(app, doctree, fromdocname):
# type: (Sphinx, nodes.Node, unicode) -> None
if not app.config['todo_include_todos']:
for node in doctree.traverse(todo_node):
node.parent.remove(node)
@ -119,7 +129,7 @@ def process_todo_nodes(app, doctree, fromdocname):
env = app.builder.env
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
env.todo_all_todos = [] # type: ignore
for node in doctree.traverse(todolist):
if not app.config['todo_include_todos']:
@ -128,7 +138,7 @@ def process_todo_nodes(app, doctree, fromdocname):
content = []
for todo_info in env.todo_all_todos:
for todo_info in env.todo_all_todos: # type: ignore
para = nodes.paragraph(classes=['todo-source'])
if app.config['todo_link_only']:
description = _('<<original entry>>')
@ -168,30 +178,35 @@ def process_todo_nodes(app, doctree, fromdocname):
def purge_todos(app, env, docname):
# type: (Sphinx, BuildEnvironment, unicode) -> None
if not hasattr(env, 'todo_all_todos'):
return
env.todo_all_todos = [todo for todo in env.todo_all_todos
env.todo_all_todos = [todo for todo in env.todo_all_todos # type: ignore
if todo['docname'] != docname]
def merge_info(app, env, docnames, other):
# type: (Sphinx, BuildEnvironment, Iterable[unicode], BuildEnvironment) -> None
if not hasattr(other, 'todo_all_todos'):
return
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
env.todo_all_todos.extend(other.todo_all_todos)
env.todo_all_todos = [] # type: ignore
env.todo_all_todos.extend(other.todo_all_todos) # type: ignore
def visit_todo_node(self, node):
# type: (nodes.NodeVisitor, todo_node) -> None
self.visit_admonition(node)
# self.visit_admonition(node, 'todo')
def depart_todo_node(self, node):
# type: (nodes.NodeVisitor, todo_node) -> None
self.depart_admonition(node)
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_event('todo-defined')
app.add_config_value('todo_include_todos', False, 'html')
app.add_config_value('todo_link_only', False, 'html')

View File

@ -12,6 +12,7 @@
import traceback
from six import iteritems, text_type
from docutils import nodes
import sphinx
@ -20,10 +21,17 @@ from sphinx.locale import _
from sphinx.pycode import ModuleAnalyzer
from sphinx.util import get_full_modname
from sphinx.util.nodes import make_refnode
from sphinx.util.console import blue
from sphinx.util.console import blue # type: ignore
if False:
# For type annotation
from typing import Any, Iterable, Iterator, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
def _get_full_modname(app, modname, attribute):
# type: (Sphinx, str, unicode) -> unicode
try:
return get_full_modname(modname, attribute)
except AttributeError:
@ -43,20 +51,21 @@ def _get_full_modname(app, modname, attribute):
def doctree_read(app, doctree):
# type: (Sphinx, nodes.Node) -> None
env = app.builder.env
if not hasattr(env, '_viewcode_modules'):
env._viewcode_modules = {}
env._viewcode_modules = {} # type: ignore
if app.builder.name == "singlehtml":
return
if app.builder.name.startswith("epub") and not env.config.viewcode_enable_epub:
return
def has_tag(modname, fullname, docname, refname):
entry = env._viewcode_modules.get(modname, None)
entry = env._viewcode_modules.get(modname, None) # type: ignore
try:
analyzer = ModuleAnalyzer.for_module(modname)
except Exception:
env._viewcode_modules[modname] = False
env._viewcode_modules[modname] = False # type: ignore
return
if not isinstance(analyzer.code, text_type):
code = analyzer.code.decode(analyzer.encoding)
@ -65,7 +74,7 @@ def doctree_read(app, doctree):
if entry is None or entry[0] != code:
analyzer.find_tags()
entry = code, analyzer.tags, {}, refname
env._viewcode_modules[modname] = entry
env._viewcode_modules[modname] = entry # type: ignore
elif entry is False:
return
_, tags, used, _ = entry
@ -76,7 +85,7 @@ def doctree_read(app, doctree):
for objnode in doctree.traverse(addnodes.desc):
if objnode.get('domain') != 'py':
continue
names = set()
names = set() # type: Set[unicode]
for signode in objnode:
if not isinstance(signode, addnodes.desc_signature):
continue
@ -106,16 +115,18 @@ def doctree_read(app, doctree):
def env_merge_info(app, env, docnames, other):
# type: (Sphinx, BuildEnvironment, Iterable[unicode], BuildEnvironment) -> None
if not hasattr(other, '_viewcode_modules'):
return
# create a _viewcode_modules dict on the main environment
if not hasattr(env, '_viewcode_modules'):
env._viewcode_modules = {}
env._viewcode_modules = {} # type: ignore
# now merge in the information from the subprocess
env._viewcode_modules.update(other._viewcode_modules)
env._viewcode_modules.update(other._viewcode_modules) # type: ignore
def missing_reference(app, env, node, contnode):
# type: (Sphinx, BuildEnvironment, nodes.Node, nodes.Node) -> nodes.Node
# resolve our "viewcode" reference nodes -- they need special treatment
if node['reftype'] == 'viewcode':
return make_refnode(app.builder, node['refdoc'], node['reftarget'],
@ -123,20 +134,21 @@ def missing_reference(app, env, node, contnode):
def collect_pages(app):
# type: (Sphinx) -> Iterator[Tuple[unicode, Dict[unicode, Any], unicode]]
env = app.builder.env
if not hasattr(env, '_viewcode_modules'):
return
highlighter = app.builder.highlighter
highlighter = app.builder.highlighter # type: ignore
urito = app.builder.get_relative_uri
modnames = set(env._viewcode_modules)
modnames = set(env._viewcode_modules) # type: ignore
# app.builder.info(' (%d module code pages)' %
# len(env._viewcode_modules), nonl=1)
for modname, entry in app.status_iterator(
iteritems(env._viewcode_modules), 'highlighting module code... ',
blue, len(env._viewcode_modules), lambda x: x[0]):
iteritems(env._viewcode_modules), 'highlighting module code... ', # type:ignore
blue, len(env._viewcode_modules), lambda x: x[0]): # type:ignore
if not entry:
continue
code, tags, used, refname = entry
@ -185,7 +197,7 @@ def collect_pages(app):
'title': modname,
'body': (_('<h1>Source code for %s</h1>') % modname +
'\n'.join(lines)),
}
} # type: Dict[unicode, Any]
yield (pagename, context, 'page.html')
if not modnames:
@ -218,6 +230,7 @@ def collect_pages(app):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_config_value('viewcode_import', True, False)
app.add_config_value('viewcode_enable_epub', False, False)
app.connect('doctree-read', doctree_read)

View File

@ -16,6 +16,7 @@ from sphinx.util.texescape import tex_hl_escape_map_new
from sphinx.ext import doctest
from pygments import highlight
from pygments.lexer import Lexer # NOQA
from pygments.lexers import PythonLexer, Python3Lexer, PythonConsoleLexer, \
CLexer, TextLexer, RstLexer
from pygments.lexers import get_lexer_by_name, guess_lexer
@ -33,7 +34,7 @@ lexers = dict(
pycon3 = PythonConsoleLexer(python3=True, stripnl=False),
rest = RstLexer(stripnl=False),
c = CLexer(stripnl=False),
)
) # type: Dict[unicode, Lexer]
for _lexer in lexers.values():
_lexer.add_filter('raiseonerror')
@ -143,7 +144,8 @@ class PygmentsBridge(object):
pass # automatic highlighting failed.
elif warn:
warn('Could not lex literal_block as "%s". '
'Highlighting skipped.' % lang)
'Highlighting skipped.' % lang,
type='misc', subtype='higlighting_failure')
else:
raise exc
hlsource = highlight(source, lexers['none'], formatter)

View File

@ -12,6 +12,7 @@ from docutils.io import FileInput
from docutils.readers import standalone
from docutils.writers import UnfilteredWriter
from six import string_types, text_type
from typing import Any, Union # NOQA
from sphinx.transforms import (
ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
@ -24,23 +25,36 @@ from sphinx.transforms.i18n import (
)
from sphinx.util import import_object, split_docinfo
if False:
# For type annotation
from typing import Any, Union # NOQA
from docutils import nodes # NOQA
from docutils.io import Input # NOQA
from docutils.parsers import Parser # NOQA
from docutils.transforms import Transform # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
class SphinxBaseReader(standalone.Reader):
"""
Add our source parsers
"""
def __init__(self, app, parsers={}, *args, **kwargs):
# type: (Sphinx, Dict[unicode, Parser], Any, Any) -> None
standalone.Reader.__init__(self, *args, **kwargs)
self.parser_map = {}
self.parser_map = {} # type: Dict[unicode, Parser]
for suffix, parser_class in parsers.items():
if isinstance(parser_class, string_types):
parser_class = import_object(parser_class, 'source parser')
parser_class = import_object(parser_class, 'source parser') # type: ignore
parser = parser_class()
if hasattr(parser, 'set_application'):
parser.set_application(app)
self.parser_map[suffix] = parser
def read(self, source, parser, settings):
# type: (Input, Parser, Dict) -> nodes.document
self.source = source
for suffix in self.parser_map:
@ -56,6 +70,7 @@ class SphinxBaseReader(standalone.Reader):
return self.document
def get_transforms(self):
# type: () -> List[Transform]
return standalone.Reader.get_transforms(self) + self.transforms
@ -84,13 +99,16 @@ class SphinxI18nReader(SphinxBaseReader):
FilterSystemMessages, RefOnlyBulletListTransform]
def __init__(self, *args, **kwargs):
# type: (Any, Any) -> None
SphinxBaseReader.__init__(self, *args, **kwargs)
self.lineno = None
self.lineno = None # type: int
def set_lineno_for_reporter(self, lineno):
# type: (int) -> None
self.lineno = lineno
def new_document(self):
# type: () -> nodes.document
document = SphinxBaseReader.new_document(self)
reporter = document.reporter
@ -105,28 +123,32 @@ class SphinxDummyWriter(UnfilteredWriter):
supported = ('html',) # needed to keep "meta" nodes
def translate(self):
# type: () -> None
pass
class SphinxFileInput(FileInput):
def __init__(self, app, env, *args, **kwds):
# type: (Sphinx, BuildEnvironment, Any, Any) -> None
self.app = app
self.env = env
kwds['error_handler'] = 'sphinx' # py3: handle error on open.
FileInput.__init__(self, *args, **kwds)
def decode(self, data):
# type: (Union[unicode, bytes]) -> unicode
if isinstance(data, text_type): # py3: `data` already decoded.
return data
return data.decode(self.encoding, 'sphinx') # py2: decoding
def read(self):
# type: () -> unicode
def get_parser_type(source_path):
for suffix in self.env.config.source_parsers:
if source_path.endswith(suffix):
parser_class = self.env.config.source_parsers[suffix]
if isinstance(parser_class, string_types):
parser_class = import_object(parser_class, 'source parser')
parser_class = import_object(parser_class, 'source parser') # type: ignore # NOQA
return parser_class.supported
else:
return ('restructuredtext',)

View File

@ -17,18 +17,28 @@ from jinja2 import FileSystemLoader, BaseLoader, TemplateNotFound, \
contextfunction
from jinja2.utils import open_if_exists
from jinja2.sandbox import SandboxedEnvironment
from typing import Any, Callable, Iterator, Tuple # NOQA
from sphinx.application import TemplateBridge
from sphinx.util.osutil import mtimes_of_files
if False:
# For type annotation
from typing import Any, Callable, Iterator, Tuple # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.themes import Theme # NOQA
def _tobool(val):
# type: (unicode) -> bool
if isinstance(val, string_types):
return val.lower() in ('true', '1', 'yes', 'on')
return val.lower() in ('true', '1', 'yes', 'on') # type: ignore
return bool(val)
def _toint(val):
# type: (unicode) -> int
try:
return int(val)
except ValueError:
@ -36,6 +46,7 @@ def _toint(val):
def _slice_index(values, slices):
# type: (List, int) -> Iterator[List]
seq = list(values)
length = 0
for value in values:
@ -57,6 +68,7 @@ def _slice_index(values, slices):
def accesskey(context, key):
# type: (Any, unicode) -> unicode
"""Helper to output each access key only once."""
if '_accesskeys' not in context:
context.vars['_accesskeys'] = {}
@ -68,12 +80,15 @@ def accesskey(context, key):
class idgen(object):
def __init__(self):
# type: () -> None
self.id = 0
def current(self):
# type: () -> int
return self.id
def __next__(self):
# type: () -> int
self.id += 1
return self.id
next = __next__ # Python 2/Jinja compatibility
@ -86,6 +101,7 @@ class SphinxFileSystemLoader(FileSystemLoader):
"""
def get_source(self, environment, template):
# type: (BuildEnvironment, unicode) -> Tuple[unicode, unicode, Callable]
for searchpath in self.searchpath:
filename = path.join(searchpath, template)
f = open_if_exists(filename)
@ -113,6 +129,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
# TemplateBridge interface
def init(self, builder, theme=None, dirs=None):
# type: (Builder, Theme, List[unicode]) -> None
# create a chain of paths to search
if theme:
# the theme's own dir and its bases' dirs
@ -155,17 +172,21 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
builder.app.translator)
def render(self, template, context):
# type: (unicode, Dict) -> None
return self.environment.get_template(template).render(context)
def render_string(self, source, context):
# type: (unicode, Dict) -> unicode
return self.environment.from_string(source).render(context)
def newest_template_mtime(self):
# type: () -> float
return max(mtimes_of_files(self.pathchain, '.html'))
# Loader interface
def get_source(self, environment, template):
# type: (BuildEnvironment, unicode) -> Tuple[unicode, unicode, Callable]
loaders = self.loaders
# exclamation mark starts search from theme
if template.startswith('!'):

View File

@ -14,6 +14,10 @@ import gettext
from six import PY3, text_type
from six.moves import UserString
if False:
# For type annotation
from typing import Any, Tuple # NOQA
class _TranslationProxy(UserString, object):
"""
@ -140,6 +144,7 @@ class _TranslationProxy(UserString, object):
def mygettext(string):
# type: (unicode) -> unicode
"""Used instead of _ when creating TranslationProxies, because _ is
not bound yet at that time.
"""
@ -147,10 +152,12 @@ def mygettext(string):
def lazy_gettext(string):
# type: (unicode) -> unicode
"""A lazy version of `gettext`."""
# if isinstance(string, _TranslationProxy):
# return string
return _TranslationProxy(mygettext, string)
return _TranslationProxy(mygettext, string) # type: ignore
l_ = lazy_gettext
@ -183,19 +190,22 @@ pairindextypes = {
'exception': l_('exception'),
'statement': l_('statement'),
'builtin': l_('built-in function'),
}
} # Dict[unicode, _TranslationProxy]
translators = {}
translators = {} # type: Dict[unicode, Any]
if PY3:
def _(message):
# type: (unicode) -> unicode
return translators['sphinx'].gettext(message)
else:
def _(message):
# type: (unicode) -> unicode
return translators['sphinx'].ugettext(message)
def init(locale_dirs, language, catalog='sphinx'):
# type: (List, unicode, unicode) -> Tuple[Any, bool]
"""Look for message catalogs in `locale_dirs` and *ensure* that there is at
least a NullTranslations catalog set in `translators`. If called multiple
times or if several ``.mo`` files are found, their contents are merged
@ -212,12 +222,12 @@ def init(locale_dirs, language, catalog='sphinx'):
# loading
for dir_ in locale_dirs:
try:
trans = gettext.translation(catalog, localedir=dir_,
languages=[language])
trans = gettext.translation(catalog, localedir=dir_, # type: ignore
languages=[language]) # type: ignore
if translator is None:
translator = trans
else:
translator._catalog.update(trans._catalog)
translator._catalog.update(trans._catalog) # type: ignore
except Exception:
# Language couldn't be found in the specified path
pass

File diff suppressed because one or more lines are too long

View File

@ -8,61 +8,42 @@ msgid ""
msgstr ""
"Project-Id-Version: Sphinx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-03-06 21:58+0900\n"
"PO-Revision-Date: 2016-03-06 13:01+0000\n"
"Last-Translator: Takayuki Shimizukawa <shimizukawa@gmail.com>\n"
"POT-Creation-Date: 2016-11-06 22:40+0900\n"
"PO-Revision-Date: 2016-11-06 13:53+0000\n"
"Last-Translator: Takeshi KOMIYA <i.tkomiya@gmail.com>\n"
"Language-Team: Bengali (http://www.transifex.com/sphinx-doc/sphinx-1/language/bn/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.2.0\n"
"Generated-By: Babel 2.3.4\n"
"Language: bn\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: sphinx/config.py:91
#: sphinx/config.py:109
#, python-format
msgid "Section %s"
msgstr ""
#: sphinx/config.py:110
#, python-format
msgid "Fig. %s"
msgstr ""
#: sphinx/config.py:92
#: sphinx/config.py:111
#, python-format
msgid "Table %s"
msgstr ""
#: sphinx/config.py:93
#: sphinx/config.py:112
#, python-format
msgid "Listing %s"
msgstr ""
#: sphinx/config.py:100
#, python-format
msgid "%s %s documentation"
msgstr ""
#: sphinx/environment.py:1829
#, python-format
msgid "see %s"
msgstr ""
#: sphinx/environment.py:1833
#, python-format
msgid "see also %s"
msgstr ""
#: sphinx/environment.py:1893
msgid "Symbols"
msgstr ""
#: sphinx/roles.py:193
#: sphinx/roles.py:187
#, python-format
msgid "Python Enhancement Proposals; PEP %s"
msgstr "পাইথন উন্নয়ন পরামর্শ; PEP %s"
#: sphinx/transforms.py:56 sphinx/writers/latex.py:374
#: sphinx/writers/manpage.py:101 sphinx/writers/texinfo.py:222
msgid "MMMM dd, YYYY"
msgstr ""
#: sphinx/builders/changes.py:75
msgid "Builtins"
msgstr "বিল্টইন সমূহ"
@ -71,8 +52,11 @@ msgstr "বিল্টইন সমূহ"
msgid "Module level"
msgstr "মডিউল লেভেল"
#: sphinx/builders/html.py:295
msgid "MMM dd, YYYY"
#: sphinx/builders/html.py:294 sphinx/transforms/__init__.py:46
#: sphinx/writers/latex.py:393 sphinx/writers/manpage.py:100
#: sphinx/writers/texinfo.py:221
#, python-format
msgid "%b %d, %Y"
msgstr ""
#: sphinx/builders/html.py:315 sphinx/themes/basic/defindex.html:30
@ -83,18 +67,28 @@ msgstr "সাধারণ ইনডেক্স"
msgid "index"
msgstr "ইনডেক্স"
#: sphinx/builders/html.py:376
#: sphinx/builders/html.py:377
msgid "next"
msgstr "পরবর্তী"
#: sphinx/builders/html.py:385
#: sphinx/builders/html.py:386
msgid "previous"
msgstr "পূর্ববর্তী"
#: sphinx/builders/latex.py:180 sphinx/builders/texinfo.py:199
#: sphinx/builders/html.py:1222
#, python-format
msgid "%s %s documentation"
msgstr ""
#: sphinx/builders/latex.py:177 sphinx/builders/texinfo.py:199
msgid " (in "
msgstr "(-"
#: sphinx/directives/code.py:140 sphinx/directives/code.py:370
#, python-format
msgid "Invalid caption: %s"
msgstr ""
#: sphinx/directives/other.py:149
msgid "Section author: "
msgstr "অনুচ্ছেদ লেখক:"
@ -111,23 +105,23 @@ msgstr ""
msgid "Author: "
msgstr "লেখক:"
#: sphinx/domains/__init__.py:275
#: sphinx/domains/__init__.py:277
#, python-format
msgid "%s %s"
msgstr ""
#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:3605
#: sphinx/domains/python.py:124
#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:4051
#: sphinx/domains/python.py:149
msgid "Parameters"
msgstr "প্যারামিটার"
#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:3614
#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:136
#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:4060
#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:161
msgid "Returns"
msgstr "রিটার্নস"
#: sphinx/domains/c.py:63 sphinx/domains/javascript.py:130
#: sphinx/domains/python.py:138
#: sphinx/domains/python.py:163
msgid "Return type"
msgstr "রিটার্ন টাইপ"
@ -156,12 +150,12 @@ msgstr "%s (C টাইপ)"
msgid "%s (C variable)"
msgstr "%s (C ভ্যারিয়েবল)"
#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:3953
#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:589
#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:4418
#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:614
msgid "function"
msgstr "ফাংশন"
#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:3954
#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:4419
msgid "member"
msgstr ""
@ -169,7 +163,7 @@ msgstr ""
msgid "macro"
msgstr ""
#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:3955
#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:4420
msgid "type"
msgstr ""
@ -177,63 +171,72 @@ msgstr ""
msgid "variable"
msgstr ""
#: sphinx/domains/cpp.py:3608
#: sphinx/domains/cpp.py:4054
msgid "Template Parameters"
msgstr ""
#: sphinx/domains/cpp.py:3611 sphinx/domains/javascript.py:125
#: sphinx/domains/cpp.py:4057 sphinx/domains/javascript.py:125
msgid "Throws"
msgstr ""
#: sphinx/domains/cpp.py:3733
#: sphinx/domains/cpp.py:4205
#, python-format
msgid "%s (C++ type)"
msgstr "%s (C++ টাইপ)"
#: sphinx/domains/cpp.py:3744
#: sphinx/domains/cpp.py:4216
#, python-format
msgid "%s (C++ concept)"
msgstr ""
#: sphinx/domains/cpp.py:4227
#, python-format
msgid "%s (C++ member)"
msgstr "%s (C++ মেম্বার)"
#: sphinx/domains/cpp.py:3755
#: sphinx/domains/cpp.py:4238
#, python-format
msgid "%s (C++ function)"
msgstr "%s (C++ ফাংশন)"
#: sphinx/domains/cpp.py:3766
#: sphinx/domains/cpp.py:4249
#, python-format
msgid "%s (C++ class)"
msgstr "%s (C++ ক্লাসে)"
#: sphinx/domains/cpp.py:3786
#: sphinx/domains/cpp.py:4260
#, python-format
msgid "%s (C++ enum)"
msgstr ""
#: sphinx/domains/cpp.py:3816
#: sphinx/domains/cpp.py:4281
#, python-format
msgid "%s (C++ enumerator)"
msgstr ""
#: sphinx/domains/cpp.py:3952 sphinx/domains/javascript.py:165
#: sphinx/domains/python.py:591
#: sphinx/domains/cpp.py:4417 sphinx/domains/javascript.py:165
#: sphinx/domains/python.py:616
msgid "class"
msgstr "ক্লাস"
#: sphinx/domains/cpp.py:3956
#: sphinx/domains/cpp.py:4421
msgid "concept"
msgstr ""
#: sphinx/domains/cpp.py:4422
msgid "enum"
msgstr ""
#: sphinx/domains/cpp.py:3957
#: sphinx/domains/cpp.py:4423
msgid "enumerator"
msgstr ""
#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:282
#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:307
#, python-format
msgid "%s() (built-in function)"
msgstr "%s() (বিল্ট-ইন ফাংশন)"
#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:346
#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:371
#, python-format
msgid "%s() (%s method)"
msgstr "%s() (%s মেথড)"
@ -248,7 +251,7 @@ msgstr "%s() (ক্লাসে)"
msgid "%s (global variable or constant)"
msgstr ""
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:384
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:409
#, python-format
msgid "%s (%s attribute)"
msgstr "%s (%s এ্যট্রিবিউট)"
@ -257,116 +260,116 @@ msgstr "%s (%s এ্যট্রিবিউট)"
msgid "Arguments"
msgstr ""
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:590
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:615
msgid "data"
msgstr "ডাটা"
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:596
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:621
msgid "attribute"
msgstr "এ্যট্রিবিউট"
#: sphinx/domains/python.py:129
#: sphinx/domains/python.py:154
msgid "Variables"
msgstr ""
#: sphinx/domains/python.py:133
#: sphinx/domains/python.py:158
msgid "Raises"
msgstr "রেইজেস"
#: sphinx/domains/python.py:283 sphinx/domains/python.py:340
#: sphinx/domains/python.py:352 sphinx/domains/python.py:365
#: sphinx/domains/python.py:308 sphinx/domains/python.py:365
#: sphinx/domains/python.py:377 sphinx/domains/python.py:390
#, python-format
msgid "%s() (in module %s)"
msgstr "%s() (%s মডিউলে)"
#: sphinx/domains/python.py:286
#: sphinx/domains/python.py:311
#, python-format
msgid "%s (built-in variable)"
msgstr "%s (বিল্ট-ইন ভ্যারিয়েবল)"
#: sphinx/domains/python.py:287 sphinx/domains/python.py:378
#: sphinx/domains/python.py:312 sphinx/domains/python.py:403
#, python-format
msgid "%s (in module %s)"
msgstr "%s (%s মডিউলে)"
#: sphinx/domains/python.py:303
#: sphinx/domains/python.py:328
#, python-format
msgid "%s (built-in class)"
msgstr "%s (বিল্ট-ইন ক্লাস)"
#: sphinx/domains/python.py:304
#: sphinx/domains/python.py:329
#, python-format
msgid "%s (class in %s)"
msgstr "%s (%s ক্লাসে)"
#: sphinx/domains/python.py:344
#: sphinx/domains/python.py:369
#, python-format
msgid "%s() (%s.%s method)"
msgstr "%s (%s.%s মেথড)"
#: sphinx/domains/python.py:356
#: sphinx/domains/python.py:381
#, python-format
msgid "%s() (%s.%s static method)"
msgstr "%s (%s.%s স্ট্যাটিক মেথড)"
#: sphinx/domains/python.py:359
#: sphinx/domains/python.py:384
#, python-format
msgid "%s() (%s static method)"
msgstr "%s() (%s স্ট্যাটিক মেথড)"
#: sphinx/domains/python.py:369
#: sphinx/domains/python.py:394
#, python-format
msgid "%s() (%s.%s class method)"
msgstr "%s() (%s.%s ক্লাস মেথড)"
#: sphinx/domains/python.py:372
#: sphinx/domains/python.py:397
#, python-format
msgid "%s() (%s class method)"
msgstr "%s() (%s ক্লাস মেথড)"
#: sphinx/domains/python.py:382
#: sphinx/domains/python.py:407
#, python-format
msgid "%s (%s.%s attribute)"
msgstr "%s (%s.%s এ্যট্রিবিউট)"
#: sphinx/domains/python.py:463
#: sphinx/domains/python.py:488
#, python-format
msgid "%s (module)"
msgstr "%s (মডিউল)"
#: sphinx/domains/python.py:520
#: sphinx/domains/python.py:545
msgid "Python Module Index"
msgstr ""
#: sphinx/domains/python.py:521
#: sphinx/domains/python.py:546
msgid "modules"
msgstr "মডিউল সমূহ"
#: sphinx/domains/python.py:567
#: sphinx/domains/python.py:592
msgid "Deprecated"
msgstr "ডেপ্রিকেটেড"
#: sphinx/domains/python.py:592 sphinx/locale/__init__.py:183
#: sphinx/domains/python.py:617 sphinx/locale/__init__.py:183
msgid "exception"
msgstr "এক্সেপশন"
#: sphinx/domains/python.py:593
#: sphinx/domains/python.py:618
msgid "method"
msgstr "মেথড"
#: sphinx/domains/python.py:594
#: sphinx/domains/python.py:619
msgid "class method"
msgstr "ক্লাস মেথড"
#: sphinx/domains/python.py:595
#: sphinx/domains/python.py:620
msgid "static method"
msgstr "স্ট্যাটিক মেথড"
#: sphinx/domains/python.py:597 sphinx/locale/__init__.py:179
#: sphinx/domains/python.py:622 sphinx/locale/__init__.py:179
msgid "module"
msgstr "মডিউল"
#: sphinx/domains/python.py:762
#: sphinx/domains/python.py:787
msgid " (deprecated)"
msgstr ""
@ -388,120 +391,147 @@ msgstr ""
msgid "role"
msgstr ""
#: sphinx/domains/std.py:73 sphinx/domains/std.py:89
#: sphinx/domains/std.py:72 sphinx/domains/std.py:88
#, python-format
msgid "environment variable; %s"
msgstr "এনভায়রনমেন্ট ভ্যারিয়েবল; %s"
#: sphinx/domains/std.py:185
#: sphinx/domains/std.py:186
#, python-format
msgid "%scommand line option; %s"
msgstr "%sকমান্ড লাইন অপশন; %s"
#: sphinx/domains/std.py:433
#: sphinx/domains/std.py:434
msgid "glossary term"
msgstr "শব্দকোষ"
#: sphinx/domains/std.py:434
#: sphinx/domains/std.py:435
msgid "grammar token"
msgstr "ব্যকরণ টোকেন"
#: sphinx/domains/std.py:435
#: sphinx/domains/std.py:436
msgid "reference label"
msgstr ""
#: sphinx/domains/std.py:437
#: sphinx/domains/std.py:438
msgid "environment variable"
msgstr "এনভায়রনমেন্ট ভ্যারিয়েবল"
#: sphinx/domains/std.py:438
#: sphinx/domains/std.py:439
msgid "program option"
msgstr "প্রোগ্রাম অপশন"
#: sphinx/domains/std.py:471 sphinx/themes/basic/genindex-single.html:32
#: sphinx/themes/basic/genindex-single.html:57
#: sphinx/domains/std.py:473 sphinx/themes/basic/genindex-single.html:30
#: sphinx/themes/basic/genindex-single.html:55
#: sphinx/themes/basic/genindex-split.html:11
#: sphinx/themes/basic/genindex-split.html:14
#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
#: sphinx/writers/latex.py:363 sphinx/writers/texinfo.py:481
#: sphinx/themes/basic/genindex.html:30 sphinx/themes/basic/genindex.html:33
#: sphinx/themes/basic/genindex.html:66 sphinx/themes/basic/layout.html:135
#: sphinx/writers/latex.py:381 sphinx/writers/texinfo.py:480
msgid "Index"
msgstr "ইনডেক্স"
#: sphinx/domains/std.py:472
#: sphinx/domains/std.py:474
msgid "Module Index"
msgstr "মডিউল ইনডেক্স"
#: sphinx/domains/std.py:473 sphinx/themes/basic/defindex.html:25
#: sphinx/domains/std.py:475 sphinx/themes/basic/defindex.html:25
msgid "Search Page"
msgstr "অনুসন্ধান পাতা"
#: sphinx/ext/autodoc.py:1265
#: sphinx/environment/managers/indexentries.py:104
#, python-format
msgid " Bases: %s"
msgstr "বেস: %s"
msgid "see %s"
msgstr ""
#: sphinx/ext/autodoc.py:1318
#: sphinx/environment/managers/indexentries.py:108
#, python-format
msgid "see also %s"
msgstr ""
#: sphinx/environment/managers/indexentries.py:168
msgid "Symbols"
msgstr ""
#: sphinx/ext/autodoc.py:1297
#, python-format
msgid "Bases: %s"
msgstr ""
#: sphinx/ext/autodoc.py:1350
#, python-format
msgid "alias of :class:`%s`"
msgstr ":class:`%s` এর উপনাম"
#: sphinx/ext/graphviz.py:309 sphinx/ext/graphviz.py:318
#: sphinx/ext/graphviz.py:331 sphinx/ext/graphviz.py:340
#, python-format
msgid "[graph: %s]"
msgstr ""
#: sphinx/ext/graphviz.py:311 sphinx/ext/graphviz.py:320
#: sphinx/ext/graphviz.py:333 sphinx/ext/graphviz.py:342
msgid "[graph]"
msgstr ""
#: sphinx/ext/intersphinx.py:359
#: sphinx/ext/imgmath.py:258 sphinx/ext/jsmath.py:39 sphinx/ext/mathjax.py:40
msgid "Permalink to this equation"
msgstr ""
#: sphinx/ext/intersphinx.py:337
#, python-format
msgid "(in %s v%s)"
msgstr ""
#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:99
#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:103
msgid "[source]"
msgstr ""
#: sphinx/ext/mathbase.py:92
#, python-format
msgid "duplicate label of equation %s, other instance in %s"
msgstr ""
#: sphinx/ext/todo.py:56
msgid "Todo"
msgstr "অসমাপ্ত কাজ"
#: sphinx/ext/todo.py:129
#: sphinx/ext/todo.py:134
msgid "<<original entry>>"
msgstr ""
#: sphinx/ext/todo.py:132
#: sphinx/ext/todo.py:137
#, python-format
msgid "(The <<original entry>> is located in %s, line %d.)"
msgstr ""
#: sphinx/ext/todo.py:141
#: sphinx/ext/todo.py:146
msgid "original entry"
msgstr ""
#: sphinx/ext/viewcode.py:162
#: sphinx/ext/viewcode.py:166
msgid "[docs]"
msgstr ""
#: sphinx/ext/viewcode.py:176
#: sphinx/ext/viewcode.py:180
msgid "Module code"
msgstr ""
#: sphinx/ext/viewcode.py:182
#: sphinx/ext/viewcode.py:186
#, python-format
msgid "<h1>Source code for %s</h1>"
msgstr ""
#: sphinx/ext/viewcode.py:208
#: sphinx/ext/viewcode.py:212
msgid "Overview: module code"
msgstr ""
#: sphinx/ext/viewcode.py:209
#: sphinx/ext/viewcode.py:213
msgid "<h1>All modules for which code is available</h1>"
msgstr ""
#: sphinx/ext/napoleon/__init__.py:313
msgid "Keyword Arguments"
msgstr ""
#: sphinx/locale/__init__.py:159
msgid "Attention"
msgstr "দৃষ্টি আকর্ষণ"
@ -582,7 +612,7 @@ msgstr "বিল্ট-ইন ফাংশন"
msgid "Table Of Contents"
msgstr "সূচীপত্র"
#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:137
#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:138
#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
#: sphinx/themes/basic/searchresults.html:10
msgid "Search"
@ -640,15 +670,15 @@ msgstr "সকল মডিউলে দ্রুত প্রবেশ"
msgid "all functions, classes, terms"
msgstr "সকল ফাংশন, ক্লাস, টার্ম"
#: sphinx/themes/basic/genindex-single.html:35
#: sphinx/themes/basic/genindex-single.html:33
#, python-format
msgid "Index &ndash; %(key)s"
msgstr "ইনডেক্স &ndash; %(key)s"
#: sphinx/themes/basic/genindex-single.html:63
#: sphinx/themes/basic/genindex-single.html:61
#: sphinx/themes/basic/genindex-split.html:24
#: sphinx/themes/basic/genindex-split.html:38
#: sphinx/themes/basic/genindex.html:74
#: sphinx/themes/basic/genindex.html:72
msgid "Full index on one page"
msgstr "এক পাতায় সম্পূর্ণ ইনডেক্স"
@ -664,35 +694,35 @@ msgstr "খুব বড় হতে পারে"
msgid "Navigation"
msgstr "নেভিগেশন"
#: sphinx/themes/basic/layout.html:122
#: sphinx/themes/basic/layout.html:123
#, python-format
msgid "Search within %(docstitle)s"
msgstr "%(docstitle)s এর মধ্যে খুঁজুন"
#: sphinx/themes/basic/layout.html:131
#: sphinx/themes/basic/layout.html:132
msgid "About these documents"
msgstr "এই ডকুমেন্ট সম্পর্কে"
#: sphinx/themes/basic/layout.html:140
#: sphinx/themes/basic/layout.html:141
msgid "Copyright"
msgstr "কপিরাইট"
#: sphinx/themes/basic/layout.html:189
#: sphinx/themes/basic/layout.html:186
#, python-format
msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr "&copy; <a href=\"%(path)s\">কপিরাইট</a> %(copyright)s."
msgid "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:191
#: sphinx/themes/basic/layout.html:188
#, python-format
msgid "&copy; Copyright %(copyright)s."
msgstr "&copy; কপিরাইট %(copyright)s."
msgid "&#169; Copyright %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:195
#: sphinx/themes/basic/layout.html:192
#, python-format
msgid "Last updated on %(last_updated)s."
msgstr "%(last_updated)s সর্বশেষ পরিবর্তন করা হয়েছে।"
#: sphinx/themes/basic/layout.html:198
#: sphinx/themes/basic/layout.html:195
#, python-format
msgid ""
"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
@ -741,13 +771,13 @@ msgstr "খুঁজুন"
#: sphinx/themes/basic/search.html:43
#: sphinx/themes/basic/searchresults.html:21
#: sphinx/themes/basic/static/searchtools.js_t:282
#: sphinx/themes/basic/static/searchtools.js_t:287
msgid "Search Results"
msgstr "অনুসন্ধানের ফলাফল"
#: sphinx/themes/basic/search.html:45
#: sphinx/themes/basic/searchresults.html:23
#: sphinx/themes/basic/static/searchtools.js_t:284
#: sphinx/themes/basic/static/searchtools.js_t:289
msgid ""
"Your search did not match any documents. Please make sure that all words are"
" spelled correctly and that you've selected enough categories."
@ -764,13 +794,13 @@ msgstr "এই পাতা"
#: sphinx/themes/basic/changes/frameset.html:5
#: sphinx/themes/basic/changes/versionchanges.html:12
#, python-format
msgid "Changes in Version %(version)s &mdash; %(docstitle)s"
msgstr "%(version)s &mdash; %(docstitle)s-এ পরিবর্তন সমূহ"
msgid "Changes in Version %(version)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/rstsource.html:5
#, python-format
msgid "%(filename)s &mdash; %(docstitle)s"
msgstr "%(filename)s &mdash; %(docstitle)s"
msgid "%(filename)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/versionchanges.html:17
#, python-format
@ -789,12 +819,13 @@ msgstr "C API পরিবর্তন"
msgid "Other changes"
msgstr "অন্যান্য পরিবর্তন"
#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:668
#: sphinx/writers/html.py:673
#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:708
#: sphinx/writers/html.py:713
msgid "Permalink to this headline"
msgstr "এই শিরোনামের পার্মালিঙ্ক"
#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:105
#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:108
#: sphinx/writers/html.py:117
msgid "Permalink to this definition"
msgstr "এই সংজ্ঞার পার্মালিঙ্ক"
@ -810,12 +841,12 @@ msgstr ""
msgid "Preparing search..."
msgstr ""
#: sphinx/themes/basic/static/searchtools.js_t:286
#: sphinx/themes/basic/static/searchtools.js_t:291
#, python-format
msgid "Search finished, found %s page(s) matching the search query."
msgstr ""
#: sphinx/themes/basic/static/searchtools.js_t:338
#: sphinx/themes/basic/static/searchtools.js_t:344
msgid ", in "
msgstr ""
@ -832,48 +863,53 @@ msgstr ""
msgid "Contents"
msgstr ""
#: sphinx/writers/html.py:349
#: sphinx/writers/html.py:389
msgid "Permalink to this code"
msgstr ""
#: sphinx/writers/html.py:353
#: sphinx/writers/html.py:393
msgid "Permalink to this image"
msgstr ""
#: sphinx/writers/html.py:355
#: sphinx/writers/html.py:395
msgid "Permalink to this toctree"
msgstr ""
#: sphinx/writers/html.py:677
#: sphinx/writers/html.py:717
msgid "Permalink to this table"
msgstr ""
#: sphinx/writers/latex.py:361
#: sphinx/writers/latex.py:380
msgid "Release"
msgstr "রিলিজ"
#: sphinx/writers/latex.py:427
#: sphinx/writers/latex.py:483
msgid "page"
msgstr ""
#: sphinx/writers/latex.py:920 sphinx/writers/manpage.py:233
#: sphinx/writers/texinfo.py:620
#: sphinx/writers/latex.py:528
#, python-format
msgid "Unknown configure key: latex_elements[%r] is ignored."
msgstr ""
#: sphinx/writers/latex.py:1003 sphinx/writers/manpage.py:238
#: sphinx/writers/texinfo.py:619
msgid "Footnotes"
msgstr "পাদটীকা"
#: sphinx/writers/latex.py:1022
#: sphinx/writers/latex.py:1112
msgid "continued from previous page"
msgstr "পূর্ববর্তী পাতা হতে চলমান"
#: sphinx/writers/latex.py:1028
#: sphinx/writers/latex.py:1118
msgid "Continued on next page"
msgstr "পরবর্তী পাতাতে চলমান"
#: sphinx/writers/manpage.py:282 sphinx/writers/text.py:582
#: sphinx/writers/manpage.py:287 sphinx/writers/text.py:591
#, python-format
msgid "[image: %s]"
msgstr ""
#: sphinx/writers/manpage.py:283 sphinx/writers/text.py:583
#: sphinx/writers/manpage.py:288 sphinx/writers/text.py:592
msgid "[image]"
msgstr "[ছবি]"

View File

@ -1 +1 @@
Documentation.addTranslations({"locale": "ca", "messages": {"%(filename)s &mdash; %(docstitle)s": "%(filename)s &mdash; %(docstitle)s", "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "&copy; <a href=\\\"%(path)s\\\">Copyright</a> %(copyright)s.", "&copy; Copyright %(copyright)s.": "&copy; Copyright %(copyright)s.", ", in ": "", "About these documents": "Quant a aquests documents", "Automatically generated list of changes in version %(version)s": "Llista de canvis de la versi\u00f3 %(version)s generada autom\u00e0ticament", "C API changes": "Canvis a la API de C", "Changes in Version %(version)s &mdash; %(docstitle)s": "Canvis a la Versi\u00f3 %(version)s &mdash; %(docstitle)s", "Collapse sidebar": "", "Complete Table of Contents": "Taula de Contingut Completa", "Contents": "", "Copyright": "Copyright", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "Creat amb <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.", "Expand sidebar": "", "From here you can search these documents. Enter your search\n words into the box below and click \"search\". Note that the search\n function will automatically search for all of the words. Pages\n containing fewer words won't appear in the result list.": "Des d'aqu\u00ed pots fer cerques en aquests documents. Entra les \nparaules de la teva cerca i clica el bot\u00f3 \"cerca\". Tingues en compte\nque la cerca inclour\u00e0 totes les paraules que posis. Les p\u00e0gines que no\ntenen totes les paraules no sortir\u00e0n.", "Full index on one page": "\u00cdndex complet en una p\u00e0gina", "General Index": "\u00cdndex General", "Global Module Index": "\u00cdndex Global de M\u00f2duls", "Go": "Ves a", "Hide Search Matches": "Oculta Resultats de Cerca", "Index": "\u00cdndex", "Index &ndash; %(key)s": "\u00cdndes &ndash; %(key)s", "Index pages by letter": "P\u00e0gines d'\u00edndex per lletra", "Indices and tables:": "\u00cdndexs i taules:", "Last updated on %(last_updated)s.": "\u00daltima actualitzaci\u00f3 el %(last_updated)s.", "Library changes": "Canvis a la llibreria", "Navigation": "Navegaci\u00f3", "Next topic": "Tema seg\u00fcent", "Other changes": "Altres canvis", "Overview": "Resum", "Permalink to this definition": "Link permanent a aquesta definici\u00f3", "Permalink to this headline": "Link permanent a aquest t\u00edtol", "Please activate JavaScript to enable the search\n functionality.": "Activa JavaScript per utilitzar la funcionalitat\nde cerca.", "Preparing search...": "", "Previous topic": "Tema anterior", "Quick search": "Cerca r\u00e0pida", "Search": "Cerca", "Search Page": "P\u00e0gina de Cerca", "Search Results": "Resultats de la Cerca", "Search finished, found %s page(s) matching the search query.": "", "Search within %(docstitle)s": "Cerca dins de %(docstitle)s", "Searching": "", "Show Source": "Mostra Codi Font", "Table Of Contents": "Taula de Contingut", "This Page": "Aquesta P\u00e0gina", "Welcome! This is": "", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "", "all functions, classes, terms": "totes les funcions, classes, termes", "can be huge": "pot ser gegant", "last updated": "", "lists all sections and subsections": "llista totes les seccions i subseccions", "next chapter": "cap\u00edtol seg\u00fcent", "previous chapter": "cap\u00edtol anterior", "quick access to all modules": "acc\u00e9s r\u00e0pid a tots els m\u00f2duls", "search": "cerca", "search this documentation": "cerca aquesta documentaci\u00f3", "the documentation for": ""}, "plural_expr": "(n != 1)"});
Documentation.addTranslations({"locale": "ca", "messages": {"%(filename)s &#8212; %(docstitle)s": "", "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "", "&#169; Copyright %(copyright)s.": "", ", in ": "", "About these documents": "Quant a aquests documents", "Automatically generated list of changes in version %(version)s": "Llista de canvis de la versi\u00f3 %(version)s generada autom\u00e0ticament", "C API changes": "Canvis a la API de C", "Changes in Version %(version)s &#8212; %(docstitle)s": "", "Collapse sidebar": "", "Complete Table of Contents": "Taula de Contingut Completa", "Contents": "", "Copyright": "Copyright", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "Creat amb <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.", "Expand sidebar": "", "From here you can search these documents. Enter your search\n words into the box below and click \"search\". Note that the search\n function will automatically search for all of the words. Pages\n containing fewer words won't appear in the result list.": "Des d'aqu\u00ed pots fer cerques en aquests documents. Entra les \nparaules de la teva cerca i clica el bot\u00f3 \"cerca\". Tingues en compte\nque la cerca inclour\u00e0 totes les paraules que posis. Les p\u00e0gines que no\ntenen totes les paraules no sortir\u00e0n.", "Full index on one page": "\u00cdndex complet en una p\u00e0gina", "General Index": "\u00cdndex General", "Global Module Index": "\u00cdndex Global de M\u00f2duls", "Go": "Ves a", "Hide Search Matches": "Oculta Resultats de Cerca", "Index": "\u00cdndex", "Index &ndash; %(key)s": "\u00cdndes &ndash; %(key)s", "Index pages by letter": "P\u00e0gines d'\u00edndex per lletra", "Indices and tables:": "\u00cdndexs i taules:", "Last updated on %(last_updated)s.": "\u00daltima actualitzaci\u00f3 el %(last_updated)s.", "Library changes": "Canvis a la llibreria", "Navigation": "Navegaci\u00f3", "Next topic": "Tema seg\u00fcent", "Other changes": "Altres canvis", "Overview": "Resum", "Permalink to this definition": "Link permanent a aquesta definici\u00f3", "Permalink to this headline": "Link permanent a aquest t\u00edtol", "Please activate JavaScript to enable the search\n functionality.": "Activa JavaScript per utilitzar la funcionalitat\nde cerca.", "Preparing search...": "", "Previous topic": "Tema anterior", "Quick search": "Cerca r\u00e0pida", "Search": "Cerca", "Search Page": "P\u00e0gina de Cerca", "Search Results": "Resultats de la Cerca", "Search finished, found %s page(s) matching the search query.": "", "Search within %(docstitle)s": "Cerca dins de %(docstitle)s", "Searching": "", "Show Source": "Mostra Codi Font", "Table Of Contents": "Taula de Contingut", "This Page": "Aquesta P\u00e0gina", "Welcome! This is": "", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "", "all functions, classes, terms": "totes les funcions, classes, termes", "can be huge": "pot ser gegant", "last updated": "", "lists all sections and subsections": "llista totes les seccions i subseccions", "next chapter": "cap\u00edtol seg\u00fcent", "previous chapter": "cap\u00edtol anterior", "quick access to all modules": "acc\u00e9s r\u00e0pid a tots els m\u00f2duls", "search": "cerca", "search this documentation": "cerca aquesta documentaci\u00f3", "the documentation for": ""}, "plural_expr": "(n != 1)"});

View File

@ -8,61 +8,42 @@ msgid ""
msgstr ""
"Project-Id-Version: Sphinx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-03-06 21:58+0900\n"
"PO-Revision-Date: 2016-03-06 13:01+0000\n"
"Last-Translator: Takayuki Shimizukawa <shimizukawa@gmail.com>\n"
"POT-Creation-Date: 2016-11-06 22:40+0900\n"
"PO-Revision-Date: 2016-11-06 13:53+0000\n"
"Last-Translator: Takeshi KOMIYA <i.tkomiya@gmail.com>\n"
"Language-Team: Catalan (http://www.transifex.com/sphinx-doc/sphinx-1/language/ca/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.2.0\n"
"Generated-By: Babel 2.3.4\n"
"Language: ca\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: sphinx/config.py:91
#: sphinx/config.py:109
#, python-format
msgid "Section %s"
msgstr ""
#: sphinx/config.py:110
#, python-format
msgid "Fig. %s"
msgstr ""
#: sphinx/config.py:92
#: sphinx/config.py:111
#, python-format
msgid "Table %s"
msgstr ""
#: sphinx/config.py:93
#: sphinx/config.py:112
#, python-format
msgid "Listing %s"
msgstr ""
#: sphinx/config.py:100
#, python-format
msgid "%s %s documentation"
msgstr "%s %s documentació"
#: sphinx/environment.py:1829
#, python-format
msgid "see %s"
msgstr "vegeu %s"
#: sphinx/environment.py:1833
#, python-format
msgid "see also %s"
msgstr "vegeu també %s"
#: sphinx/environment.py:1893
msgid "Symbols"
msgstr ""
#: sphinx/roles.py:193
#: sphinx/roles.py:187
#, python-format
msgid "Python Enhancement Proposals; PEP %s"
msgstr "Python Enhancement Proposals; PEP %s"
#: sphinx/transforms.py:56 sphinx/writers/latex.py:374
#: sphinx/writers/manpage.py:101 sphinx/writers/texinfo.py:222
msgid "MMMM dd, YYYY"
msgstr ""
#: sphinx/builders/changes.py:75
msgid "Builtins"
msgstr "Mòduls Interns"
@ -71,8 +52,11 @@ msgstr "Mòduls Interns"
msgid "Module level"
msgstr "Nivell de mòdul"
#: sphinx/builders/html.py:295
msgid "MMM dd, YYYY"
#: sphinx/builders/html.py:294 sphinx/transforms/__init__.py:46
#: sphinx/writers/latex.py:393 sphinx/writers/manpage.py:100
#: sphinx/writers/texinfo.py:221
#, python-format
msgid "%b %d, %Y"
msgstr ""
#: sphinx/builders/html.py:315 sphinx/themes/basic/defindex.html:30
@ -83,18 +67,28 @@ msgstr "Índex General"
msgid "index"
msgstr "índex"
#: sphinx/builders/html.py:376
#: sphinx/builders/html.py:377
msgid "next"
msgstr "següent"
#: sphinx/builders/html.py:385
#: sphinx/builders/html.py:386
msgid "previous"
msgstr "anterior"
#: sphinx/builders/latex.py:180 sphinx/builders/texinfo.py:199
#: sphinx/builders/html.py:1222
#, python-format
msgid "%s %s documentation"
msgstr "%s %s documentació"
#: sphinx/builders/latex.py:177 sphinx/builders/texinfo.py:199
msgid " (in "
msgstr " (a "
#: sphinx/directives/code.py:140 sphinx/directives/code.py:370
#, python-format
msgid "Invalid caption: %s"
msgstr ""
#: sphinx/directives/other.py:149
msgid "Section author: "
msgstr "Autor de la secció:"
@ -111,23 +105,23 @@ msgstr ""
msgid "Author: "
msgstr "Autor: "
#: sphinx/domains/__init__.py:275
#: sphinx/domains/__init__.py:277
#, python-format
msgid "%s %s"
msgstr ""
#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:3605
#: sphinx/domains/python.py:124
#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:4051
#: sphinx/domains/python.py:149
msgid "Parameters"
msgstr "Paràmetres"
#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:3614
#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:136
#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:4060
#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:161
msgid "Returns"
msgstr "Retorna"
#: sphinx/domains/c.py:63 sphinx/domains/javascript.py:130
#: sphinx/domains/python.py:138
#: sphinx/domains/python.py:163
msgid "Return type"
msgstr "Tipus de retorn"
@ -156,12 +150,12 @@ msgstr "%s (tipus de C)"
msgid "%s (C variable)"
msgstr "%s (variable de C)"
#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:3953
#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:589
#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:4418
#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:614
msgid "function"
msgstr "funció"
#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:3954
#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:4419
msgid "member"
msgstr "membre"
@ -169,7 +163,7 @@ msgstr "membre"
msgid "macro"
msgstr "macro"
#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:3955
#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:4420
msgid "type"
msgstr "tipus"
@ -177,63 +171,72 @@ msgstr "tipus"
msgid "variable"
msgstr "variable"
#: sphinx/domains/cpp.py:3608
#: sphinx/domains/cpp.py:4054
msgid "Template Parameters"
msgstr ""
#: sphinx/domains/cpp.py:3611 sphinx/domains/javascript.py:125
#: sphinx/domains/cpp.py:4057 sphinx/domains/javascript.py:125
msgid "Throws"
msgstr ""
#: sphinx/domains/cpp.py:3733
#: sphinx/domains/cpp.py:4205
#, python-format
msgid "%s (C++ type)"
msgstr "%s (tipus de C++)"
#: sphinx/domains/cpp.py:3744
#: sphinx/domains/cpp.py:4216
#, python-format
msgid "%s (C++ concept)"
msgstr ""
#: sphinx/domains/cpp.py:4227
#, python-format
msgid "%s (C++ member)"
msgstr "%s (membre de C++)"
#: sphinx/domains/cpp.py:3755
#: sphinx/domains/cpp.py:4238
#, python-format
msgid "%s (C++ function)"
msgstr "%s (funció de C++)"
#: sphinx/domains/cpp.py:3766
#: sphinx/domains/cpp.py:4249
#, python-format
msgid "%s (C++ class)"
msgstr "%s (class de C++)"
#: sphinx/domains/cpp.py:3786
#: sphinx/domains/cpp.py:4260
#, python-format
msgid "%s (C++ enum)"
msgstr ""
#: sphinx/domains/cpp.py:3816
#: sphinx/domains/cpp.py:4281
#, python-format
msgid "%s (C++ enumerator)"
msgstr ""
#: sphinx/domains/cpp.py:3952 sphinx/domains/javascript.py:165
#: sphinx/domains/python.py:591
#: sphinx/domains/cpp.py:4417 sphinx/domains/javascript.py:165
#: sphinx/domains/python.py:616
msgid "class"
msgstr "class"
#: sphinx/domains/cpp.py:3956
#: sphinx/domains/cpp.py:4421
msgid "concept"
msgstr ""
#: sphinx/domains/cpp.py:4422
msgid "enum"
msgstr ""
#: sphinx/domains/cpp.py:3957
#: sphinx/domains/cpp.py:4423
msgid "enumerator"
msgstr ""
#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:282
#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:307
#, python-format
msgid "%s() (built-in function)"
msgstr "%s() (funció interna)"
#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:346
#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:371
#, python-format
msgid "%s() (%s method)"
msgstr "%s() (mètode %s)"
@ -248,7 +251,7 @@ msgstr "%s() (class)"
msgid "%s (global variable or constant)"
msgstr ""
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:384
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:409
#, python-format
msgid "%s (%s attribute)"
msgstr "%s (atribut %s)"
@ -257,116 +260,116 @@ msgstr "%s (atribut %s)"
msgid "Arguments"
msgstr ""
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:590
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:615
msgid "data"
msgstr ""
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:596
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:621
msgid "attribute"
msgstr "atribut"
#: sphinx/domains/python.py:129
#: sphinx/domains/python.py:154
msgid "Variables"
msgstr ""
#: sphinx/domains/python.py:133
#: sphinx/domains/python.py:158
msgid "Raises"
msgstr "Llença"
#: sphinx/domains/python.py:283 sphinx/domains/python.py:340
#: sphinx/domains/python.py:352 sphinx/domains/python.py:365
#: sphinx/domains/python.py:308 sphinx/domains/python.py:365
#: sphinx/domains/python.py:377 sphinx/domains/python.py:390
#, python-format
msgid "%s() (in module %s)"
msgstr "%s() (al mòdul %s)"
#: sphinx/domains/python.py:286
#: sphinx/domains/python.py:311
#, python-format
msgid "%s (built-in variable)"
msgstr "%s (variable interna)"
#: sphinx/domains/python.py:287 sphinx/domains/python.py:378
#: sphinx/domains/python.py:312 sphinx/domains/python.py:403
#, python-format
msgid "%s (in module %s)"
msgstr "%s (al mòdul %s)"
#: sphinx/domains/python.py:303
#: sphinx/domains/python.py:328
#, python-format
msgid "%s (built-in class)"
msgstr "%s (classe interna)"
#: sphinx/domains/python.py:304
#: sphinx/domains/python.py:329
#, python-format
msgid "%s (class in %s)"
msgstr "%s (class a %s)"
#: sphinx/domains/python.py:344
#: sphinx/domains/python.py:369
#, python-format
msgid "%s() (%s.%s method)"
msgstr "%s() (mètode %s.%s)"
#: sphinx/domains/python.py:356
#: sphinx/domains/python.py:381
#, python-format
msgid "%s() (%s.%s static method)"
msgstr "%s() (mètode estàtic %s.%s)"
#: sphinx/domains/python.py:359
#: sphinx/domains/python.py:384
#, python-format
msgid "%s() (%s static method)"
msgstr "%s() (mètode estàtic %s)"
#: sphinx/domains/python.py:369
#: sphinx/domains/python.py:394
#, python-format
msgid "%s() (%s.%s class method)"
msgstr ""
#: sphinx/domains/python.py:372
#: sphinx/domains/python.py:397
#, python-format
msgid "%s() (%s class method)"
msgstr ""
#: sphinx/domains/python.py:382
#: sphinx/domains/python.py:407
#, python-format
msgid "%s (%s.%s attribute)"
msgstr "%s (atribut %s.%s)"
#: sphinx/domains/python.py:463
#: sphinx/domains/python.py:488
#, python-format
msgid "%s (module)"
msgstr "%s (mòdul)"
#: sphinx/domains/python.py:520
#: sphinx/domains/python.py:545
msgid "Python Module Index"
msgstr ""
#: sphinx/domains/python.py:521
#: sphinx/domains/python.py:546
msgid "modules"
msgstr "mòduls"
#: sphinx/domains/python.py:567
#: sphinx/domains/python.py:592
msgid "Deprecated"
msgstr "Obsolet"
#: sphinx/domains/python.py:592 sphinx/locale/__init__.py:183
#: sphinx/domains/python.py:617 sphinx/locale/__init__.py:183
msgid "exception"
msgstr "excepció"
#: sphinx/domains/python.py:593
#: sphinx/domains/python.py:618
msgid "method"
msgstr ""
#: sphinx/domains/python.py:594
#: sphinx/domains/python.py:619
msgid "class method"
msgstr ""
#: sphinx/domains/python.py:595
#: sphinx/domains/python.py:620
msgid "static method"
msgstr "mètode estàtic"
#: sphinx/domains/python.py:597 sphinx/locale/__init__.py:179
#: sphinx/domains/python.py:622 sphinx/locale/__init__.py:179
msgid "module"
msgstr "mòdul"
#: sphinx/domains/python.py:762
#: sphinx/domains/python.py:787
msgid " (deprecated)"
msgstr " (obsolet)"
@ -388,120 +391,147 @@ msgstr ""
msgid "role"
msgstr ""
#: sphinx/domains/std.py:73 sphinx/domains/std.py:89
#: sphinx/domains/std.py:72 sphinx/domains/std.py:88
#, python-format
msgid "environment variable; %s"
msgstr "variable d'entorn; %s"
#: sphinx/domains/std.py:185
#: sphinx/domains/std.py:186
#, python-format
msgid "%scommand line option; %s"
msgstr "opció de línia de comandes %s; %s"
#: sphinx/domains/std.py:433
#: sphinx/domains/std.py:434
msgid "glossary term"
msgstr ""
#: sphinx/domains/std.py:434
#: sphinx/domains/std.py:435
msgid "grammar token"
msgstr ""
#: sphinx/domains/std.py:435
#: sphinx/domains/std.py:436
msgid "reference label"
msgstr ""
#: sphinx/domains/std.py:437
#: sphinx/domains/std.py:438
msgid "environment variable"
msgstr "variable d'entorn"
#: sphinx/domains/std.py:438
#: sphinx/domains/std.py:439
msgid "program option"
msgstr ""
#: sphinx/domains/std.py:471 sphinx/themes/basic/genindex-single.html:32
#: sphinx/themes/basic/genindex-single.html:57
#: sphinx/domains/std.py:473 sphinx/themes/basic/genindex-single.html:30
#: sphinx/themes/basic/genindex-single.html:55
#: sphinx/themes/basic/genindex-split.html:11
#: sphinx/themes/basic/genindex-split.html:14
#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
#: sphinx/writers/latex.py:363 sphinx/writers/texinfo.py:481
#: sphinx/themes/basic/genindex.html:30 sphinx/themes/basic/genindex.html:33
#: sphinx/themes/basic/genindex.html:66 sphinx/themes/basic/layout.html:135
#: sphinx/writers/latex.py:381 sphinx/writers/texinfo.py:480
msgid "Index"
msgstr "Índex"
#: sphinx/domains/std.py:472
#: sphinx/domains/std.py:474
msgid "Module Index"
msgstr "Índex de Mòduls"
#: sphinx/domains/std.py:473 sphinx/themes/basic/defindex.html:25
#: sphinx/domains/std.py:475 sphinx/themes/basic/defindex.html:25
msgid "Search Page"
msgstr "Pàgina de Cerca"
#: sphinx/ext/autodoc.py:1265
#: sphinx/environment/managers/indexentries.py:104
#, python-format
msgid " Bases: %s"
msgstr " Bases: %s"
msgid "see %s"
msgstr "vegeu %s"
#: sphinx/ext/autodoc.py:1318
#: sphinx/environment/managers/indexentries.py:108
#, python-format
msgid "see also %s"
msgstr "vegeu també %s"
#: sphinx/environment/managers/indexentries.py:168
msgid "Symbols"
msgstr ""
#: sphinx/ext/autodoc.py:1297
#, python-format
msgid "Bases: %s"
msgstr ""
#: sphinx/ext/autodoc.py:1350
#, python-format
msgid "alias of :class:`%s`"
msgstr "àlies de :class:`%s`"
#: sphinx/ext/graphviz.py:309 sphinx/ext/graphviz.py:318
#: sphinx/ext/graphviz.py:331 sphinx/ext/graphviz.py:340
#, python-format
msgid "[graph: %s]"
msgstr ""
#: sphinx/ext/graphviz.py:311 sphinx/ext/graphviz.py:320
#: sphinx/ext/graphviz.py:333 sphinx/ext/graphviz.py:342
msgid "[graph]"
msgstr ""
#: sphinx/ext/intersphinx.py:359
#: sphinx/ext/imgmath.py:258 sphinx/ext/jsmath.py:39 sphinx/ext/mathjax.py:40
msgid "Permalink to this equation"
msgstr ""
#: sphinx/ext/intersphinx.py:337
#, python-format
msgid "(in %s v%s)"
msgstr ""
#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:99
#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:103
msgid "[source]"
msgstr ""
#: sphinx/ext/mathbase.py:92
#, python-format
msgid "duplicate label of equation %s, other instance in %s"
msgstr ""
#: sphinx/ext/todo.py:56
msgid "Todo"
msgstr "Pendent"
#: sphinx/ext/todo.py:129
#: sphinx/ext/todo.py:134
msgid "<<original entry>>"
msgstr ""
#: sphinx/ext/todo.py:132
#: sphinx/ext/todo.py:137
#, python-format
msgid "(The <<original entry>> is located in %s, line %d.)"
msgstr ""
#: sphinx/ext/todo.py:141
#: sphinx/ext/todo.py:146
msgid "original entry"
msgstr ""
#: sphinx/ext/viewcode.py:162
#: sphinx/ext/viewcode.py:166
msgid "[docs]"
msgstr ""
#: sphinx/ext/viewcode.py:176
#: sphinx/ext/viewcode.py:180
msgid "Module code"
msgstr ""
#: sphinx/ext/viewcode.py:182
#: sphinx/ext/viewcode.py:186
#, python-format
msgid "<h1>Source code for %s</h1>"
msgstr ""
#: sphinx/ext/viewcode.py:208
#: sphinx/ext/viewcode.py:212
msgid "Overview: module code"
msgstr ""
#: sphinx/ext/viewcode.py:209
#: sphinx/ext/viewcode.py:213
msgid "<h1>All modules for which code is available</h1>"
msgstr ""
#: sphinx/ext/napoleon/__init__.py:313
msgid "Keyword Arguments"
msgstr ""
#: sphinx/locale/__init__.py:159
msgid "Attention"
msgstr "Atenció"
@ -582,7 +612,7 @@ msgstr "funció interna"
msgid "Table Of Contents"
msgstr "Taula de Contingut"
#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:137
#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:138
#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
#: sphinx/themes/basic/searchresults.html:10
msgid "Search"
@ -640,15 +670,15 @@ msgstr "accés ràpid a tots els mòduls"
msgid "all functions, classes, terms"
msgstr "totes les funcions, classes, termes"
#: sphinx/themes/basic/genindex-single.html:35
#: sphinx/themes/basic/genindex-single.html:33
#, python-format
msgid "Index &ndash; %(key)s"
msgstr "Índes &ndash; %(key)s"
#: sphinx/themes/basic/genindex-single.html:63
#: sphinx/themes/basic/genindex-single.html:61
#: sphinx/themes/basic/genindex-split.html:24
#: sphinx/themes/basic/genindex-split.html:38
#: sphinx/themes/basic/genindex.html:74
#: sphinx/themes/basic/genindex.html:72
msgid "Full index on one page"
msgstr "Índex complet en una pàgina"
@ -664,35 +694,35 @@ msgstr "pot ser gegant"
msgid "Navigation"
msgstr "Navegació"
#: sphinx/themes/basic/layout.html:122
#: sphinx/themes/basic/layout.html:123
#, python-format
msgid "Search within %(docstitle)s"
msgstr "Cerca dins de %(docstitle)s"
#: sphinx/themes/basic/layout.html:131
#: sphinx/themes/basic/layout.html:132
msgid "About these documents"
msgstr "Quant a aquests documents"
#: sphinx/themes/basic/layout.html:140
#: sphinx/themes/basic/layout.html:141
msgid "Copyright"
msgstr "Copyright"
#: sphinx/themes/basic/layout.html:189
#: sphinx/themes/basic/layout.html:186
#, python-format
msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr "&copy; <a href=\\\"%(path)s\\\">Copyright</a> %(copyright)s."
msgid "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:191
#: sphinx/themes/basic/layout.html:188
#, python-format
msgid "&copy; Copyright %(copyright)s."
msgstr "&copy; Copyright %(copyright)s."
msgid "&#169; Copyright %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:195
#: sphinx/themes/basic/layout.html:192
#, python-format
msgid "Last updated on %(last_updated)s."
msgstr "Última actualització el %(last_updated)s."
#: sphinx/themes/basic/layout.html:198
#: sphinx/themes/basic/layout.html:195
#, python-format
msgid ""
"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
@ -741,13 +771,13 @@ msgstr "cerca"
#: sphinx/themes/basic/search.html:43
#: sphinx/themes/basic/searchresults.html:21
#: sphinx/themes/basic/static/searchtools.js_t:282
#: sphinx/themes/basic/static/searchtools.js_t:287
msgid "Search Results"
msgstr "Resultats de la Cerca"
#: sphinx/themes/basic/search.html:45
#: sphinx/themes/basic/searchresults.html:23
#: sphinx/themes/basic/static/searchtools.js_t:284
#: sphinx/themes/basic/static/searchtools.js_t:289
msgid ""
"Your search did not match any documents. Please make sure that all words are"
" spelled correctly and that you've selected enough categories."
@ -764,13 +794,13 @@ msgstr "Aquesta Pàgina"
#: sphinx/themes/basic/changes/frameset.html:5
#: sphinx/themes/basic/changes/versionchanges.html:12
#, python-format
msgid "Changes in Version %(version)s &mdash; %(docstitle)s"
msgstr "Canvis a la Versió %(version)s &mdash; %(docstitle)s"
msgid "Changes in Version %(version)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/rstsource.html:5
#, python-format
msgid "%(filename)s &mdash; %(docstitle)s"
msgstr "%(filename)s &mdash; %(docstitle)s"
msgid "%(filename)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/versionchanges.html:17
#, python-format
@ -789,12 +819,13 @@ msgstr "Canvis a la API de C"
msgid "Other changes"
msgstr "Altres canvis"
#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:668
#: sphinx/writers/html.py:673
#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:708
#: sphinx/writers/html.py:713
msgid "Permalink to this headline"
msgstr "Link permanent a aquest títol"
#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:105
#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:108
#: sphinx/writers/html.py:117
msgid "Permalink to this definition"
msgstr "Link permanent a aquesta definició"
@ -810,12 +841,12 @@ msgstr ""
msgid "Preparing search..."
msgstr ""
#: sphinx/themes/basic/static/searchtools.js_t:286
#: sphinx/themes/basic/static/searchtools.js_t:291
#, python-format
msgid "Search finished, found %s page(s) matching the search query."
msgstr ""
#: sphinx/themes/basic/static/searchtools.js_t:338
#: sphinx/themes/basic/static/searchtools.js_t:344
msgid ", in "
msgstr ""
@ -832,48 +863,53 @@ msgstr ""
msgid "Contents"
msgstr ""
#: sphinx/writers/html.py:349
#: sphinx/writers/html.py:389
msgid "Permalink to this code"
msgstr ""
#: sphinx/writers/html.py:353
#: sphinx/writers/html.py:393
msgid "Permalink to this image"
msgstr ""
#: sphinx/writers/html.py:355
#: sphinx/writers/html.py:395
msgid "Permalink to this toctree"
msgstr ""
#: sphinx/writers/html.py:677
#: sphinx/writers/html.py:717
msgid "Permalink to this table"
msgstr ""
#: sphinx/writers/latex.py:361
#: sphinx/writers/latex.py:380
msgid "Release"
msgstr "Versió"
#: sphinx/writers/latex.py:427
#: sphinx/writers/latex.py:483
msgid "page"
msgstr ""
#: sphinx/writers/latex.py:920 sphinx/writers/manpage.py:233
#: sphinx/writers/texinfo.py:620
#: sphinx/writers/latex.py:528
#, python-format
msgid "Unknown configure key: latex_elements[%r] is ignored."
msgstr ""
#: sphinx/writers/latex.py:1003 sphinx/writers/manpage.py:238
#: sphinx/writers/texinfo.py:619
msgid "Footnotes"
msgstr ""
#: sphinx/writers/latex.py:1022
#: sphinx/writers/latex.py:1112
msgid "continued from previous page"
msgstr "ve de la pàgina anterior"
#: sphinx/writers/latex.py:1028
#: sphinx/writers/latex.py:1118
msgid "Continued on next page"
msgstr "Continua a la pàgina següent"
#: sphinx/writers/manpage.py:282 sphinx/writers/text.py:582
#: sphinx/writers/manpage.py:287 sphinx/writers/text.py:591
#, python-format
msgid "[image: %s]"
msgstr ""
#: sphinx/writers/manpage.py:283 sphinx/writers/text.py:583
#: sphinx/writers/manpage.py:288 sphinx/writers/text.py:592
msgid "[image]"
msgstr "[imatge]"

View File

@ -0,0 +1 @@
Documentation.addTranslations({"locale": "zh_Hans_CN", "messages": {"%(filename)s &#8212; %(docstitle)s": "", "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "", "&#169; Copyright %(copyright)s.": "", ", in ": "", "About these documents": "", "Automatically generated list of changes in version %(version)s": "", "C API changes": "", "Changes in Version %(version)s &#8212; %(docstitle)s": "", "Collapse sidebar": "", "Complete Table of Contents": "", "Contents": "", "Copyright": "", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "", "Expand sidebar": "", "From here you can search these documents. Enter your search\n words into the box below and click \"search\". Note that the search\n function will automatically search for all of the words. Pages\n containing fewer words won't appear in the result list.": "", "Full index on one page": "", "General Index": "", "Global Module Index": "", "Go": "", "Hide Search Matches": "", "Index": "", "Index &ndash; %(key)s": "", "Index pages by letter": "", "Indices and tables:": "", "Last updated on %(last_updated)s.": "", "Library changes": "", "Navigation": "", "Next topic": "", "Other changes": "", "Overview": "", "Permalink to this definition": "", "Permalink to this headline": "", "Please activate JavaScript to enable the search\n functionality.": "", "Preparing search...": "", "Previous topic": "", "Quick search": "", "Search": "", "Search Page": "", "Search Results": "", "Search finished, found %s page(s) matching the search query.": "", "Search within %(docstitle)s": "", "Searching": "", "Show Source": "", "Table Of Contents": "", "This Page": "", "Welcome! This is": "", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "", "all functions, classes, terms": "", "can be huge": "", "last updated": "", "lists all sections and subsections": "", "next chapter": "", "previous chapter": "", "quick access to all modules": "", "search": "", "search this documentation": "", "the documentation for": ""}, "plural_expr": "0"});

Binary file not shown.

View File

@ -0,0 +1,914 @@
# Translations template for Sphinx.
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the Sphinx project.
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: Sphinx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-11-06 22:40+0900\n"
"PO-Revision-Date: 2016-11-06 13:53+0000\n"
"Last-Translator: Takeshi KOMIYA <i.tkomiya@gmail.com>\n"
"Language-Team: Chinese (Mandarin) (http://www.transifex.com/sphinx-doc/sphinx-1/language/cmn/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n"
"Language: cmn\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: sphinx/config.py:109
#, python-format
msgid "Section %s"
msgstr ""
#: sphinx/config.py:110
#, python-format
msgid "Fig. %s"
msgstr ""
#: sphinx/config.py:111
#, python-format
msgid "Table %s"
msgstr ""
#: sphinx/config.py:112
#, python-format
msgid "Listing %s"
msgstr ""
#: sphinx/roles.py:187
#, python-format
msgid "Python Enhancement Proposals; PEP %s"
msgstr ""
#: sphinx/builders/changes.py:75
msgid "Builtins"
msgstr ""
#: sphinx/builders/changes.py:77
msgid "Module level"
msgstr ""
#: sphinx/builders/html.py:294 sphinx/transforms/__init__.py:46
#: sphinx/writers/latex.py:393 sphinx/writers/manpage.py:100
#: sphinx/writers/texinfo.py:221
#, python-format
msgid "%b %d, %Y"
msgstr ""
#: sphinx/builders/html.py:315 sphinx/themes/basic/defindex.html:30
msgid "General Index"
msgstr ""
#: sphinx/builders/html.py:315
msgid "index"
msgstr ""
#: sphinx/builders/html.py:377
msgid "next"
msgstr ""
#: sphinx/builders/html.py:386
msgid "previous"
msgstr ""
#: sphinx/builders/html.py:1222
#, python-format
msgid "%s %s documentation"
msgstr ""
#: sphinx/builders/latex.py:177 sphinx/builders/texinfo.py:199
msgid " (in "
msgstr ""
#: sphinx/directives/code.py:140 sphinx/directives/code.py:370
#, python-format
msgid "Invalid caption: %s"
msgstr ""
#: sphinx/directives/other.py:149
msgid "Section author: "
msgstr ""
#: sphinx/directives/other.py:151
msgid "Module author: "
msgstr ""
#: sphinx/directives/other.py:153
msgid "Code author: "
msgstr ""
#: sphinx/directives/other.py:155
msgid "Author: "
msgstr ""
#: sphinx/domains/__init__.py:277
#, python-format
msgid "%s %s"
msgstr ""
#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:4051
#: sphinx/domains/python.py:149
msgid "Parameters"
msgstr ""
#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:4060
#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:161
msgid "Returns"
msgstr ""
#: sphinx/domains/c.py:63 sphinx/domains/javascript.py:130
#: sphinx/domains/python.py:163
msgid "Return type"
msgstr ""
#: sphinx/domains/c.py:177
#, python-format
msgid "%s (C function)"
msgstr ""
#: sphinx/domains/c.py:179
#, python-format
msgid "%s (C member)"
msgstr ""
#: sphinx/domains/c.py:181
#, python-format
msgid "%s (C macro)"
msgstr ""
#: sphinx/domains/c.py:183
#, python-format
msgid "%s (C type)"
msgstr ""
#: sphinx/domains/c.py:185
#, python-format
msgid "%s (C variable)"
msgstr ""
#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:4418
#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:614
msgid "function"
msgstr ""
#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:4419
msgid "member"
msgstr ""
#: sphinx/domains/c.py:244
msgid "macro"
msgstr ""
#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:4420
msgid "type"
msgstr ""
#: sphinx/domains/c.py:246
msgid "variable"
msgstr ""
#: sphinx/domains/cpp.py:4054
msgid "Template Parameters"
msgstr ""
#: sphinx/domains/cpp.py:4057 sphinx/domains/javascript.py:125
msgid "Throws"
msgstr ""
#: sphinx/domains/cpp.py:4205
#, python-format
msgid "%s (C++ type)"
msgstr ""
#: sphinx/domains/cpp.py:4216
#, python-format
msgid "%s (C++ concept)"
msgstr ""
#: sphinx/domains/cpp.py:4227
#, python-format
msgid "%s (C++ member)"
msgstr ""
#: sphinx/domains/cpp.py:4238
#, python-format
msgid "%s (C++ function)"
msgstr ""
#: sphinx/domains/cpp.py:4249
#, python-format
msgid "%s (C++ class)"
msgstr ""
#: sphinx/domains/cpp.py:4260
#, python-format
msgid "%s (C++ enum)"
msgstr ""
#: sphinx/domains/cpp.py:4281
#, python-format
msgid "%s (C++ enumerator)"
msgstr ""
#: sphinx/domains/cpp.py:4417 sphinx/domains/javascript.py:165
#: sphinx/domains/python.py:616
msgid "class"
msgstr ""
#: sphinx/domains/cpp.py:4421
msgid "concept"
msgstr ""
#: sphinx/domains/cpp.py:4422
msgid "enum"
msgstr ""
#: sphinx/domains/cpp.py:4423
msgid "enumerator"
msgstr ""
#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:307
#, python-format
msgid "%s() (built-in function)"
msgstr ""
#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:371
#, python-format
msgid "%s() (%s method)"
msgstr ""
#: sphinx/domains/javascript.py:109
#, python-format
msgid "%s() (class)"
msgstr ""
#: sphinx/domains/javascript.py:111
#, python-format
msgid "%s (global variable or constant)"
msgstr ""
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:409
#, python-format
msgid "%s (%s attribute)"
msgstr ""
#: sphinx/domains/javascript.py:122
msgid "Arguments"
msgstr ""
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:615
msgid "data"
msgstr ""
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:621
msgid "attribute"
msgstr ""
#: sphinx/domains/python.py:154
msgid "Variables"
msgstr ""
#: sphinx/domains/python.py:158
msgid "Raises"
msgstr ""
#: sphinx/domains/python.py:308 sphinx/domains/python.py:365
#: sphinx/domains/python.py:377 sphinx/domains/python.py:390
#, python-format
msgid "%s() (in module %s)"
msgstr ""
#: sphinx/domains/python.py:311
#, python-format
msgid "%s (built-in variable)"
msgstr ""
#: sphinx/domains/python.py:312 sphinx/domains/python.py:403
#, python-format
msgid "%s (in module %s)"
msgstr ""
#: sphinx/domains/python.py:328
#, python-format
msgid "%s (built-in class)"
msgstr ""
#: sphinx/domains/python.py:329
#, python-format
msgid "%s (class in %s)"
msgstr ""
#: sphinx/domains/python.py:369
#, python-format
msgid "%s() (%s.%s method)"
msgstr ""
#: sphinx/domains/python.py:381
#, python-format
msgid "%s() (%s.%s static method)"
msgstr ""
#: sphinx/domains/python.py:384
#, python-format
msgid "%s() (%s static method)"
msgstr ""
#: sphinx/domains/python.py:394
#, python-format
msgid "%s() (%s.%s class method)"
msgstr ""
#: sphinx/domains/python.py:397
#, python-format
msgid "%s() (%s class method)"
msgstr ""
#: sphinx/domains/python.py:407
#, python-format
msgid "%s (%s.%s attribute)"
msgstr ""
#: sphinx/domains/python.py:488
#, python-format
msgid "%s (module)"
msgstr ""
#: sphinx/domains/python.py:545
msgid "Python Module Index"
msgstr ""
#: sphinx/domains/python.py:546
msgid "modules"
msgstr ""
#: sphinx/domains/python.py:592
msgid "Deprecated"
msgstr ""
#: sphinx/domains/python.py:617 sphinx/locale/__init__.py:183
msgid "exception"
msgstr ""
#: sphinx/domains/python.py:618
msgid "method"
msgstr ""
#: sphinx/domains/python.py:619
msgid "class method"
msgstr ""
#: sphinx/domains/python.py:620
msgid "static method"
msgstr ""
#: sphinx/domains/python.py:622 sphinx/locale/__init__.py:179
msgid "module"
msgstr ""
#: sphinx/domains/python.py:787
msgid " (deprecated)"
msgstr ""
#: sphinx/domains/rst.py:55
#, python-format
msgid "%s (directive)"
msgstr ""
#: sphinx/domains/rst.py:57
#, python-format
msgid "%s (role)"
msgstr ""
#: sphinx/domains/rst.py:106
msgid "directive"
msgstr ""
#: sphinx/domains/rst.py:107
msgid "role"
msgstr ""
#: sphinx/domains/std.py:72 sphinx/domains/std.py:88
#, python-format
msgid "environment variable; %s"
msgstr ""
#: sphinx/domains/std.py:186
#, python-format
msgid "%scommand line option; %s"
msgstr ""
#: sphinx/domains/std.py:434
msgid "glossary term"
msgstr ""
#: sphinx/domains/std.py:435
msgid "grammar token"
msgstr ""
#: sphinx/domains/std.py:436
msgid "reference label"
msgstr ""
#: sphinx/domains/std.py:438
msgid "environment variable"
msgstr ""
#: sphinx/domains/std.py:439
msgid "program option"
msgstr ""
#: sphinx/domains/std.py:473 sphinx/themes/basic/genindex-single.html:30
#: sphinx/themes/basic/genindex-single.html:55
#: sphinx/themes/basic/genindex-split.html:11
#: sphinx/themes/basic/genindex-split.html:14
#: sphinx/themes/basic/genindex.html:30 sphinx/themes/basic/genindex.html:33
#: sphinx/themes/basic/genindex.html:66 sphinx/themes/basic/layout.html:135
#: sphinx/writers/latex.py:381 sphinx/writers/texinfo.py:480
msgid "Index"
msgstr ""
#: sphinx/domains/std.py:474
msgid "Module Index"
msgstr ""
#: sphinx/domains/std.py:475 sphinx/themes/basic/defindex.html:25
msgid "Search Page"
msgstr ""
#: sphinx/environment/managers/indexentries.py:104
#, python-format
msgid "see %s"
msgstr ""
#: sphinx/environment/managers/indexentries.py:108
#, python-format
msgid "see also %s"
msgstr ""
#: sphinx/environment/managers/indexentries.py:168
msgid "Symbols"
msgstr ""
#: sphinx/ext/autodoc.py:1297
#, python-format
msgid "Bases: %s"
msgstr ""
#: sphinx/ext/autodoc.py:1350
#, python-format
msgid "alias of :class:`%s`"
msgstr ""
#: sphinx/ext/graphviz.py:331 sphinx/ext/graphviz.py:340
#, python-format
msgid "[graph: %s]"
msgstr ""
#: sphinx/ext/graphviz.py:333 sphinx/ext/graphviz.py:342
msgid "[graph]"
msgstr ""
#: sphinx/ext/imgmath.py:258 sphinx/ext/jsmath.py:39 sphinx/ext/mathjax.py:40
msgid "Permalink to this equation"
msgstr ""
#: sphinx/ext/intersphinx.py:337
#, python-format
msgid "(in %s v%s)"
msgstr ""
#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:103
msgid "[source]"
msgstr ""
#: sphinx/ext/mathbase.py:92
#, python-format
msgid "duplicate label of equation %s, other instance in %s"
msgstr ""
#: sphinx/ext/todo.py:56
msgid "Todo"
msgstr ""
#: sphinx/ext/todo.py:134
msgid "<<original entry>>"
msgstr ""
#: sphinx/ext/todo.py:137
#, python-format
msgid "(The <<original entry>> is located in %s, line %d.)"
msgstr ""
#: sphinx/ext/todo.py:146
msgid "original entry"
msgstr ""
#: sphinx/ext/viewcode.py:166
msgid "[docs]"
msgstr ""
#: sphinx/ext/viewcode.py:180
msgid "Module code"
msgstr ""
#: sphinx/ext/viewcode.py:186
#, python-format
msgid "<h1>Source code for %s</h1>"
msgstr ""
#: sphinx/ext/viewcode.py:212
msgid "Overview: module code"
msgstr ""
#: sphinx/ext/viewcode.py:213
msgid "<h1>All modules for which code is available</h1>"
msgstr ""
#: sphinx/ext/napoleon/__init__.py:313
msgid "Keyword Arguments"
msgstr ""
#: sphinx/locale/__init__.py:159
msgid "Attention"
msgstr ""
#: sphinx/locale/__init__.py:160
msgid "Caution"
msgstr ""
#: sphinx/locale/__init__.py:161
msgid "Danger"
msgstr ""
#: sphinx/locale/__init__.py:162
msgid "Error"
msgstr ""
#: sphinx/locale/__init__.py:163
msgid "Hint"
msgstr ""
#: sphinx/locale/__init__.py:164
msgid "Important"
msgstr ""
#: sphinx/locale/__init__.py:165
msgid "Note"
msgstr ""
#: sphinx/locale/__init__.py:166
msgid "See also"
msgstr ""
#: sphinx/locale/__init__.py:167
msgid "Tip"
msgstr ""
#: sphinx/locale/__init__.py:168
msgid "Warning"
msgstr ""
#: sphinx/locale/__init__.py:172
#, python-format
msgid "New in version %s"
msgstr ""
#: sphinx/locale/__init__.py:173
#, python-format
msgid "Changed in version %s"
msgstr ""
#: sphinx/locale/__init__.py:174
#, python-format
msgid "Deprecated since version %s"
msgstr ""
#: sphinx/locale/__init__.py:180
msgid "keyword"
msgstr ""
#: sphinx/locale/__init__.py:181
msgid "operator"
msgstr ""
#: sphinx/locale/__init__.py:182
msgid "object"
msgstr ""
#: sphinx/locale/__init__.py:184
msgid "statement"
msgstr ""
#: sphinx/locale/__init__.py:185
msgid "built-in function"
msgstr ""
#: sphinx/themes/agogo/layout.html:46 sphinx/themes/basic/globaltoc.html:10
#: sphinx/themes/basic/localtoc.html:11 sphinx/themes/scrolls/layout.html:35
msgid "Table Of Contents"
msgstr ""
#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:138
#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
#: sphinx/themes/basic/searchresults.html:10
msgid "Search"
msgstr ""
#: sphinx/themes/agogo/layout.html:54 sphinx/themes/basic/searchbox.html:15
msgid "Go"
msgstr ""
#: sphinx/themes/agogo/layout.html:81 sphinx/themes/basic/sourcelink.html:15
msgid "Show Source"
msgstr ""
#: sphinx/themes/basic/defindex.html:11
msgid "Overview"
msgstr ""
#: sphinx/themes/basic/defindex.html:15
msgid "Welcome! This is"
msgstr ""
#: sphinx/themes/basic/defindex.html:16
msgid "the documentation for"
msgstr ""
#: sphinx/themes/basic/defindex.html:17
msgid "last updated"
msgstr ""
#: sphinx/themes/basic/defindex.html:20
msgid "Indices and tables:"
msgstr ""
#: sphinx/themes/basic/defindex.html:23
msgid "Complete Table of Contents"
msgstr ""
#: sphinx/themes/basic/defindex.html:24
msgid "lists all sections and subsections"
msgstr ""
#: sphinx/themes/basic/defindex.html:26
msgid "search this documentation"
msgstr ""
#: sphinx/themes/basic/defindex.html:28
msgid "Global Module Index"
msgstr ""
#: sphinx/themes/basic/defindex.html:29
msgid "quick access to all modules"
msgstr ""
#: sphinx/themes/basic/defindex.html:31
msgid "all functions, classes, terms"
msgstr ""
#: sphinx/themes/basic/genindex-single.html:33
#, python-format
msgid "Index &ndash; %(key)s"
msgstr ""
#: sphinx/themes/basic/genindex-single.html:61
#: sphinx/themes/basic/genindex-split.html:24
#: sphinx/themes/basic/genindex-split.html:38
#: sphinx/themes/basic/genindex.html:72
msgid "Full index on one page"
msgstr ""
#: sphinx/themes/basic/genindex-split.html:16
msgid "Index pages by letter"
msgstr ""
#: sphinx/themes/basic/genindex-split.html:25
msgid "can be huge"
msgstr ""
#: sphinx/themes/basic/layout.html:29
msgid "Navigation"
msgstr ""
#: sphinx/themes/basic/layout.html:123
#, python-format
msgid "Search within %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/layout.html:132
msgid "About these documents"
msgstr ""
#: sphinx/themes/basic/layout.html:141
msgid "Copyright"
msgstr ""
#: sphinx/themes/basic/layout.html:186
#, python-format
msgid "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:188
#, python-format
msgid "&#169; Copyright %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:192
#, python-format
msgid "Last updated on %(last_updated)s."
msgstr ""
#: sphinx/themes/basic/layout.html:195
#, python-format
msgid ""
"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
"%(sphinx_version)s."
msgstr ""
#: sphinx/themes/basic/opensearch.xml:4
#, python-format
msgid "Search %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/relations.html:11
msgid "Previous topic"
msgstr ""
#: sphinx/themes/basic/relations.html:13
msgid "previous chapter"
msgstr ""
#: sphinx/themes/basic/relations.html:16
msgid "Next topic"
msgstr ""
#: sphinx/themes/basic/relations.html:18
msgid "next chapter"
msgstr ""
#: sphinx/themes/basic/search.html:27
msgid ""
"Please activate JavaScript to enable the search\n"
" functionality."
msgstr ""
#: sphinx/themes/basic/search.html:32
msgid ""
"From here you can search these documents. Enter your search\n"
" words into the box below and click \"search\". Note that the search\n"
" function will automatically search for all of the words. Pages\n"
" containing fewer words won't appear in the result list."
msgstr ""
#: sphinx/themes/basic/search.html:39
#: sphinx/themes/basic/searchresults.html:17
msgid "search"
msgstr ""
#: sphinx/themes/basic/search.html:43
#: sphinx/themes/basic/searchresults.html:21
#: sphinx/themes/basic/static/searchtools.js_t:287
msgid "Search Results"
msgstr ""
#: sphinx/themes/basic/search.html:45
#: sphinx/themes/basic/searchresults.html:23
#: sphinx/themes/basic/static/searchtools.js_t:289
msgid ""
"Your search did not match any documents. Please make sure that all words are"
" spelled correctly and that you've selected enough categories."
msgstr ""
#: sphinx/themes/basic/searchbox.html:12
msgid "Quick search"
msgstr ""
#: sphinx/themes/basic/sourcelink.html:12
msgid "This Page"
msgstr ""
#: sphinx/themes/basic/changes/frameset.html:5
#: sphinx/themes/basic/changes/versionchanges.html:12
#, python-format
msgid "Changes in Version %(version)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/rstsource.html:5
#, python-format
msgid "%(filename)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/versionchanges.html:17
#, python-format
msgid "Automatically generated list of changes in version %(version)s"
msgstr ""
#: sphinx/themes/basic/changes/versionchanges.html:18
msgid "Library changes"
msgstr ""
#: sphinx/themes/basic/changes/versionchanges.html:23
msgid "C API changes"
msgstr ""
#: sphinx/themes/basic/changes/versionchanges.html:25
msgid "Other changes"
msgstr ""
#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:708
#: sphinx/writers/html.py:713
msgid "Permalink to this headline"
msgstr ""
#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:108
#: sphinx/writers/html.py:117
msgid "Permalink to this definition"
msgstr ""
#: sphinx/themes/basic/static/doctools.js_t:208
msgid "Hide Search Matches"
msgstr ""
#: sphinx/themes/basic/static/searchtools.js_t:121
msgid "Searching"
msgstr ""
#: sphinx/themes/basic/static/searchtools.js_t:126
msgid "Preparing search..."
msgstr ""
#: sphinx/themes/basic/static/searchtools.js_t:291
#, python-format
msgid "Search finished, found %s page(s) matching the search query."
msgstr ""
#: sphinx/themes/basic/static/searchtools.js_t:344
msgid ", in "
msgstr ""
#: sphinx/themes/classic/static/sidebar.js_t:83
msgid "Expand sidebar"
msgstr ""
#: sphinx/themes/classic/static/sidebar.js_t:96
#: sphinx/themes/classic/static/sidebar.js_t:124
msgid "Collapse sidebar"
msgstr ""
#: sphinx/themes/haiku/layout.html:24
msgid "Contents"
msgstr ""
#: sphinx/writers/html.py:389
msgid "Permalink to this code"
msgstr ""
#: sphinx/writers/html.py:393
msgid "Permalink to this image"
msgstr ""
#: sphinx/writers/html.py:395
msgid "Permalink to this toctree"
msgstr ""
#: sphinx/writers/html.py:717
msgid "Permalink to this table"
msgstr ""
#: sphinx/writers/latex.py:380
msgid "Release"
msgstr ""
#: sphinx/writers/latex.py:483
msgid "page"
msgstr ""
#: sphinx/writers/latex.py:528
#, python-format
msgid "Unknown configure key: latex_elements[%r] is ignored."
msgstr ""
#: sphinx/writers/latex.py:1003 sphinx/writers/manpage.py:238
#: sphinx/writers/texinfo.py:619
msgid "Footnotes"
msgstr ""
#: sphinx/writers/latex.py:1112
msgid "continued from previous page"
msgstr ""
#: sphinx/writers/latex.py:1118
msgid "Continued on next page"
msgstr ""
#: sphinx/writers/manpage.py:287 sphinx/writers/text.py:591
#, python-format
msgid "[image: %s]"
msgstr ""
#: sphinx/writers/manpage.py:288 sphinx/writers/text.py:592
msgid "[image]"
msgstr ""

View File

@ -1 +1 @@
Documentation.addTranslations({"locale": "cs", "messages": {"%(filename)s &mdash; %(docstitle)s": "%(filename)s &mdash; %(docstitle)s", "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s.", "&copy; Copyright %(copyright)s.": "&copy; Copyright %(copyright)s.", ", in ": ", v ", "About these documents": "O t\u011bchto dokumentech", "Automatically generated list of changes in version %(version)s": "Automaticky generovan\u00fd seznam zm\u011bn ve verzi %(version)s", "C API changes": "Zm\u011bny API", "Changes in Version %(version)s &mdash; %(docstitle)s": "Zm\u011bny ve verzi %(version)s &mdash; %(docstitle)s", "Collapse sidebar": "Sbalit bo\u010dn\u00ed li\u0161tu", "Complete Table of Contents": "Celkov\u00fd obsah", "Contents": "Obsah", "Copyright": "Ve\u0161ker\u00e1 pr\u00e1va vyhrazena", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "Vytvo\u0159eno pomoc\u00ed <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.", "Expand sidebar": "Rozbalit bo\u010dn\u00ed li\u0161tu", "From here you can search these documents. Enter your search\n words into the box below and click \"search\". Note that the search\n function will automatically search for all of the words. Pages\n containing fewer words won't appear in the result list.": "Toto je vyhled\u00e1vac\u00ed str\u00e1nka. Zadejte kl\u00ed\u010dov\u00e1 slova a klikn\u011bte na \"hledat\". \nVyhled\u00e1v\u00e1n\u00ed automaticky hled\u00e1 v\u0161echna slova, nebudou tedy nalezeny str\u00e1nky obsahuj\u00edc\u00ed jen n\u011bkter\u00e9 z nich.", "Full index on one page": "Cel\u00fd rejst\u0159\u00edk na jedn\u00e9 str\u00e1nce", "General Index": "Obecn\u00fd rejst\u0159\u00edk", "Global Module Index": "Celkov\u00fd rejst\u0159\u00edk modul\u016f", "Go": "OK", "Hide Search Matches": "Skr\u00fdt v\u00fdsledky vyhled\u00e1v\u00e1n\u00ed", "Index": "Rejst\u0159\u00edk", "Index &ndash; %(key)s": "Rejst\u0159\u00edk &ndash; %(key)s", "Index pages by letter": "Rejst\u0159\u00edk podle p\u00edsmene", "Indices and tables:": "Rejst\u0159\u00edky a tabulky:", "Last updated on %(last_updated)s.": "Aktualizov\u00e1no dne %(last_updated)s.", "Library changes": "Zm\u011bny v knihovn\u00e1ch", "Navigation": "Navigace", "Next topic": "Dal\u0161\u00ed t\u00e9ma", "Other changes": "Ostatn\u00ed zm\u011bny", "Overview": "P\u0159ehled", "Permalink to this definition": "Trval\u00fd odkaz na tuto definici", "Permalink to this headline": "Trval\u00fd odkaz na tento nadpis", "Please activate JavaScript to enable the search\n functionality.": "Pro podporu vyhled\u00e1v\u00e1n\u00ed aktivujte JavaScript.", "Preparing search...": "Vyhled\u00e1v\u00e1n\u00ed se p\u0159ipravuje...", "Previous topic": "P\u0159echoz\u00ed t\u00e9ma", "Quick search": "Rychl\u00e9 vyhled\u00e1v\u00e1n\u00ed", "Search": "Vyhled\u00e1v\u00e1n\u00ed", "Search Page": "Vyhled\u00e1vac\u00ed str\u00e1nka", "Search Results": "V\u00fdsledky vyhled\u00e1v\u00e1n\u00ed", "Search finished, found %s page(s) matching the search query.": "Vyhled\u00e1v\u00e1n\u00ed dokon\u010deno, str\u00e1nky odpov\u00eddaj\u00edc\u00ed hledan\u00e9mu v\u00fdrazu: %s.", "Search within %(docstitle)s": "Prohledat %(docstitle)s", "Searching": "Prob\u00edh\u00e1 vyhled\u00e1n\u00ed", "Show Source": "Uk\u00e1zat zdroj", "Table Of Contents": "Obsah", "This Page": "Tato str\u00e1nka", "Welcome! This is": "V\u00edtejte! Toto je", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Vyhled\u00e1v\u00e1n\u00ed nenalezlo \u017e\u00e1dn\u00fd odpov\u00eddaj\u00edc\u00ed dokument. Ujist\u011bte se, \u017ee jste v\u0161echna slova zapsal/a spr\u00e1vn\u011b a \u017ee jste vybral/a dostatek kategori\u00ed.", "all functions, classes, terms": "v\u0161echny funkce, t\u0159\u00eddy, term\u00edny", "can be huge": "m\u016f\u017ee b\u00fdt obrovsk\u00fd", "last updated": "naposledy aktualizov\u00e1no", "lists all sections and subsections": "seznam v\u0161ech sekc\u00ed a podsekc\u00ed", "next chapter": "dal\u0161\u00ed kapitola", "previous chapter": "p\u0159edchoz\u00ed kapitola", "quick access to all modules": "rychl\u00fd p\u0159\u00edstup ke v\u0161em modul\u016fm", "search": "hledat", "search this documentation": "prohledat tuto dokumentaci", "the documentation for": "dokumentace pro"}, "plural_expr": "(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2"});
Documentation.addTranslations({"locale": "cs", "messages": {"%(filename)s &#8212; %(docstitle)s": "", "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "", "&#169; Copyright %(copyright)s.": "", ", in ": ", v ", "About these documents": "O t\u011bchto dokumentech", "Automatically generated list of changes in version %(version)s": "Automaticky generovan\u00fd seznam zm\u011bn ve verzi %(version)s", "C API changes": "Zm\u011bny API", "Changes in Version %(version)s &#8212; %(docstitle)s": "", "Collapse sidebar": "Sbalit bo\u010dn\u00ed li\u0161tu", "Complete Table of Contents": "Celkov\u00fd obsah", "Contents": "Obsah", "Copyright": "Ve\u0161ker\u00e1 pr\u00e1va vyhrazena", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "Vytvo\u0159eno pomoc\u00ed <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.", "Expand sidebar": "Rozbalit bo\u010dn\u00ed li\u0161tu", "From here you can search these documents. Enter your search\n words into the box below and click \"search\". Note that the search\n function will automatically search for all of the words. Pages\n containing fewer words won't appear in the result list.": "Toto je vyhled\u00e1vac\u00ed str\u00e1nka. Zadejte kl\u00ed\u010dov\u00e1 slova a klikn\u011bte na \"hledat\". \nVyhled\u00e1v\u00e1n\u00ed automaticky hled\u00e1 v\u0161echna slova, nebudou tedy nalezeny str\u00e1nky obsahuj\u00edc\u00ed jen n\u011bkter\u00e9 z nich.", "Full index on one page": "Cel\u00fd rejst\u0159\u00edk na jedn\u00e9 str\u00e1nce", "General Index": "Obecn\u00fd rejst\u0159\u00edk", "Global Module Index": "Celkov\u00fd rejst\u0159\u00edk modul\u016f", "Go": "OK", "Hide Search Matches": "Skr\u00fdt v\u00fdsledky vyhled\u00e1v\u00e1n\u00ed", "Index": "Rejst\u0159\u00edk", "Index &ndash; %(key)s": "Rejst\u0159\u00edk &ndash; %(key)s", "Index pages by letter": "Rejst\u0159\u00edk podle p\u00edsmene", "Indices and tables:": "Rejst\u0159\u00edky a tabulky:", "Last updated on %(last_updated)s.": "Aktualizov\u00e1no dne %(last_updated)s.", "Library changes": "Zm\u011bny v knihovn\u00e1ch", "Navigation": "Navigace", "Next topic": "Dal\u0161\u00ed t\u00e9ma", "Other changes": "Ostatn\u00ed zm\u011bny", "Overview": "P\u0159ehled", "Permalink to this definition": "Trval\u00fd odkaz na tuto definici", "Permalink to this headline": "Trval\u00fd odkaz na tento nadpis", "Please activate JavaScript to enable the search\n functionality.": "Pro podporu vyhled\u00e1v\u00e1n\u00ed aktivujte JavaScript.", "Preparing search...": "Vyhled\u00e1v\u00e1n\u00ed se p\u0159ipravuje...", "Previous topic": "P\u0159echoz\u00ed t\u00e9ma", "Quick search": "Rychl\u00e9 vyhled\u00e1v\u00e1n\u00ed", "Search": "Vyhled\u00e1v\u00e1n\u00ed", "Search Page": "Vyhled\u00e1vac\u00ed str\u00e1nka", "Search Results": "V\u00fdsledky vyhled\u00e1v\u00e1n\u00ed", "Search finished, found %s page(s) matching the search query.": "Vyhled\u00e1v\u00e1n\u00ed dokon\u010deno, str\u00e1nky odpov\u00eddaj\u00edc\u00ed hledan\u00e9mu v\u00fdrazu: %s.", "Search within %(docstitle)s": "Prohledat %(docstitle)s", "Searching": "Prob\u00edh\u00e1 vyhled\u00e1n\u00ed", "Show Source": "Uk\u00e1zat zdroj", "Table Of Contents": "Obsah", "This Page": "Tato str\u00e1nka", "Welcome! This is": "V\u00edtejte! Toto je", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Vyhled\u00e1v\u00e1n\u00ed nenalezlo \u017e\u00e1dn\u00fd odpov\u00eddaj\u00edc\u00ed dokument. Ujist\u011bte se, \u017ee jste v\u0161echna slova zapsal/a spr\u00e1vn\u011b a \u017ee jste vybral/a dostatek kategori\u00ed.", "all functions, classes, terms": "v\u0161echny funkce, t\u0159\u00eddy, term\u00edny", "can be huge": "m\u016f\u017ee b\u00fdt obrovsk\u00fd", "last updated": "naposledy aktualizov\u00e1no", "lists all sections and subsections": "seznam v\u0161ech sekc\u00ed a podsekc\u00ed", "next chapter": "dal\u0161\u00ed kapitola", "previous chapter": "p\u0159edchoz\u00ed kapitola", "quick access to all modules": "rychl\u00fd p\u0159\u00edstup ke v\u0161em modul\u016fm", "search": "hledat", "search this documentation": "prohledat tuto dokumentaci", "the documentation for": "dokumentace pro"}, "plural_expr": "(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2"});

View File

@ -9,61 +9,42 @@ msgid ""
msgstr ""
"Project-Id-Version: Sphinx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-03-06 21:58+0900\n"
"PO-Revision-Date: 2016-03-06 13:01+0000\n"
"Last-Translator: Takayuki Shimizukawa <shimizukawa@gmail.com>\n"
"POT-Creation-Date: 2016-11-06 22:40+0900\n"
"PO-Revision-Date: 2016-11-06 13:53+0000\n"
"Last-Translator: Takeshi KOMIYA <i.tkomiya@gmail.com>\n"
"Language-Team: Czech (http://www.transifex.com/sphinx-doc/sphinx-1/language/cs/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.2.0\n"
"Generated-By: Babel 2.3.4\n"
"Language: cs\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
#: sphinx/config.py:91
#: sphinx/config.py:109
#, python-format
msgid "Section %s"
msgstr ""
#: sphinx/config.py:110
#, python-format
msgid "Fig. %s"
msgstr "Obr. %s"
#: sphinx/config.py:92
#: sphinx/config.py:111
#, python-format
msgid "Table %s"
msgstr "Tabulka %s"
#: sphinx/config.py:93
#: sphinx/config.py:112
#, python-format
msgid "Listing %s"
msgstr "Výpis %s"
#: sphinx/config.py:100
#, python-format
msgid "%s %s documentation"
msgstr "Dokumentace pro %s %s"
#: sphinx/environment.py:1829
#, python-format
msgid "see %s"
msgstr "viz %s"
#: sphinx/environment.py:1833
#, python-format
msgid "see also %s"
msgstr "viz také %s"
#: sphinx/environment.py:1893
msgid "Symbols"
msgstr "Symboly"
#: sphinx/roles.py:193
#: sphinx/roles.py:187
#, python-format
msgid "Python Enhancement Proposals; PEP %s"
msgstr "Python Enhancement Proposals; PEP %s"
#: sphinx/transforms.py:56 sphinx/writers/latex.py:374
#: sphinx/writers/manpage.py:101 sphinx/writers/texinfo.py:222
msgid "MMMM dd, YYYY"
msgstr ""
#: sphinx/builders/changes.py:75
msgid "Builtins"
msgstr "Vestavěné funkce"
@ -72,8 +53,11 @@ msgstr "Vestavěné funkce"
msgid "Module level"
msgstr "Úroveň modulu"
#: sphinx/builders/html.py:295
msgid "MMM dd, YYYY"
#: sphinx/builders/html.py:294 sphinx/transforms/__init__.py:46
#: sphinx/writers/latex.py:393 sphinx/writers/manpage.py:100
#: sphinx/writers/texinfo.py:221
#, python-format
msgid "%b %d, %Y"
msgstr ""
#: sphinx/builders/html.py:315 sphinx/themes/basic/defindex.html:30
@ -84,18 +68,28 @@ msgstr "Obecný rejstřík"
msgid "index"
msgstr "rejstřík"
#: sphinx/builders/html.py:376
#: sphinx/builders/html.py:377
msgid "next"
msgstr "další"
#: sphinx/builders/html.py:385
#: sphinx/builders/html.py:386
msgid "previous"
msgstr "předchozí"
#: sphinx/builders/latex.py:180 sphinx/builders/texinfo.py:199
#: sphinx/builders/html.py:1222
#, python-format
msgid "%s %s documentation"
msgstr "Dokumentace pro %s %s"
#: sphinx/builders/latex.py:177 sphinx/builders/texinfo.py:199
msgid " (in "
msgstr " (v "
#: sphinx/directives/code.py:140 sphinx/directives/code.py:370
#, python-format
msgid "Invalid caption: %s"
msgstr ""
#: sphinx/directives/other.py:149
msgid "Section author: "
msgstr "Autor sekce: "
@ -112,23 +106,23 @@ msgstr "Autor kódu:"
msgid "Author: "
msgstr "Autor: "
#: sphinx/domains/__init__.py:275
#: sphinx/domains/__init__.py:277
#, python-format
msgid "%s %s"
msgstr "%s %s"
#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:3605
#: sphinx/domains/python.py:124
#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:4051
#: sphinx/domains/python.py:149
msgid "Parameters"
msgstr "Parametry"
#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:3614
#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:136
#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:4060
#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:161
msgid "Returns"
msgstr "Vrací"
#: sphinx/domains/c.py:63 sphinx/domains/javascript.py:130
#: sphinx/domains/python.py:138
#: sphinx/domains/python.py:163
msgid "Return type"
msgstr "Typ návratové hodnoty"
@ -157,12 +151,12 @@ msgstr "%s (C typ)"
msgid "%s (C variable)"
msgstr "%s (C proměnná)"
#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:3953
#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:589
#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:4418
#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:614
msgid "function"
msgstr "funkce"
#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:3954
#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:4419
msgid "member"
msgstr "člen"
@ -170,7 +164,7 @@ msgstr "člen"
msgid "macro"
msgstr "makro"
#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:3955
#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:4420
msgid "type"
msgstr "typ"
@ -178,63 +172,72 @@ msgstr "typ"
msgid "variable"
msgstr "proměnná"
#: sphinx/domains/cpp.py:3608
#: sphinx/domains/cpp.py:4054
msgid "Template Parameters"
msgstr ""
#: sphinx/domains/cpp.py:3611 sphinx/domains/javascript.py:125
#: sphinx/domains/cpp.py:4057 sphinx/domains/javascript.py:125
msgid "Throws"
msgstr "Vyvolá"
#: sphinx/domains/cpp.py:3733
#: sphinx/domains/cpp.py:4205
#, python-format
msgid "%s (C++ type)"
msgstr "%s (C++ typ)"
#: sphinx/domains/cpp.py:3744
#: sphinx/domains/cpp.py:4216
#, python-format
msgid "%s (C++ concept)"
msgstr ""
#: sphinx/domains/cpp.py:4227
#, python-format
msgid "%s (C++ member)"
msgstr "%s (C++ člen)"
#: sphinx/domains/cpp.py:3755
#: sphinx/domains/cpp.py:4238
#, python-format
msgid "%s (C++ function)"
msgstr "%s (C++ funkce)"
#: sphinx/domains/cpp.py:3766
#: sphinx/domains/cpp.py:4249
#, python-format
msgid "%s (C++ class)"
msgstr "%s (C++ třída)"
#: sphinx/domains/cpp.py:3786
#: sphinx/domains/cpp.py:4260
#, python-format
msgid "%s (C++ enum)"
msgstr ""
#: sphinx/domains/cpp.py:3816
#: sphinx/domains/cpp.py:4281
#, python-format
msgid "%s (C++ enumerator)"
msgstr ""
#: sphinx/domains/cpp.py:3952 sphinx/domains/javascript.py:165
#: sphinx/domains/python.py:591
#: sphinx/domains/cpp.py:4417 sphinx/domains/javascript.py:165
#: sphinx/domains/python.py:616
msgid "class"
msgstr "třída"
#: sphinx/domains/cpp.py:3956
#: sphinx/domains/cpp.py:4421
msgid "concept"
msgstr ""
#: sphinx/domains/cpp.py:4422
msgid "enum"
msgstr ""
#: sphinx/domains/cpp.py:3957
#: sphinx/domains/cpp.py:4423
msgid "enumerator"
msgstr ""
#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:282
#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:307
#, python-format
msgid "%s() (built-in function)"
msgstr "%s() (vestavěná funkce)"
#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:346
#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:371
#, python-format
msgid "%s() (%s method)"
msgstr "%s() (metoda %s)"
@ -249,7 +252,7 @@ msgstr "%s() (třída)"
msgid "%s (global variable or constant)"
msgstr "%s (globální proměnná nebo konstanta)"
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:384
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:409
#, python-format
msgid "%s (%s attribute)"
msgstr "%s (atribut %s)"
@ -258,116 +261,116 @@ msgstr "%s (atribut %s)"
msgid "Arguments"
msgstr "Argumenty"
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:590
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:615
msgid "data"
msgstr "data"
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:596
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:621
msgid "attribute"
msgstr "atribut"
#: sphinx/domains/python.py:129
#: sphinx/domains/python.py:154
msgid "Variables"
msgstr "Proměnné"
#: sphinx/domains/python.py:133
#: sphinx/domains/python.py:158
msgid "Raises"
msgstr "Vyvolá"
#: sphinx/domains/python.py:283 sphinx/domains/python.py:340
#: sphinx/domains/python.py:352 sphinx/domains/python.py:365
#: sphinx/domains/python.py:308 sphinx/domains/python.py:365
#: sphinx/domains/python.py:377 sphinx/domains/python.py:390
#, python-format
msgid "%s() (in module %s)"
msgstr "%s() (v modulu %s)"
#: sphinx/domains/python.py:286
#: sphinx/domains/python.py:311
#, python-format
msgid "%s (built-in variable)"
msgstr "%s (vestavěná proměnná)"
#: sphinx/domains/python.py:287 sphinx/domains/python.py:378
#: sphinx/domains/python.py:312 sphinx/domains/python.py:403
#, python-format
msgid "%s (in module %s)"
msgstr "%s (v modulu %s)"
#: sphinx/domains/python.py:303
#: sphinx/domains/python.py:328
#, python-format
msgid "%s (built-in class)"
msgstr "%s (vestavěná třída)"
#: sphinx/domains/python.py:304
#: sphinx/domains/python.py:329
#, python-format
msgid "%s (class in %s)"
msgstr "%s (třída v %s)"
#: sphinx/domains/python.py:344
#: sphinx/domains/python.py:369
#, python-format
msgid "%s() (%s.%s method)"
msgstr "%s() (metoda %s.%s)"
#: sphinx/domains/python.py:356
#: sphinx/domains/python.py:381
#, python-format
msgid "%s() (%s.%s static method)"
msgstr "%s() (statická metoda %s.%s)"
#: sphinx/domains/python.py:359
#: sphinx/domains/python.py:384
#, python-format
msgid "%s() (%s static method)"
msgstr "%s() (statická metoda %s)"
#: sphinx/domains/python.py:369
#: sphinx/domains/python.py:394
#, python-format
msgid "%s() (%s.%s class method)"
msgstr "%s() (třídní metoda %s.%s)"
#: sphinx/domains/python.py:372
#: sphinx/domains/python.py:397
#, python-format
msgid "%s() (%s class method)"
msgstr "%s() (třídní metoda %s)"
#: sphinx/domains/python.py:382
#: sphinx/domains/python.py:407
#, python-format
msgid "%s (%s.%s attribute)"
msgstr "%s (atribut %s.%s)"
#: sphinx/domains/python.py:463
#: sphinx/domains/python.py:488
#, python-format
msgid "%s (module)"
msgstr "%s (modul)"
#: sphinx/domains/python.py:520
#: sphinx/domains/python.py:545
msgid "Python Module Index"
msgstr "Rejstřík modulů Pythonu"
#: sphinx/domains/python.py:521
#: sphinx/domains/python.py:546
msgid "modules"
msgstr "moduly"
#: sphinx/domains/python.py:567
#: sphinx/domains/python.py:592
msgid "Deprecated"
msgstr "Zastaralé"
#: sphinx/domains/python.py:592 sphinx/locale/__init__.py:183
#: sphinx/domains/python.py:617 sphinx/locale/__init__.py:183
msgid "exception"
msgstr "výjimka"
#: sphinx/domains/python.py:593
#: sphinx/domains/python.py:618
msgid "method"
msgstr "metoda"
#: sphinx/domains/python.py:594
#: sphinx/domains/python.py:619
msgid "class method"
msgstr "třídní metoda"
#: sphinx/domains/python.py:595
#: sphinx/domains/python.py:620
msgid "static method"
msgstr "statická metoda"
#: sphinx/domains/python.py:597 sphinx/locale/__init__.py:179
#: sphinx/domains/python.py:622 sphinx/locale/__init__.py:179
msgid "module"
msgstr "modul"
#: sphinx/domains/python.py:762
#: sphinx/domains/python.py:787
msgid " (deprecated)"
msgstr " (zastaralé)"
@ -389,120 +392,147 @@ msgstr "direktiva"
msgid "role"
msgstr "role"
#: sphinx/domains/std.py:73 sphinx/domains/std.py:89
#: sphinx/domains/std.py:72 sphinx/domains/std.py:88
#, python-format
msgid "environment variable; %s"
msgstr "proměnná prostředí; %s"
#: sphinx/domains/std.py:185
#: sphinx/domains/std.py:186
#, python-format
msgid "%scommand line option; %s"
msgstr "%svolba příkazového řádku; %s"
#: sphinx/domains/std.py:433
#: sphinx/domains/std.py:434
msgid "glossary term"
msgstr "termín v glosáři"
#: sphinx/domains/std.py:434
#: sphinx/domains/std.py:435
msgid "grammar token"
msgstr "token gramatiky"
#: sphinx/domains/std.py:435
#: sphinx/domains/std.py:436
msgid "reference label"
msgstr "referenční návěstí"
#: sphinx/domains/std.py:437
#: sphinx/domains/std.py:438
msgid "environment variable"
msgstr "proměnná prostředí"
#: sphinx/domains/std.py:438
#: sphinx/domains/std.py:439
msgid "program option"
msgstr "volba programu"
#: sphinx/domains/std.py:471 sphinx/themes/basic/genindex-single.html:32
#: sphinx/themes/basic/genindex-single.html:57
#: sphinx/domains/std.py:473 sphinx/themes/basic/genindex-single.html:30
#: sphinx/themes/basic/genindex-single.html:55
#: sphinx/themes/basic/genindex-split.html:11
#: sphinx/themes/basic/genindex-split.html:14
#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
#: sphinx/writers/latex.py:363 sphinx/writers/texinfo.py:481
#: sphinx/themes/basic/genindex.html:30 sphinx/themes/basic/genindex.html:33
#: sphinx/themes/basic/genindex.html:66 sphinx/themes/basic/layout.html:135
#: sphinx/writers/latex.py:381 sphinx/writers/texinfo.py:480
msgid "Index"
msgstr "Rejstřík"
#: sphinx/domains/std.py:472
#: sphinx/domains/std.py:474
msgid "Module Index"
msgstr "Rejstřík modulů"
#: sphinx/domains/std.py:473 sphinx/themes/basic/defindex.html:25
#: sphinx/domains/std.py:475 sphinx/themes/basic/defindex.html:25
msgid "Search Page"
msgstr "Vyhledávací stránka"
#: sphinx/ext/autodoc.py:1265
#: sphinx/environment/managers/indexentries.py:104
#, python-format
msgid " Bases: %s"
msgstr " Nadtřídy: %s"
msgid "see %s"
msgstr "viz %s"
#: sphinx/ext/autodoc.py:1318
#: sphinx/environment/managers/indexentries.py:108
#, python-format
msgid "see also %s"
msgstr "viz také %s"
#: sphinx/environment/managers/indexentries.py:168
msgid "Symbols"
msgstr "Symboly"
#: sphinx/ext/autodoc.py:1297
#, python-format
msgid "Bases: %s"
msgstr ""
#: sphinx/ext/autodoc.py:1350
#, python-format
msgid "alias of :class:`%s`"
msgstr "alias třídy :class:`%s`"
#: sphinx/ext/graphviz.py:309 sphinx/ext/graphviz.py:318
#: sphinx/ext/graphviz.py:331 sphinx/ext/graphviz.py:340
#, python-format
msgid "[graph: %s]"
msgstr "[graf: %s]"
#: sphinx/ext/graphviz.py:311 sphinx/ext/graphviz.py:320
#: sphinx/ext/graphviz.py:333 sphinx/ext/graphviz.py:342
msgid "[graph]"
msgstr "[graf]"
#: sphinx/ext/intersphinx.py:359
#: sphinx/ext/imgmath.py:258 sphinx/ext/jsmath.py:39 sphinx/ext/mathjax.py:40
msgid "Permalink to this equation"
msgstr ""
#: sphinx/ext/intersphinx.py:337
#, python-format
msgid "(in %s v%s)"
msgstr "(v %s v%s)"
#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:99
#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:103
msgid "[source]"
msgstr "[zdroj]"
#: sphinx/ext/mathbase.py:92
#, python-format
msgid "duplicate label of equation %s, other instance in %s"
msgstr ""
#: sphinx/ext/todo.py:56
msgid "Todo"
msgstr "Todo"
#: sphinx/ext/todo.py:129
#: sphinx/ext/todo.py:134
msgid "<<original entry>>"
msgstr ""
#: sphinx/ext/todo.py:132
#: sphinx/ext/todo.py:137
#, python-format
msgid "(The <<original entry>> is located in %s, line %d.)"
msgstr ""
#: sphinx/ext/todo.py:141
#: sphinx/ext/todo.py:146
msgid "original entry"
msgstr "původní záznam"
#: sphinx/ext/viewcode.py:162
#: sphinx/ext/viewcode.py:166
msgid "[docs]"
msgstr "[dokumentace]"
#: sphinx/ext/viewcode.py:176
#: sphinx/ext/viewcode.py:180
msgid "Module code"
msgstr "Kód modulu"
#: sphinx/ext/viewcode.py:182
#: sphinx/ext/viewcode.py:186
#, python-format
msgid "<h1>Source code for %s</h1>"
msgstr "<h1>Zdrojový kód pro %s</h1>"
#: sphinx/ext/viewcode.py:208
#: sphinx/ext/viewcode.py:212
msgid "Overview: module code"
msgstr "Přehled: kód modulu"
#: sphinx/ext/viewcode.py:209
#: sphinx/ext/viewcode.py:213
msgid "<h1>All modules for which code is available</h1>"
msgstr "<h1>Všechny moduly s dostupným kódem</h1>"
#: sphinx/ext/napoleon/__init__.py:313
msgid "Keyword Arguments"
msgstr ""
#: sphinx/locale/__init__.py:159
msgid "Attention"
msgstr "Výstraha"
@ -583,7 +613,7 @@ msgstr "vestavěná funkce"
msgid "Table Of Contents"
msgstr "Obsah"
#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:137
#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:138
#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
#: sphinx/themes/basic/searchresults.html:10
msgid "Search"
@ -641,15 +671,15 @@ msgstr "rychlý přístup ke všem modulům"
msgid "all functions, classes, terms"
msgstr "všechny funkce, třídy, termíny"
#: sphinx/themes/basic/genindex-single.html:35
#: sphinx/themes/basic/genindex-single.html:33
#, python-format
msgid "Index &ndash; %(key)s"
msgstr "Rejstřík &ndash; %(key)s"
#: sphinx/themes/basic/genindex-single.html:63
#: sphinx/themes/basic/genindex-single.html:61
#: sphinx/themes/basic/genindex-split.html:24
#: sphinx/themes/basic/genindex-split.html:38
#: sphinx/themes/basic/genindex.html:74
#: sphinx/themes/basic/genindex.html:72
msgid "Full index on one page"
msgstr "Celý rejstřík na jedné stránce"
@ -665,35 +695,35 @@ msgstr "může být obrovský"
msgid "Navigation"
msgstr "Navigace"
#: sphinx/themes/basic/layout.html:122
#: sphinx/themes/basic/layout.html:123
#, python-format
msgid "Search within %(docstitle)s"
msgstr "Prohledat %(docstitle)s"
#: sphinx/themes/basic/layout.html:131
#: sphinx/themes/basic/layout.html:132
msgid "About these documents"
msgstr "O těchto dokumentech"
#: sphinx/themes/basic/layout.html:140
#: sphinx/themes/basic/layout.html:141
msgid "Copyright"
msgstr "Veškerá práva vyhrazena"
#: sphinx/themes/basic/layout.html:189
#: sphinx/themes/basic/layout.html:186
#, python-format
msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgid "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:191
#: sphinx/themes/basic/layout.html:188
#, python-format
msgid "&copy; Copyright %(copyright)s."
msgstr "&copy; Copyright %(copyright)s."
msgid "&#169; Copyright %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:195
#: sphinx/themes/basic/layout.html:192
#, python-format
msgid "Last updated on %(last_updated)s."
msgstr "Aktualizováno dne %(last_updated)s."
#: sphinx/themes/basic/layout.html:198
#: sphinx/themes/basic/layout.html:195
#, python-format
msgid ""
"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
@ -742,13 +772,13 @@ msgstr "hledat"
#: sphinx/themes/basic/search.html:43
#: sphinx/themes/basic/searchresults.html:21
#: sphinx/themes/basic/static/searchtools.js_t:282
#: sphinx/themes/basic/static/searchtools.js_t:287
msgid "Search Results"
msgstr "Výsledky vyhledávání"
#: sphinx/themes/basic/search.html:45
#: sphinx/themes/basic/searchresults.html:23
#: sphinx/themes/basic/static/searchtools.js_t:284
#: sphinx/themes/basic/static/searchtools.js_t:289
msgid ""
"Your search did not match any documents. Please make sure that all words are"
" spelled correctly and that you've selected enough categories."
@ -765,13 +795,13 @@ msgstr "Tato stránka"
#: sphinx/themes/basic/changes/frameset.html:5
#: sphinx/themes/basic/changes/versionchanges.html:12
#, python-format
msgid "Changes in Version %(version)s &mdash; %(docstitle)s"
msgstr "Změny ve verzi %(version)s &mdash; %(docstitle)s"
msgid "Changes in Version %(version)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/rstsource.html:5
#, python-format
msgid "%(filename)s &mdash; %(docstitle)s"
msgstr "%(filename)s &mdash; %(docstitle)s"
msgid "%(filename)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/versionchanges.html:17
#, python-format
@ -790,12 +820,13 @@ msgstr "Změny API"
msgid "Other changes"
msgstr "Ostatní změny"
#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:668
#: sphinx/writers/html.py:673
#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:708
#: sphinx/writers/html.py:713
msgid "Permalink to this headline"
msgstr "Trvalý odkaz na tento nadpis"
#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:105
#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:108
#: sphinx/writers/html.py:117
msgid "Permalink to this definition"
msgstr "Trvalý odkaz na tuto definici"
@ -811,12 +842,12 @@ msgstr "Probíhá vyhledání"
msgid "Preparing search..."
msgstr "Vyhledávání se připravuje..."
#: sphinx/themes/basic/static/searchtools.js_t:286
#: sphinx/themes/basic/static/searchtools.js_t:291
#, python-format
msgid "Search finished, found %s page(s) matching the search query."
msgstr "Vyhledávání dokončeno, stránky odpovídající hledanému výrazu: %s."
#: sphinx/themes/basic/static/searchtools.js_t:338
#: sphinx/themes/basic/static/searchtools.js_t:344
msgid ", in "
msgstr ", v "
@ -833,48 +864,53 @@ msgstr "Sbalit boční lištu"
msgid "Contents"
msgstr "Obsah"
#: sphinx/writers/html.py:349
#: sphinx/writers/html.py:389
msgid "Permalink to this code"
msgstr "Permalink k tomuto kódu"
#: sphinx/writers/html.py:353
#: sphinx/writers/html.py:393
msgid "Permalink to this image"
msgstr "Permalink k tomuto obrázku"
#: sphinx/writers/html.py:355
#: sphinx/writers/html.py:395
msgid "Permalink to this toctree"
msgstr ""
#: sphinx/writers/html.py:677
#: sphinx/writers/html.py:717
msgid "Permalink to this table"
msgstr "Permalink k této tabulce"
#: sphinx/writers/latex.py:361
#: sphinx/writers/latex.py:380
msgid "Release"
msgstr "Vydání"
#: sphinx/writers/latex.py:427
#: sphinx/writers/latex.py:483
msgid "page"
msgstr ""
#: sphinx/writers/latex.py:920 sphinx/writers/manpage.py:233
#: sphinx/writers/texinfo.py:620
#: sphinx/writers/latex.py:528
#, python-format
msgid "Unknown configure key: latex_elements[%r] is ignored."
msgstr ""
#: sphinx/writers/latex.py:1003 sphinx/writers/manpage.py:238
#: sphinx/writers/texinfo.py:619
msgid "Footnotes"
msgstr "Poznámky pod čarou"
#: sphinx/writers/latex.py:1022
#: sphinx/writers/latex.py:1112
msgid "continued from previous page"
msgstr "pokračujte na předchozí stránce"
#: sphinx/writers/latex.py:1028
#: sphinx/writers/latex.py:1118
msgid "Continued on next page"
msgstr "Pokračujte na další stránce"
#: sphinx/writers/manpage.py:282 sphinx/writers/text.py:582
#: sphinx/writers/manpage.py:287 sphinx/writers/text.py:591
#, python-format
msgid "[image: %s]"
msgstr "[obrázek: %s]"
#: sphinx/writers/manpage.py:283 sphinx/writers/text.py:583
#: sphinx/writers/manpage.py:288 sphinx/writers/text.py:592
msgid "[image]"
msgstr "[obrázek]"

View File

@ -1 +1 @@
Documentation.addTranslations({"locale": "cy", "messages": {"%(filename)s &mdash; %(docstitle)s": "%(filename)s &mdash; %(docstitle)s", "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "&copy; <a href=\"%(path)s\">Hawlfraint</a> %(copyright)s.", "&copy; Copyright %(copyright)s.": "&copy; Hawlfraint %(copyright)s.", ", in ": ", yn ", "About these documents": "Yngl\u0177n \u00e2'r dogfennau hyn", "Automatically generated list of changes in version %(version)s": "Rhestr o newidiadau yn fersiwn %(version)s wedi'i cynhyrchu'n awtomatig", "C API changes": "Newidiadau i'r C-API", "Changes in Version %(version)s &mdash; %(docstitle)s": "Newidiadau yn Fersiwn %(version)s &mdash; %(docstitle)s", "Collapse sidebar": "Cyfangu'r bar ochr", "Complete Table of Contents": "Tabl Cynnwys Llawn", "Contents": "Cynnwys", "Copyright": "Hawlfraint", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "Cr\u8c37wyd gan ddefnyddio <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s", "Expand sidebar": "Ehangu'r bar ochr", "From here you can search these documents. Enter your search\n words into the box below and click \"search\". Note that the search\n function will automatically search for all of the words. Pages\n containing fewer words won't appear in the result list.": "O'r fan hon gallwch chwilio'r dogfennau hyn. Rhowch eich geiriau chwilio yn y blwch isod a chliciwch \"chwilio\". Nodwch fod y ffwythiant chwilio yn chwilio am bob un o'r geiriau yn awtomatig. Ni fydd dudalennau sy'n cynnwys llai o eiriau yn ymddangos yn y rhestr canlyniadau.", "Full index on one page": "Indecs llawn ar un tudalen", "General Index": "Indecs cyffredinol", "Global Module Index": "Indecs Modiwl Byd-Eang", "Go": "Ewch", "Hide Search Matches": "Cuddio Canlyniadau Chwilio", "Index": "Indecs", "Index &ndash; %(key)s": "Indecs &ndash; %(key)s", "Index pages by letter": "Indecs tudalennau gan lythyren", "Indices and tables:": "Indecsau a tablau:", "Last updated on %(last_updated)s.": "Diweddarwyd yn ddiwethaf ar %(last_updated)s.", "Library changes": "Newidiadau i'r llyfrgell", "Navigation": "Llywio", "Next topic": "Pwnc nesaf", "Other changes": "Newidiadau arall", "Overview": "Trosolwg", "Permalink to this definition": "Permalink i'r diffiniad hwn", "Permalink to this headline": "Permalink i'r pennawd hwn", "Please activate JavaScript to enable the search\n functionality.": "Trwoch JavaScript ymlaen i alluogi'r chwilio.", "Preparing search...": "Paratoi chwilio...", "Previous topic": "Pwnc blaenorol", "Quick search": "Chwilio cyflym", "Search": "Chwilio", "Search Page": "Tudalen Chwilio", "Search Results": "Canlyniadau chwilio", "Search finished, found %s page(s) matching the search query.": "Chwiliad wedi gorffen, wedi ffeindio %s tudalen(nau) yn cyfateb a'r ymholiad chwilio.", "Search within %(docstitle)s": "Chwilio o fewn %(docstitle)s", "Searching": "Yn chwilio", "Show Source": "Dangos Ffynhonell", "Table Of Contents": "Tabl Cynnwys", "This Page": "Y Dudalen Hon", "Welcome! This is": "Croeso! Dyma", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Nid yw eich chwiliad yn cyfateb unrhyw ddogfennau. Gwnewch yn si\u0175r fod pob gair wedi'i sillafu'n gywir, ac eich bod wedi dewis digon o gategor\u00efau.", "all functions, classes, terms": "holl ffwythiannau, dosbarthau a thermau", "can be huge": "gall fod yn enfawr", "last updated": "diweddarwyd yn ddiwethaf", "lists all sections and subsections": "rhestru holl adrannau ac isadrannau", "next chapter": "pennod nesaf", "previous chapter": "pennod blaenorol", "quick access to all modules": "mynediad cloi i bob modiwl", "search": "chwilio", "search this documentation": "chwiliwch y ddogfennaeth", "the documentation for": "y dogfennaeth am"}, "plural_expr": "(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3"});
Documentation.addTranslations({"locale": "cy", "messages": {"%(filename)s &#8212; %(docstitle)s": "", "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "", "&#169; Copyright %(copyright)s.": "", ", in ": ", yn ", "About these documents": "Yngl\u0177n \u00e2'r dogfennau hyn", "Automatically generated list of changes in version %(version)s": "Rhestr o newidiadau yn fersiwn %(version)s wedi'i cynhyrchu'n awtomatig", "C API changes": "Newidiadau i'r C-API", "Changes in Version %(version)s &#8212; %(docstitle)s": "", "Collapse sidebar": "Cyfangu'r bar ochr", "Complete Table of Contents": "Tabl Cynnwys Llawn", "Contents": "Cynnwys", "Copyright": "Hawlfraint", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "Cr\u8c37wyd gan ddefnyddio <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s", "Expand sidebar": "Ehangu'r bar ochr", "From here you can search these documents. Enter your search\n words into the box below and click \"search\". Note that the search\n function will automatically search for all of the words. Pages\n containing fewer words won't appear in the result list.": "O'r fan hon gallwch chwilio'r dogfennau hyn. Rhowch eich geiriau chwilio yn y blwch isod a chliciwch \"chwilio\". Nodwch fod y ffwythiant chwilio yn chwilio am bob un o'r geiriau yn awtomatig. Ni fydd dudalennau sy'n cynnwys llai o eiriau yn ymddangos yn y rhestr canlyniadau.", "Full index on one page": "Indecs llawn ar un tudalen", "General Index": "Indecs cyffredinol", "Global Module Index": "Indecs Modiwl Byd-Eang", "Go": "Ewch", "Hide Search Matches": "Cuddio Canlyniadau Chwilio", "Index": "Indecs", "Index &ndash; %(key)s": "Indecs &ndash; %(key)s", "Index pages by letter": "Indecs tudalennau gan lythyren", "Indices and tables:": "Indecsau a tablau:", "Last updated on %(last_updated)s.": "Diweddarwyd yn ddiwethaf ar %(last_updated)s.", "Library changes": "Newidiadau i'r llyfrgell", "Navigation": "Llywio", "Next topic": "Pwnc nesaf", "Other changes": "Newidiadau arall", "Overview": "Trosolwg", "Permalink to this definition": "Permalink i'r diffiniad hwn", "Permalink to this headline": "Permalink i'r pennawd hwn", "Please activate JavaScript to enable the search\n functionality.": "Trwoch JavaScript ymlaen i alluogi'r chwilio.", "Preparing search...": "Paratoi chwilio...", "Previous topic": "Pwnc blaenorol", "Quick search": "Chwilio cyflym", "Search": "Chwilio", "Search Page": "Tudalen Chwilio", "Search Results": "Canlyniadau chwilio", "Search finished, found %s page(s) matching the search query.": "Chwiliad wedi gorffen, wedi ffeindio %s tudalen(nau) yn cyfateb a'r ymholiad chwilio.", "Search within %(docstitle)s": "Chwilio o fewn %(docstitle)s", "Searching": "Yn chwilio", "Show Source": "Dangos Ffynhonell", "Table Of Contents": "Tabl Cynnwys", "This Page": "Y Dudalen Hon", "Welcome! This is": "Croeso! Dyma", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Nid yw eich chwiliad yn cyfateb unrhyw ddogfennau. Gwnewch yn si\u0175r fod pob gair wedi'i sillafu'n gywir, ac eich bod wedi dewis digon o gategor\u00efau.", "all functions, classes, terms": "holl ffwythiannau, dosbarthau a thermau", "can be huge": "gall fod yn enfawr", "last updated": "diweddarwyd yn ddiwethaf", "lists all sections and subsections": "rhestru holl adrannau ac isadrannau", "next chapter": "pennod nesaf", "previous chapter": "pennod blaenorol", "quick access to all modules": "mynediad cloi i bob modiwl", "search": "chwilio", "search this documentation": "chwiliwch y ddogfennaeth", "the documentation for": "y dogfennaeth am"}, "plural_expr": "(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3"});

View File

@ -9,61 +9,42 @@ msgid ""
msgstr ""
"Project-Id-Version: Sphinx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-03-06 21:58+0900\n"
"PO-Revision-Date: 2016-03-06 13:01+0000\n"
"Last-Translator: Takayuki Shimizukawa <shimizukawa@gmail.com>\n"
"POT-Creation-Date: 2016-11-06 22:40+0900\n"
"PO-Revision-Date: 2016-11-06 13:53+0000\n"
"Last-Translator: Takeshi KOMIYA <i.tkomiya@gmail.com>\n"
"Language-Team: Welsh (http://www.transifex.com/sphinx-doc/sphinx-1/language/cy/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.2.0\n"
"Generated-By: Babel 2.3.4\n"
"Language: cy\n"
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n"
#: sphinx/config.py:91
#: sphinx/config.py:109
#, python-format
msgid "Section %s"
msgstr ""
#: sphinx/config.py:110
#, python-format
msgid "Fig. %s"
msgstr "Ffig. %s"
#: sphinx/config.py:92
#: sphinx/config.py:111
#, python-format
msgid "Table %s"
msgstr "Tabl %s"
#: sphinx/config.py:93
#: sphinx/config.py:112
#, python-format
msgid "Listing %s"
msgstr "Listing %s"
#: sphinx/config.py:100
#, python-format
msgid "%s %s documentation"
msgstr "Dogfennaeth %s %s "
#: sphinx/environment.py:1829
#, python-format
msgid "see %s"
msgstr "gweler %s"
#: sphinx/environment.py:1833
#, python-format
msgid "see also %s"
msgstr "gweler hefyd %s"
#: sphinx/environment.py:1893
msgid "Symbols"
msgstr "Symbolau"
#: sphinx/roles.py:193
#: sphinx/roles.py:187
#, python-format
msgid "Python Enhancement Proposals; PEP %s"
msgstr "Python Enhancement Proposals; PEP %s"
#: sphinx/transforms.py:56 sphinx/writers/latex.py:374
#: sphinx/writers/manpage.py:101 sphinx/writers/texinfo.py:222
msgid "MMMM dd, YYYY"
msgstr ""
#: sphinx/builders/changes.py:75
msgid "Builtins"
msgstr ""
@ -72,8 +53,11 @@ msgstr ""
msgid "Module level"
msgstr "Lefel modiwl"
#: sphinx/builders/html.py:295
msgid "MMM dd, YYYY"
#: sphinx/builders/html.py:294 sphinx/transforms/__init__.py:46
#: sphinx/writers/latex.py:393 sphinx/writers/manpage.py:100
#: sphinx/writers/texinfo.py:221
#, python-format
msgid "%b %d, %Y"
msgstr ""
#: sphinx/builders/html.py:315 sphinx/themes/basic/defindex.html:30
@ -84,18 +68,28 @@ msgstr "Indecs cyffredinol"
msgid "index"
msgstr "indecs"
#: sphinx/builders/html.py:376
#: sphinx/builders/html.py:377
msgid "next"
msgstr "nesaf"
#: sphinx/builders/html.py:385
#: sphinx/builders/html.py:386
msgid "previous"
msgstr "blaenorol"
#: sphinx/builders/latex.py:180 sphinx/builders/texinfo.py:199
#: sphinx/builders/html.py:1222
#, python-format
msgid "%s %s documentation"
msgstr "Dogfennaeth %s %s "
#: sphinx/builders/latex.py:177 sphinx/builders/texinfo.py:199
msgid " (in "
msgstr " (yn "
#: sphinx/directives/code.py:140 sphinx/directives/code.py:370
#, python-format
msgid "Invalid caption: %s"
msgstr ""
#: sphinx/directives/other.py:149
msgid "Section author: "
msgstr "Awdur yr adran:"
@ -112,23 +106,23 @@ msgstr "Awdur y cod:"
msgid "Author: "
msgstr "Awdur:"
#: sphinx/domains/__init__.py:275
#: sphinx/domains/__init__.py:277
#, python-format
msgid "%s %s"
msgstr ""
#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:3605
#: sphinx/domains/python.py:124
#: sphinx/domains/c.py:58 sphinx/domains/cpp.py:4051
#: sphinx/domains/python.py:149
msgid "Parameters"
msgstr "Paramedrau"
#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:3614
#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:136
#: sphinx/domains/c.py:61 sphinx/domains/cpp.py:4060
#: sphinx/domains/javascript.py:128 sphinx/domains/python.py:161
msgid "Returns"
msgstr ""
#: sphinx/domains/c.py:63 sphinx/domains/javascript.py:130
#: sphinx/domains/python.py:138
#: sphinx/domains/python.py:163
msgid "Return type"
msgstr ""
@ -157,12 +151,12 @@ msgstr ""
msgid "%s (C variable)"
msgstr ""
#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:3953
#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:589
#: sphinx/domains/c.py:242 sphinx/domains/cpp.py:4418
#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:614
msgid "function"
msgstr "ffwythiant"
#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:3954
#: sphinx/domains/c.py:243 sphinx/domains/cpp.py:4419
msgid "member"
msgstr "aelod"
@ -170,7 +164,7 @@ msgstr "aelod"
msgid "macro"
msgstr ""
#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:3955
#: sphinx/domains/c.py:245 sphinx/domains/cpp.py:4420
msgid "type"
msgstr ""
@ -178,63 +172,72 @@ msgstr ""
msgid "variable"
msgstr ""
#: sphinx/domains/cpp.py:3608
#: sphinx/domains/cpp.py:4054
msgid "Template Parameters"
msgstr ""
#: sphinx/domains/cpp.py:3611 sphinx/domains/javascript.py:125
#: sphinx/domains/cpp.py:4057 sphinx/domains/javascript.py:125
msgid "Throws"
msgstr ""
#: sphinx/domains/cpp.py:3733
#: sphinx/domains/cpp.py:4205
#, python-format
msgid "%s (C++ type)"
msgstr ""
#: sphinx/domains/cpp.py:3744
#: sphinx/domains/cpp.py:4216
#, python-format
msgid "%s (C++ concept)"
msgstr ""
#: sphinx/domains/cpp.py:4227
#, python-format
msgid "%s (C++ member)"
msgstr ""
#: sphinx/domains/cpp.py:3755
#: sphinx/domains/cpp.py:4238
#, python-format
msgid "%s (C++ function)"
msgstr ""
#: sphinx/domains/cpp.py:3766
#: sphinx/domains/cpp.py:4249
#, python-format
msgid "%s (C++ class)"
msgstr ""
#: sphinx/domains/cpp.py:3786
#: sphinx/domains/cpp.py:4260
#, python-format
msgid "%s (C++ enum)"
msgstr ""
#: sphinx/domains/cpp.py:3816
#: sphinx/domains/cpp.py:4281
#, python-format
msgid "%s (C++ enumerator)"
msgstr ""
#: sphinx/domains/cpp.py:3952 sphinx/domains/javascript.py:165
#: sphinx/domains/python.py:591
#: sphinx/domains/cpp.py:4417 sphinx/domains/javascript.py:165
#: sphinx/domains/python.py:616
msgid "class"
msgstr ""
#: sphinx/domains/cpp.py:3956
#: sphinx/domains/cpp.py:4421
msgid "concept"
msgstr ""
#: sphinx/domains/cpp.py:4422
msgid "enum"
msgstr ""
#: sphinx/domains/cpp.py:3957
#: sphinx/domains/cpp.py:4423
msgid "enumerator"
msgstr ""
#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:282
#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:307
#, python-format
msgid "%s() (built-in function)"
msgstr ""
#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:346
#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:371
#, python-format
msgid "%s() (%s method)"
msgstr ""
@ -249,7 +252,7 @@ msgstr ""
msgid "%s (global variable or constant)"
msgstr "%s (newidyn byd-eang neu cysonyn)"
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:384
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:409
#, python-format
msgid "%s (%s attribute)"
msgstr ""
@ -258,116 +261,116 @@ msgstr ""
msgid "Arguments"
msgstr ""
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:590
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:615
msgid "data"
msgstr ""
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:596
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:621
msgid "attribute"
msgstr ""
#: sphinx/domains/python.py:129
#: sphinx/domains/python.py:154
msgid "Variables"
msgstr ""
#: sphinx/domains/python.py:133
#: sphinx/domains/python.py:158
msgid "Raises"
msgstr ""
#: sphinx/domains/python.py:283 sphinx/domains/python.py:340
#: sphinx/domains/python.py:352 sphinx/domains/python.py:365
#: sphinx/domains/python.py:308 sphinx/domains/python.py:365
#: sphinx/domains/python.py:377 sphinx/domains/python.py:390
#, python-format
msgid "%s() (in module %s)"
msgstr ""
#: sphinx/domains/python.py:286
#: sphinx/domains/python.py:311
#, python-format
msgid "%s (built-in variable)"
msgstr ""
#: sphinx/domains/python.py:287 sphinx/domains/python.py:378
#: sphinx/domains/python.py:312 sphinx/domains/python.py:403
#, python-format
msgid "%s (in module %s)"
msgstr ""
#: sphinx/domains/python.py:303
#: sphinx/domains/python.py:328
#, python-format
msgid "%s (built-in class)"
msgstr ""
#: sphinx/domains/python.py:304
#: sphinx/domains/python.py:329
#, python-format
msgid "%s (class in %s)"
msgstr ""
#: sphinx/domains/python.py:344
#: sphinx/domains/python.py:369
#, python-format
msgid "%s() (%s.%s method)"
msgstr ""
#: sphinx/domains/python.py:356
#: sphinx/domains/python.py:381
#, python-format
msgid "%s() (%s.%s static method)"
msgstr ""
#: sphinx/domains/python.py:359
#: sphinx/domains/python.py:384
#, python-format
msgid "%s() (%s static method)"
msgstr ""
#: sphinx/domains/python.py:369
#: sphinx/domains/python.py:394
#, python-format
msgid "%s() (%s.%s class method)"
msgstr ""
#: sphinx/domains/python.py:372
#: sphinx/domains/python.py:397
#, python-format
msgid "%s() (%s class method)"
msgstr ""
#: sphinx/domains/python.py:382
#: sphinx/domains/python.py:407
#, python-format
msgid "%s (%s.%s attribute)"
msgstr ""
#: sphinx/domains/python.py:463
#: sphinx/domains/python.py:488
#, python-format
msgid "%s (module)"
msgstr ""
#: sphinx/domains/python.py:520
#: sphinx/domains/python.py:545
msgid "Python Module Index"
msgstr ""
#: sphinx/domains/python.py:521
#: sphinx/domains/python.py:546
msgid "modules"
msgstr ""
#: sphinx/domains/python.py:567
#: sphinx/domains/python.py:592
msgid "Deprecated"
msgstr ""
#: sphinx/domains/python.py:592 sphinx/locale/__init__.py:183
#: sphinx/domains/python.py:617 sphinx/locale/__init__.py:183
msgid "exception"
msgstr ""
#: sphinx/domains/python.py:593
#: sphinx/domains/python.py:618
msgid "method"
msgstr ""
#: sphinx/domains/python.py:594
#: sphinx/domains/python.py:619
msgid "class method"
msgstr ""
#: sphinx/domains/python.py:595
#: sphinx/domains/python.py:620
msgid "static method"
msgstr ""
#: sphinx/domains/python.py:597 sphinx/locale/__init__.py:179
#: sphinx/domains/python.py:622 sphinx/locale/__init__.py:179
msgid "module"
msgstr "modiwl"
#: sphinx/domains/python.py:762
#: sphinx/domains/python.py:787
msgid " (deprecated)"
msgstr ""
@ -389,120 +392,147 @@ msgstr ""
msgid "role"
msgstr ""
#: sphinx/domains/std.py:73 sphinx/domains/std.py:89
#: sphinx/domains/std.py:72 sphinx/domains/std.py:88
#, python-format
msgid "environment variable; %s"
msgstr ""
#: sphinx/domains/std.py:185
#: sphinx/domains/std.py:186
#, python-format
msgid "%scommand line option; %s"
msgstr ""
#: sphinx/domains/std.py:433
#: sphinx/domains/std.py:434
msgid "glossary term"
msgstr ""
#: sphinx/domains/std.py:434
#: sphinx/domains/std.py:435
msgid "grammar token"
msgstr ""
#: sphinx/domains/std.py:435
#: sphinx/domains/std.py:436
msgid "reference label"
msgstr ""
#: sphinx/domains/std.py:437
#: sphinx/domains/std.py:438
msgid "environment variable"
msgstr ""
#: sphinx/domains/std.py:438
#: sphinx/domains/std.py:439
msgid "program option"
msgstr ""
#: sphinx/domains/std.py:471 sphinx/themes/basic/genindex-single.html:32
#: sphinx/themes/basic/genindex-single.html:57
#: sphinx/domains/std.py:473 sphinx/themes/basic/genindex-single.html:30
#: sphinx/themes/basic/genindex-single.html:55
#: sphinx/themes/basic/genindex-split.html:11
#: sphinx/themes/basic/genindex-split.html:14
#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35
#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
#: sphinx/writers/latex.py:363 sphinx/writers/texinfo.py:481
#: sphinx/themes/basic/genindex.html:30 sphinx/themes/basic/genindex.html:33
#: sphinx/themes/basic/genindex.html:66 sphinx/themes/basic/layout.html:135
#: sphinx/writers/latex.py:381 sphinx/writers/texinfo.py:480
msgid "Index"
msgstr "Indecs"
#: sphinx/domains/std.py:472
#: sphinx/domains/std.py:474
msgid "Module Index"
msgstr "Indecs Modiwlau"
#: sphinx/domains/std.py:473 sphinx/themes/basic/defindex.html:25
#: sphinx/domains/std.py:475 sphinx/themes/basic/defindex.html:25
msgid "Search Page"
msgstr "Tudalen Chwilio"
#: sphinx/ext/autodoc.py:1265
#: sphinx/environment/managers/indexentries.py:104
#, python-format
msgid " Bases: %s"
msgid "see %s"
msgstr "gweler %s"
#: sphinx/environment/managers/indexentries.py:108
#, python-format
msgid "see also %s"
msgstr "gweler hefyd %s"
#: sphinx/environment/managers/indexentries.py:168
msgid "Symbols"
msgstr "Symbolau"
#: sphinx/ext/autodoc.py:1297
#, python-format
msgid "Bases: %s"
msgstr ""
#: sphinx/ext/autodoc.py:1318
#: sphinx/ext/autodoc.py:1350
#, python-format
msgid "alias of :class:`%s`"
msgstr ""
#: sphinx/ext/graphviz.py:309 sphinx/ext/graphviz.py:318
#: sphinx/ext/graphviz.py:331 sphinx/ext/graphviz.py:340
#, python-format
msgid "[graph: %s]"
msgstr "[graff: %s]"
#: sphinx/ext/graphviz.py:311 sphinx/ext/graphviz.py:320
#: sphinx/ext/graphviz.py:333 sphinx/ext/graphviz.py:342
msgid "[graph]"
msgstr "[graff]"
#: sphinx/ext/intersphinx.py:359
#: sphinx/ext/imgmath.py:258 sphinx/ext/jsmath.py:39 sphinx/ext/mathjax.py:40
msgid "Permalink to this equation"
msgstr ""
#: sphinx/ext/intersphinx.py:337
#, python-format
msgid "(in %s v%s)"
msgstr "(yn %s v%s)"
#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:99
#: sphinx/ext/linkcode.py:69 sphinx/ext/viewcode.py:103
msgid "[source]"
msgstr "[ffynhonnell]"
#: sphinx/ext/mathbase.py:92
#, python-format
msgid "duplicate label of equation %s, other instance in %s"
msgstr ""
#: sphinx/ext/todo.py:56
msgid "Todo"
msgstr "Todo"
#: sphinx/ext/todo.py:129
#: sphinx/ext/todo.py:134
msgid "<<original entry>>"
msgstr ""
#: sphinx/ext/todo.py:132
#: sphinx/ext/todo.py:137
#, python-format
msgid "(The <<original entry>> is located in %s, line %d.)"
msgstr ""
#: sphinx/ext/todo.py:141
#: sphinx/ext/todo.py:146
msgid "original entry"
msgstr "eitem wreiddiol"
#: sphinx/ext/viewcode.py:162
#: sphinx/ext/viewcode.py:166
msgid "[docs]"
msgstr "[docs]"
#: sphinx/ext/viewcode.py:176
#: sphinx/ext/viewcode.py:180
msgid "Module code"
msgstr "Cod y modiwl"
#: sphinx/ext/viewcode.py:182
#: sphinx/ext/viewcode.py:186
#, python-format
msgid "<h1>Source code for %s</h1>"
msgstr "<h1>Cod ffynhonnell ar gyfer %s</h1>"
#: sphinx/ext/viewcode.py:208
#: sphinx/ext/viewcode.py:212
msgid "Overview: module code"
msgstr "Trosolwg: cod y modiwl"
#: sphinx/ext/viewcode.py:209
#: sphinx/ext/viewcode.py:213
msgid "<h1>All modules for which code is available</h1>"
msgstr "<h1>Holl fodiwlau lle mae'r cod ar gael</h1>"
#: sphinx/ext/napoleon/__init__.py:313
msgid "Keyword Arguments"
msgstr ""
#: sphinx/locale/__init__.py:159
msgid "Attention"
msgstr "Sylw"
@ -583,7 +613,7 @@ msgstr "ffwythiant built-in"
msgid "Table Of Contents"
msgstr "Tabl Cynnwys"
#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:137
#: sphinx/themes/agogo/layout.html:51 sphinx/themes/basic/layout.html:138
#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
#: sphinx/themes/basic/searchresults.html:10
msgid "Search"
@ -641,15 +671,15 @@ msgstr "mynediad cloi i bob modiwl"
msgid "all functions, classes, terms"
msgstr "holl ffwythiannau, dosbarthau a thermau"
#: sphinx/themes/basic/genindex-single.html:35
#: sphinx/themes/basic/genindex-single.html:33
#, python-format
msgid "Index &ndash; %(key)s"
msgstr "Indecs &ndash; %(key)s"
#: sphinx/themes/basic/genindex-single.html:63
#: sphinx/themes/basic/genindex-single.html:61
#: sphinx/themes/basic/genindex-split.html:24
#: sphinx/themes/basic/genindex-split.html:38
#: sphinx/themes/basic/genindex.html:74
#: sphinx/themes/basic/genindex.html:72
msgid "Full index on one page"
msgstr "Indecs llawn ar un tudalen"
@ -665,35 +695,35 @@ msgstr "gall fod yn enfawr"
msgid "Navigation"
msgstr "Llywio"
#: sphinx/themes/basic/layout.html:122
#: sphinx/themes/basic/layout.html:123
#, python-format
msgid "Search within %(docstitle)s"
msgstr "Chwilio o fewn %(docstitle)s"
#: sphinx/themes/basic/layout.html:131
#: sphinx/themes/basic/layout.html:132
msgid "About these documents"
msgstr "Ynglŷn â'r dogfennau hyn"
#: sphinx/themes/basic/layout.html:140
#: sphinx/themes/basic/layout.html:141
msgid "Copyright"
msgstr "Hawlfraint"
#: sphinx/themes/basic/layout.html:189
#: sphinx/themes/basic/layout.html:186
#, python-format
msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr "&copy; <a href=\"%(path)s\">Hawlfraint</a> %(copyright)s."
msgid "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:191
#: sphinx/themes/basic/layout.html:188
#, python-format
msgid "&copy; Copyright %(copyright)s."
msgstr "&copy; Hawlfraint %(copyright)s."
msgid "&#169; Copyright %(copyright)s."
msgstr ""
#: sphinx/themes/basic/layout.html:195
#: sphinx/themes/basic/layout.html:192
#, python-format
msgid "Last updated on %(last_updated)s."
msgstr "Diweddarwyd yn ddiwethaf ar %(last_updated)s."
#: sphinx/themes/basic/layout.html:198
#: sphinx/themes/basic/layout.html:195
#, python-format
msgid ""
"Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> "
@ -742,13 +772,13 @@ msgstr "chwilio"
#: sphinx/themes/basic/search.html:43
#: sphinx/themes/basic/searchresults.html:21
#: sphinx/themes/basic/static/searchtools.js_t:282
#: sphinx/themes/basic/static/searchtools.js_t:287
msgid "Search Results"
msgstr "Canlyniadau chwilio"
#: sphinx/themes/basic/search.html:45
#: sphinx/themes/basic/searchresults.html:23
#: sphinx/themes/basic/static/searchtools.js_t:284
#: sphinx/themes/basic/static/searchtools.js_t:289
msgid ""
"Your search did not match any documents. Please make sure that all words are"
" spelled correctly and that you've selected enough categories."
@ -765,13 +795,13 @@ msgstr "Y Dudalen Hon"
#: sphinx/themes/basic/changes/frameset.html:5
#: sphinx/themes/basic/changes/versionchanges.html:12
#, python-format
msgid "Changes in Version %(version)s &mdash; %(docstitle)s"
msgstr "Newidiadau yn Fersiwn %(version)s &mdash; %(docstitle)s"
msgid "Changes in Version %(version)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/rstsource.html:5
#, python-format
msgid "%(filename)s &mdash; %(docstitle)s"
msgstr "%(filename)s &mdash; %(docstitle)s"
msgid "%(filename)s &#8212; %(docstitle)s"
msgstr ""
#: sphinx/themes/basic/changes/versionchanges.html:17
#, python-format
@ -790,12 +820,13 @@ msgstr "Newidiadau i'r C-API"
msgid "Other changes"
msgstr "Newidiadau arall"
#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:668
#: sphinx/writers/html.py:673
#: sphinx/themes/basic/static/doctools.js_t:169 sphinx/writers/html.py:708
#: sphinx/writers/html.py:713
msgid "Permalink to this headline"
msgstr "Permalink i'r pennawd hwn"
#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:105
#: sphinx/themes/basic/static/doctools.js_t:175 sphinx/writers/html.py:108
#: sphinx/writers/html.py:117
msgid "Permalink to this definition"
msgstr "Permalink i'r diffiniad hwn"
@ -811,12 +842,12 @@ msgstr "Yn chwilio"
msgid "Preparing search..."
msgstr "Paratoi chwilio..."
#: sphinx/themes/basic/static/searchtools.js_t:286
#: sphinx/themes/basic/static/searchtools.js_t:291
#, python-format
msgid "Search finished, found %s page(s) matching the search query."
msgstr "Chwiliad wedi gorffen, wedi ffeindio %s tudalen(nau) yn cyfateb a'r ymholiad chwilio."
#: sphinx/themes/basic/static/searchtools.js_t:338
#: sphinx/themes/basic/static/searchtools.js_t:344
msgid ", in "
msgstr ", yn "
@ -833,48 +864,53 @@ msgstr "Cyfangu'r bar ochr"
msgid "Contents"
msgstr "Cynnwys"
#: sphinx/writers/html.py:349
#: sphinx/writers/html.py:389
msgid "Permalink to this code"
msgstr "Permalink i'r cod hwn"
#: sphinx/writers/html.py:353
#: sphinx/writers/html.py:393
msgid "Permalink to this image"
msgstr "Permalink i'r ddelwedd hon"
#: sphinx/writers/html.py:355
#: sphinx/writers/html.py:395
msgid "Permalink to this toctree"
msgstr "Permalink i'r toctree hwn"
#: sphinx/writers/html.py:677
#: sphinx/writers/html.py:717
msgid "Permalink to this table"
msgstr "Permalink i'r tabl hwn"
#: sphinx/writers/latex.py:361
#: sphinx/writers/latex.py:380
msgid "Release"
msgstr "Rhyddhad"
#: sphinx/writers/latex.py:427
#: sphinx/writers/latex.py:483
msgid "page"
msgstr ""
#: sphinx/writers/latex.py:920 sphinx/writers/manpage.py:233
#: sphinx/writers/texinfo.py:620
#: sphinx/writers/latex.py:528
#, python-format
msgid "Unknown configure key: latex_elements[%r] is ignored."
msgstr ""
#: sphinx/writers/latex.py:1003 sphinx/writers/manpage.py:238
#: sphinx/writers/texinfo.py:619
msgid "Footnotes"
msgstr "Troednodiadau"
#: sphinx/writers/latex.py:1022
#: sphinx/writers/latex.py:1112
msgid "continued from previous page"
msgstr "wedi'i barhau o'r tudalen blaenorol"
#: sphinx/writers/latex.py:1028
#: sphinx/writers/latex.py:1118
msgid "Continued on next page"
msgstr "Yn parhau ar y tudalen nesaf"
#: sphinx/writers/manpage.py:282 sphinx/writers/text.py:582
#: sphinx/writers/manpage.py:287 sphinx/writers/text.py:591
#, python-format
msgid "[image: %s]"
msgstr "[delwedd: %s]"
#: sphinx/writers/manpage.py:283 sphinx/writers/text.py:583
#: sphinx/writers/manpage.py:288 sphinx/writers/text.py:592
msgid "[image]"
msgstr "[delwedd]"

View File

@ -1 +1 @@
Documentation.addTranslations({"locale": "da", "messages": {"%(filename)s &mdash; %(docstitle)s": "%(filename)s &mdash; %(docstitle)s", "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "&copy; <a href=\"%(path)s\">Ophavsret</a> %(copyright)s.", "&copy; Copyright %(copyright)s.": "&copy; Ophavsret %(copyright)s.", ", in ": ", i", "About these documents": "Om disse dokumenter", "Automatically generated list of changes in version %(version)s": "Automatisk oprettet liste af \u00e6ndringer i version %(version)s", "C API changes": "\u00c6ndringer i C-API", "Changes in Version %(version)s &mdash; %(docstitle)s": "\u00c6ndringer i version %(version)s &mdash; %(docstitle)s", "Collapse sidebar": "Sammenfold sidebj\u00e6lke", "Complete Table of Contents": "Fuldst\u00e6ndig indholdsfortegnelse", "Contents": "Indhold", "Copyright": "Ophavsret", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "Bygget med <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.", "Expand sidebar": "Udfold sidebj\u00e6lke", "From here you can search these documents. Enter your search\n words into the box below and click \"search\". Note that the search\n function will automatically search for all of the words. Pages\n containing fewer words won't appear in the result list.": "Her fra kan du s\u00f8ge i disse dokumenter. Indtast dine s\u00f8geord\n i boksen nedenfor og klik p\u00e5 \"s\u00f8g\". Bem\u00e6rk at s\u00f8gefunktionen\n automatisk vil s\u00f8ge p\u00e5 alle ordene. Sider, der indeholder\n f\u00e6rre ord, vil ikke indg\u00e5 i resultaterne.", "Full index on one page": "Fuldt indeks p\u00e5 \u00e9n side", "General Index": "Generelt indeks", "Global Module Index": "Globalt modulindeks", "Go": "S\u00f8g", "Hide Search Matches": "Skjul s\u00f8geresultater", "Index": "Indeks", "Index &ndash; %(key)s": "Indeks &ndash; %(key)s", "Index pages by letter": "Indeks\u00e9r sider efter bogstav", "Indices and tables:": "Indeks og tabeller:", "Last updated on %(last_updated)s.": "Sidst opdateret %(last_updated)s.", "Library changes": "Biblioteks\u00e6ndringer", "Navigation": "Navigation", "Next topic": "N\u00e6ste emne", "Other changes": "Andre \u00e6ndringer", "Overview": "Oversigt", "Permalink to this definition": "Permalink til denne definition", "Permalink to this headline": "Permalink til denne overskrift", "Please activate JavaScript to enable the search\n functionality.": "Aktiv\u00e9r venligst JavaScript for at aktivere\n s\u00f8gefunktionalitet.", "Preparing search...": "Forbereder s\u00f8gning...", "Previous topic": "Forrige emne", "Quick search": "Hurtig s\u00f8gning", "Search": "S\u00f8g", "Search Page": "S\u00f8geside", "Search Results": "S\u00f8geresultater", "Search finished, found %s page(s) matching the search query.": "S\u00f8gning f\u00e6rdig, fandt %s sider der matcher s\u00f8geforesp\u00f8rgslen.", "Search within %(docstitle)s": "S\u00f8g i %(docstitle)s", "Searching": "S\u00f8ger", "Show Source": "Vis kilde", "Table Of Contents": "Indholdsfortegnelse", "This Page": "Denne side", "Welcome! This is": "Velkommen! Dette er", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Din s\u00f8gning matchede ikke nogen dokumenter. Sikr dig at alle ord er stavet korrekt og at du har valgt nok kategorier.", "all functions, classes, terms": "alle funktioner, klasser, begreber", "can be huge": "kan v\u00e6re enormt", "last updated": "sidst opdateret", "lists all sections and subsections": "viser alle afsnit og underafsnit", "next chapter": "n\u00e6ste kapitel", "previous chapter": "forrige kapitel", "quick access to all modules": "hurtig adgang til alle moduler", "search": "s\u00f8g", "search this documentation": "s\u00f8g i denne dokumentation", "the documentation for": "dokumentationen for"}, "plural_expr": "(n != 1)"});
Documentation.addTranslations({"locale": "da", "messages": {"%(filename)s &#8212; %(docstitle)s": "", "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "", "&#169; Copyright %(copyright)s.": "", ", in ": ", i", "About these documents": "Om disse dokumenter", "Automatically generated list of changes in version %(version)s": "Automatisk oprettet liste af \u00e6ndringer i version %(version)s", "C API changes": "\u00c6ndringer i C-API", "Changes in Version %(version)s &#8212; %(docstitle)s": "", "Collapse sidebar": "Sammenfold sidebj\u00e6lke", "Complete Table of Contents": "Fuldst\u00e6ndig indholdsfortegnelse", "Contents": "Indhold", "Copyright": "Ophavsret", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "Bygget med <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.", "Expand sidebar": "Udfold sidebj\u00e6lke", "From here you can search these documents. Enter your search\n words into the box below and click \"search\". Note that the search\n function will automatically search for all of the words. Pages\n containing fewer words won't appear in the result list.": "Her fra kan du s\u00f8ge i disse dokumenter. Indtast dine s\u00f8geord\n i boksen nedenfor og klik p\u00e5 \"s\u00f8g\". Bem\u00e6rk at s\u00f8gefunktionen\n automatisk vil s\u00f8ge p\u00e5 alle ordene. Sider, der indeholder\n f\u00e6rre ord, vil ikke indg\u00e5 i resultaterne.", "Full index on one page": "Fuldt indeks p\u00e5 \u00e9n side", "General Index": "Generelt indeks", "Global Module Index": "Globalt modulindeks", "Go": "S\u00f8g", "Hide Search Matches": "Skjul s\u00f8geresultater", "Index": "Indeks", "Index &ndash; %(key)s": "Indeks &ndash; %(key)s", "Index pages by letter": "Indeks\u00e9r sider efter bogstav", "Indices and tables:": "Indeks og tabeller:", "Last updated on %(last_updated)s.": "Sidst opdateret %(last_updated)s.", "Library changes": "Biblioteks\u00e6ndringer", "Navigation": "Navigation", "Next topic": "N\u00e6ste emne", "Other changes": "Andre \u00e6ndringer", "Overview": "Oversigt", "Permalink to this definition": "Permalink til denne definition", "Permalink to this headline": "Permalink til denne overskrift", "Please activate JavaScript to enable the search\n functionality.": "Aktiv\u00e9r venligst JavaScript for at aktivere\n s\u00f8gefunktionalitet.", "Preparing search...": "Forbereder s\u00f8gning...", "Previous topic": "Forrige emne", "Quick search": "Hurtig s\u00f8gning", "Search": "S\u00f8g", "Search Page": "S\u00f8geside", "Search Results": "S\u00f8geresultater", "Search finished, found %s page(s) matching the search query.": "S\u00f8gning f\u00e6rdig, fandt %s sider der matcher s\u00f8geforesp\u00f8rgslen.", "Search within %(docstitle)s": "S\u00f8g i %(docstitle)s", "Searching": "S\u00f8ger", "Show Source": "Vis kilde", "Table Of Contents": "Indholdsfortegnelse", "This Page": "Denne side", "Welcome! This is": "Velkommen! Dette er", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Din s\u00f8gning matchede ikke nogen dokumenter. Sikr dig at alle ord er stavet korrekt og at du har valgt nok kategorier.", "all functions, classes, terms": "alle funktioner, klasser, begreber", "can be huge": "kan v\u00e6re enormt", "last updated": "sidst opdateret", "lists all sections and subsections": "viser alle afsnit og underafsnit", "next chapter": "n\u00e6ste kapitel", "previous chapter": "forrige kapitel", "quick access to all modules": "hurtig adgang til alle moduler", "search": "s\u00f8g", "search this documentation": "s\u00f8g i denne dokumentation", "the documentation for": "dokumentationen for"}, "plural_expr": "(n != 1)"});

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