Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Ignacio Fdez. Galván 2015-07-09 17:35:23 +02:00
commit d5cbda5c79
58 changed files with 43775 additions and 343 deletions

View File

@ -13,6 +13,7 @@ Bugs fixed
* #1789: ``:pyobject:`` option of ``literalinclude`` directive includes following
lines after class definitions
* #1790: ``literalinclude`` strips empty lines at the head and tail
* #1913: C++, fix assert bug for enumerators in next-to-global and global scope.
Documentation
-------------
@ -38,6 +39,7 @@ Bugs fixed
Thanks to Jens Hedegaard Nielsen.
* #1781: Setting `html_domain_indices` to a list raises a type check warnings.
Release 1.3 (released Mar 10, 2015)
===================================
@ -86,6 +88,7 @@ Documentation
* #1651: Add ``vartype`` field descritpion for python domain.
Release 1.3b3 (released Feb 24, 2015)
=====================================

View File

@ -27,7 +27,7 @@ are also available.{%endtrans%}</p>
<h3>{%trans%}Questions? Suggestions?{%endtrans%}</h3>
<p>{%trans%}Join the <a href="http://groups.google.com/group/sphinx-users">Google group</a>:{%endtrans%}</p>
<p>{%trans%}Join the <a href="http://groups.google.com/group/sphinx-users">sphinx-users</a> mailing list on Google Groups:{%endtrans%}</p>
<form action="http://groups.google.com/group/sphinx-users/boxsubscribe"
style="padding-left: 0.5em">
<input type="text" name="email" value="your@email" style="font-size: 90%; width: 120px"

View File

@ -12,11 +12,11 @@ Example:
$ python example_google.py
Section breaks are created by simply resuming unindented text. Section breaks
Section breaks are created by resuming unindented text. Section breaks
are also implicitly created anytime a new section starts.
Attributes:
module_level_variable (int): Module level variables may be documented in
module_level_variable1 (int): Module level variables may be documented in
either the ``Attributes`` section of the module docstring, or in an
inline docstring immediately following the variable.
@ -25,11 +25,18 @@ Attributes:
with it.
.. _Google Python Style Guide:
http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
http://google.github.io/styleguide/pyguide.html
"""
module_level_variable = 12345
module_level_variable1 = 12345
module_level_variable2 = 98765
"""int: Module level variable documented inline.
The docstring may span multiple lines. The type may optionally be specified
on the first line, separated by a colon.
"""
def module_level_function(param1, param2=None, *args, **kwargs):
@ -39,22 +46,24 @@ def module_level_function(param1, param2=None, *args, **kwargs):
of each parameter is required. The type and description of each parameter
is optional, but should be included if not obvious.
If the parameter itself is optional, it should be noted by adding
", optional" to the type. If \*args or \*\*kwargs are accepted, they
should be listed as \*args and \*\*kwargs.
Parameter types -- if given -- should be specified according to
`PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
If \*args or \*\*kwargs are accepted,
they should be listed as ``*args`` and ``**kwargs``.
The format for a parameter is::
name (type): description
The description may span multiple lines. Following
lines should be indented.
lines should be indented. The "(type)" is optional.
Multiple paragraphs are supported in parameter
descriptions.
Args:
param1 (int): The first parameter.
param2 (str, optional): The second parameter. Defaults to None.
param2 (Optional[str]): The second parameter. Defaults to None.
Second line of description should be indented.
*args: Variable length argument list.
**kwargs: Arbitrary keyword arguments.
@ -81,6 +90,10 @@ def module_level_function(param1, param2=None, *args, **kwargs):
that are relevant to the interface.
ValueError: If `param2` is equal to `param1`.
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
"""
if param1 == param2:
raise ValueError('param1 may not be equal to param2')
@ -91,16 +104,16 @@ def example_generator(n):
"""Generators have a ``Yields`` section instead of a ``Returns`` section.
Args:
n (int): The upper limit of the range to generate, from 0 to `n` - 1
n (int): The upper limit of the range to generate, from 0 to `n` - 1.
Yields:
int: The next number in the range of 0 to `n` - 1
int: The next number in the range of 0 to `n` - 1.
Examples:
Examples should be written in doctest format, and should illustrate how
to use the function.
>>> print [i for i in example_generator(4)]
>>> print([i for i in example_generator(4)])
[0, 1, 2, 3]
"""
@ -122,14 +135,15 @@ class ExampleError(Exception):
Args:
msg (str): Human readable string describing the exception.
code (int, optional): Error code, defaults to 2.
code (Optional[int]): Error code.
Attributes:
msg (str): Human readable string describing the exception.
code (int): Exception error code.
"""
def __init__(self, msg, code=2):
def __init__(self, msg, code):
self.msg = msg
self.code = code
@ -137,17 +151,28 @@ class ExampleError(Exception):
class ExampleClass(object):
"""The summary line for a class docstring should fit on one line.
If the class has public attributes, they should be documented here
If the class has public attributes, they may be documented here
in an ``Attributes`` section and follow the same formatting as a
function's ``Args`` section.
function's ``Args`` section. Alternatively, attributes may be documented
inline with the attribute's declaration (see __init__ method below).
Properties created with the ``@property`` decorator should be documented
in the property's getter method.
Attribute and property types -- if given -- should be specified according
to `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
Attributes:
attr1 (str): Description of `attr1`.
attr2 (list of str): Description of `attr2`.
attr3 (int): Description of `attr3`.
attr2 (Optional[int]): Description of `attr2`.
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
"""
def __init__(self, param1, param2, param3=0):
def __init__(self, param1, param2, param3):
"""Example of docstring on the __init__ method.
The __init__ method may be documented in either the class level
@ -161,14 +186,39 @@ class ExampleClass(object):
Args:
param1 (str): Description of `param1`.
param2 (list of str): Description of `param2`. Multiple
param2 (Optional[int]): Description of `param2`. Multiple
lines are supported.
param3 (int, optional): Description of `param3`, defaults to 0.
param3 (List[str]): Description of `param3`.
"""
self.attr1 = param1
self.attr2 = param2
self.attr3 = param3
self.attr3 = param3 #: Doc comment *inline* with attribute
#: List[str]: Doc comment *before* attribute, with type specified
self.attr4 = ['attr4']
self.attr5 = None
"""Optional[str]: Docstring *after* attribute, with type specified."""
@property
def readonly_property(self):
"""str: Properties should be documented in their getter method."""
return 'readonly_property'
@property
def readwrite_property(self):
"""List[str]: Properties with both a getter and setter should only
be documented in their getter method.
If the setter method contains notable behavior, it should be
mentioned here.
"""
return ['readwrite_property']
@readwrite_property.setter
def readwrite_property(self, value):
value
def example_method(self, param1, param2):
"""Class methods are similar to regular functions.

View File

@ -23,12 +23,12 @@ Notes
This is an example of an indented section. It's like any other section,
but the body is indented to help it stand out from surrounding text.
If a section is indented, then a section break is created simply by
If a section is indented, then a section break is created by
resuming unindented text.
Attributes
----------
module_level_variable : int
module_level_variable1 : int
Module level variables may be documented in either the ``Attributes``
section of the module docstring, or in an inline docstring immediately
following the variable.
@ -42,7 +42,14 @@ module_level_variable : int
"""
module_level_variable = 12345
module_level_variable1 = 12345
module_level_variable2 = 98765
"""int: Module level variable documented inline.
The docstring may span multiple lines. The type may optionally be specified
on the first line, separated by a colon.
"""
def module_level_function(param1, param2=None, *args, **kwargs):
@ -52,9 +59,11 @@ def module_level_function(param1, param2=None, *args, **kwargs):
The name of each parameter is required. The type and description of each
parameter is optional, but should be included if not obvious.
If the parameter itself is optional, it should be noted by adding
", optional" to the type. If \*args or \*\*kwargs are accepted, they
should be listed as \*args and \*\*kwargs.
Parameter types -- if given -- should be specified according to
`PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
If \*args or \*\*kwargs are accepted,
they should be listed as ``*args`` and ``**kwargs``.
The format for a parameter is::
@ -63,6 +72,7 @@ def module_level_function(param1, param2=None, *args, **kwargs):
The description may span multiple lines. Following lines
should be indented to match the first line of the description.
The ": type" is optional.
Multiple paragraphs are supported in parameter
descriptions.
@ -71,8 +81,8 @@ def module_level_function(param1, param2=None, *args, **kwargs):
----------
param1 : int
The first parameter.
param2 : str, optional
The second parameter, defaults to None.
param2 : Optional[str]
The second parameter.
*args
Variable length argument list.
**kwargs
@ -103,6 +113,10 @@ def module_level_function(param1, param2=None, *args, **kwargs):
ValueError
If `param2` is equal to `param1`.
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
"""
if param1 == param2:
raise ValueError('param1 may not be equal to param2')
@ -115,19 +129,19 @@ def example_generator(n):
Parameters
----------
n : int
The upper limit of the range to generate, from 0 to `n` - 1
The upper limit of the range to generate, from 0 to `n` - 1.
Yields
------
int
The next number in the range of 0 to `n` - 1
The next number in the range of 0 to `n` - 1.
Examples
--------
Examples should be written in doctest format, and should illustrate how
to use the function.
>>> print [i for i in example_generator(4)]
>>> print([i for i in example_generator(4)])
[0, 1, 2, 3]
"""
@ -152,18 +166,19 @@ class ExampleError(Exception):
----------
msg : str
Human readable string describing the exception.
code : int, optional
Error code, defaults to 2.
code : Optional[int]
Numeric error code.
Attributes
----------
msg : str
Human readable string describing the exception.
code : int
Exception error code.
Numeric error code.
"""
def __init__(self, msg, code=2):
def __init__(self, msg, code):
self.msg = msg
self.code = code
@ -171,21 +186,31 @@ class ExampleError(Exception):
class ExampleClass(object):
"""The summary line for a class docstring should fit on one line.
If the class has public attributes, they should be documented here
If the class has public attributes, they may be documented here
in an ``Attributes`` section and follow the same formatting as a
function's ``Parameters`` section.
function's ``Args`` section. Alternatively, attributes may be documented
inline with the attribute's declaration (see __init__ method below).
Properties created with the ``@property`` decorator should be documented
in the property's getter method.
Attribute and property types -- if given -- should be specified according
to `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
Attributes
----------
attr1 : str
Description of `attr1`.
attr2 : list of str
attr2 : Optional[int]
Description of `attr2`.
attr3 : int
Description of `attr3`.
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
"""
def __init__(self, param1, param2, param3=0):
def __init__(self, param1, param2, param3):
"""Example of docstring on the __init__ method.
The __init__ method may be documented in either the class level
@ -202,16 +227,41 @@ class ExampleClass(object):
----------
param1 : str
Description of `param1`.
param2 : list of str
param2 : List[str]
Description of `param2`. Multiple
lines are supported.
param3 : int, optional
Description of `param3`, defaults to 0.
param3 : Optional[int]
Description of `param3`.
"""
self.attr1 = param1
self.attr2 = param2
self.attr3 = param3
self.attr3 = param3 #: Doc comment *inline* with attribute
#: List[str]: Doc comment *before* attribute, with type specified
self.attr4 = ["attr4"]
self.attr5 = None
"""Optional[str]: Docstring *after* attribute, with type specified."""
@property
def readonly_property(self):
"""str: Properties should be documented in their getter method."""
return "readonly_property"
@property
def readwrite_property(self):
"""List[str]: Properties with both a getter and setter should only
be documented in their getter method.
If the setter method contains notable behavior, it should be
mentioned here.
"""
return ["readwrite_property"]
@readwrite_property.setter
def readwrite_property(self, value):
value
def example_method(self, param1, param2):
"""Class methods are similar to regular functions.

View File

@ -50,9 +50,9 @@ source code files.
.. _ReStructuredText: http://docutils.sourceforge.net/rst.html
.. _docstrings: http://www.python.org/dev/peps/pep-0287/
.. _Google Python Style Guide:
http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
http://google.github.io/styleguide/pyguide.html
.. _Google:
http://google-styleguide.googlecode.com/svn/trunk/pyguide.html#Comments
http://google.github.io/styleguide/pyguide.html#Comments
.. _NumPy:
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
.. _Khan Academy:
@ -113,6 +113,7 @@ All of the following section headers are supported:
* ``Warning``
* ``Warnings`` *(alias of Warning)*
* ``Warns``
* ``Yield`` *(alias of Yields)*
* ``Yields``
Google vs NumPy
@ -178,6 +179,11 @@ not be mixed. Choose one style for your project and be consistent with it.
* :ref:`example_google`
* :ref:`example_numpy`
For Python type annotations, see `PEP 484`_.
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
Configuration
=============

View File

@ -4,11 +4,11 @@ Tutorial: Writing a simple extension
====================================
This section is intended as a walkthrough for the creation of custom extensions.
It covers the basics of writing and activating an extensions, as well as
It covers the basics of writing and activating an extension, as well as
commonly used features of extensions.
As an example, we will cover a "todo" extension that adds capabilities to
include todo entries in the documentation, and collecting these in a central
include todo entries in the documentation, and to collect these in a central
place. (A similar "todo" extension is distributed with Sphinx.)
@ -20,7 +20,7 @@ extension. These are:
**Application**
The application object (usually called ``app``) is an instance of
:class:`.Sphinx`. It controls the most high-level functionality, such as the
:class:`.Sphinx`. It controls most high-level functionality, such as the
setup of extensions, event dispatching and producing output (logging).
If you have the environment object, the application is available as
@ -29,8 +29,8 @@ extension. These are:
**Environment**
The build environment object (usually called ``env``) is an instance of
:class:`.BuildEnvironment`. It is responsible for parsing the source
documents stores all metadata about the document collection and is serialized
after each build.
documents, stores all metadata about the document collection and is
serialized to disk after each build.
Its API provides methods to do with access to metadata, resolving references,
etc. It can also be used by extensions to cache information that should
@ -64,7 +64,7 @@ in which a Sphinx project is built: this works in several phases.
**Phase 0: Initialization**
In this phase, almost nothing interesting for us happens. The source
In this phase, almost nothing of interest to us happens. The source
directory is searched for source files, and extensions are initialized.
Should a stored build environment exist, it is loaded, otherwise a new one is
created.
@ -73,8 +73,8 @@ in which a Sphinx project is built: this works in several phases.
In Phase 1, all source files (and on subsequent builds, those that are new or
changed) are read and parsed. This is the phase where directives and roles
are encountered by the docutils, and the corresponding code is executed. The
output of this phase is a *doctree* for each source files, that is a tree of
are encountered by docutils, and the corresponding code is executed. The
output of this phase is a *doctree* for each source file; that is a tree of
docutils nodes. For document elements that aren't fully known until all
existing files are read, temporary nodes are created.
@ -229,8 +229,8 @@ The Directive Classes
A directive class is a class deriving usually from
:class:`docutils.parsers.rst.Directive`. The directive interface is also
covered in detail in the `docutils documentation`_; the important thing is that
the class has attributes that configure the allowed markup and a method ``run``
that returns a list of nodes.
the class should have attributes that configure the allowed markup,
and a ``run`` method that returns a list of nodes.
The ``todolist`` directive is quite simple::

View File

@ -147,7 +147,7 @@ If you finished the installation of pip, type this line in the command prompt:
C:\> pip install sphinx
After installation, type :command:`sphinx-build` on the command prompt. If
After installation, type :command:`sphinx-build -h` on the command prompt. If
everything worked fine, you will get a Sphinx version number and a list of
options for this command.

33
doc/make.bat Normal file
View File

@ -0,0 +1,33 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=python ../sphinx-build.py
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=sphinx-doc
if "%1" == "" goto help
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end

View File

@ -85,7 +85,7 @@ tables of contents. The ``toctree`` directive is the central element.
**Additional options**
You can use ``caption`` option to provide toctree caption and you can use
You can use ``caption`` option to provide a toctree caption and you can use
``name`` option to provide implicit target name that can be referenced by
using :rst:role:`ref`::

View File

@ -412,3 +412,8 @@ are in HTML form), these variables are also available:
* ``includehidden`` (``False`` by default): if true, the TOC tree will also
contain hidden entries.
.. data:: page_source_suffix
The suffix of the file that was rendered. Since we support a list of :confval:`source_suffix`,
this will allow you to properly link to the original source file.

View File

@ -238,7 +238,7 @@ def recurse_tree(rootpath, excludes, opts):
def normalize_excludes(rootpath, excludes):
"""Normalize the excluded directory list."""
return [path.normpath(path.abspath(exclude)) for exclude in excludes]
return [path.abspath(exclude) for exclude in excludes]
def is_excluded(root, excludes):
@ -247,7 +247,6 @@ def is_excluded(root, excludes):
Note: by having trailing slashes, we avoid common prefix issues, like
e.g. an exlude "foo" also accidentally excluding "foobar".
"""
root = path.normpath(root)
for exclude in excludes:
if root == exclude:
return True
@ -328,7 +327,7 @@ Note: By default this script will not overwrite already created files.""")
if not opts.destdir:
parser.error('An output directory is required.')
if opts.header is None:
opts.header = path.normpath(rootpath).split(path.sep)[-1]
opts.header = path.abspath(rootpath).split(path.sep)[-1]
if opts.suffix.startswith('.'):
opts.suffix = opts.suffix[1:]
if not path.isdir(rootpath):
@ -337,7 +336,7 @@ Note: By default this script will not overwrite already created files.""")
if not path.isdir(opts.destdir):
if not opts.dryrun:
os.makedirs(opts.destdir)
rootpath = path.normpath(path.abspath(rootpath))
rootpath = path.abspath(rootpath)
excludes = normalize_excludes(rootpath, excludes)
modules = recurse_tree(rootpath, excludes, opts)
if opts.full:

View File

@ -79,6 +79,7 @@ class Sphinx(object):
self._extension_metadata = {}
self._listeners = {}
self.domains = BUILTIN_DOMAINS.copy()
self.buildername = buildername
self.builderclasses = BUILTIN_BUILDERS.copy()
self.builder = None
self.env = None
@ -185,7 +186,7 @@ class Sphinx(object):
# set up the build environment
self._init_env(freshenv)
# set up the builder
self._init_builder(buildername)
self._init_builder(self.buildername)
def _init_i18n(self):
"""Load translated strings from the configured localedirs if enabled in
@ -446,8 +447,17 @@ class Sphinx(object):
'version.' % (extension, err))
if ext_meta is None:
ext_meta = {}
# special-case for compatibility
if extension == 'rst2pdf.pdfbuilder':
ext_meta = {'parallel_read_safe': True}
try:
if not ext_meta.get('version'):
ext_meta['version'] = 'unknown version'
except Exception:
self.warn('extension %r returned an unsupported object from '
'its setup() function; it should return None or a '
'metadata dictionary' % extension)
ext_meta = {'version': 'unknown version'}
self._extensions[extension] = mod
self._extension_metadata[extension] = ext_meta

View File

@ -408,6 +408,9 @@ class StandaloneHTMLBuilder(Builder):
# metadata for the document
meta = self.env.metadata.get(docname)
# Suffix for the document
source_suffix = '.' + self.env.doc2path(docname).split('.')[-1]
# local TOC and global TOC tree
self_toc = self.env.get_toc_for(docname, self)
toc = self.render_partial(self_toc)['fragment']
@ -425,6 +428,7 @@ class StandaloneHTMLBuilder(Builder):
toc = toc,
# only display a TOC if there's more than one item to show
display_toc = (self.env.toc_num_entries[docname] > 1),
page_source_suffix = source_suffix,
)
def write_doc(self, docname, doctree):
@ -584,6 +588,12 @@ class StandaloneHTMLBuilder(Builder):
copyfile(jsfile, path.join(self.outdir, '_static',
'translations.js'))
# copy non-minified stemmer JavaScript file
if self.indexer is not None:
jsfile = self.indexer.get_js_stemmer_rawcode()
if jsfile:
copyfile(jsfile, path.join(self.outdir, '_static', '_stemmer.js'))
ctx = self.globalcontext.copy()
# add context items for search function used in searchtools.js_t

View File

@ -2415,6 +2415,43 @@ class CPPObject(ObjectDescription):
names=('returns', 'return')),
]
def _add_enumerator_to_parent(self, ast, objects):
assert ast.objectType == 'enumerator'
# find the parent, if it exists && is an enum
# && it's unscoped,
# then add the name to the parent scope
assert len(ast.prefixedName.names) > 0
if len(ast.prefixedName.names) == 1:
# TODO: we could warn, but it is somewhat equivalent to unscoped
# enums, without the enum
return # no parent
parentPrefixedAstName = ASTNestedName(ast.prefixedName.names[:-1])
parentPrefixedName = text_type(parentPrefixedAstName).lstrip(':')
if parentPrefixedName not in objects:
# the parent is not explicitly declared
# TODO: we could warn, but it could be a style to just assume
# enumerator parnets to be scoped
return
docname, parentAst = objects[parentPrefixedName]
if parentAst.objectType != 'enum':
# TODO: maybe issue a warning, enumerators in non-enums is weird,
# but it is somewhat equivalent to unscoped enums, without the enum
return
if parentAst.scoped:
return
enumeratorName = ASTNestedName([ast.prefixedName.names[-1]])
assert len(parentAst.prefixedName.names) > 0
if len(parentAst.prefixedName.names) == 1:
# the enum is in global scope
unscopedName = enumeratorName
else:
enumScope = ASTNestedName(parentAst.prefixedName.names[:-1])
unscopedName = enumeratorName.prefix_nested_name(enumScope)
txtUnscopedName = text_type(unscopedName).lstrip(':')
if txtUnscopedName not in objects:
objects.setdefault(txtUnscopedName,
(self.env.docname, ast))
def add_target_and_index(self, ast, sig, signode):
# general note: name must be lstrip(':')'ed, to remove "::"
try:
@ -2445,23 +2482,7 @@ class CPPObject(ObjectDescription):
if name not in objects:
objects.setdefault(name, (self.env.docname, ast))
if ast.objectType == 'enumerator':
# find the parent, if it exists && is an enum
# && it's unscoped,
# then add the name to the parent scope
assert len(ast.prefixedName.names) > 0
parentPrefixedAstName = ASTNestedName(ast.prefixedName.names[:-1])
parentPrefixedName = text_type(parentPrefixedAstName).lstrip(':')
if parentPrefixedName in objects:
docname, parentAst = objects[parentPrefixedName]
if parentAst.objectType == 'enum' and not parentAst.scoped:
enumeratorName = ASTNestedName([ast.prefixedName.names[-1]])
assert len(parentAst.prefixedName.names) > 0
enumScope = ASTNestedName(parentAst.prefixedName.names[:-1])
unscopedName = enumeratorName.prefix_nested_name(enumScope)
txtUnscopedName = text_type(unscopedName).lstrip(':')
if txtUnscopedName not in objects:
objects.setdefault(txtUnscopedName,
(self.env.docname, ast))
self._add_enumerator_to_parent(ast, objects)
# add the uninstantiated template if it doesn't exist
uninstantiated = ast.prefixedName.get_name_no_last_template().lstrip(':')
if uninstantiated != name and uninstantiated not in objects:

View File

@ -141,8 +141,6 @@ class SphinxFileInput(FileInput):
def __init__(self, app, env, *args, **kwds):
self.app = app
self.env = env
# don't call sys.exit() on IOErrors
kwds['handle_io_errors'] = False
kwds['error_handler'] = 'sphinx' # py3: handle error on open.
FileInput.__init__(self, *args, **kwds)

View File

@ -276,7 +276,7 @@ class Autosummary(Directive):
self.warn('failed to import object %s' % real_name)
items.append((display_name, '', '', real_name))
continue
if not documenter.check_module():
if documenter.options.members and not documenter.check_module():
continue
# try to also get a source code analyzer for attribute docs

View File

@ -371,7 +371,7 @@ def _skip_member(app, what, name, obj, skip, options):
cls = functools.reduce(getattr, mod_path, mod)
else:
cls = obj.__globals__[cls_path]
except:
except Exception:
cls_is_owner = False
else:
cls_is_owner = (cls and hasattr(cls, name) and

View File

@ -23,21 +23,19 @@ from sphinx.util.pycompat import UnicodeMixin
_directive_regex = re.compile(r'\.\. \S+::')
_google_untyped_arg_regex = re.compile(r'(.+)\s*(?<!:):(?!:)\s*(.*)')
_google_typed_arg_regex = re.compile(r'(.+)\((.+)\)\s*(?<!:):(?!:)\s*(.*)')
_google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.+?)\s*\)')
_xref_regex = re.compile(r'(:\w+:\S+:`.+?`|:\S+:`.+?`|`.+?`)')
class GoogleDocstring(UnicodeMixin):
"""Parse Google style docstrings.
Convert Google style docstrings to reStructuredText.
"""Convert Google style docstrings to reStructuredText.
Parameters
----------
docstring : str or list of str
docstring : str or List[str]
The docstring to parse, given either as a string or split into
individual lines.
config : sphinx.ext.napoleon.Config or sphinx.config.Config, optional
config : Optional[sphinx.ext.napoleon.Config or sphinx.config.Config]
The configuration settings to use. If not given, defaults to the
config object on `app`; or if `app` is not given defaults to the
a new `sphinx.ext.napoleon.Config` object.
@ -48,17 +46,17 @@ class GoogleDocstring(UnicodeMixin):
Other Parameters
----------------
app : sphinx.application.Sphinx, optional
app : Optional[sphinx.application.Sphinx]
Application object representing the Sphinx process.
what : str, optional
what : Optional[str]
A string specifying the type of the object to which the docstring
belongs. Valid values: "module", "class", "exception", "function",
"method", "attribute".
name : str, optional
name : Optional[str]
The fully qualified name of the object.
obj : module, class, exception, function, method, or attribute
The object to which the docstring belongs.
options : sphinx.ext.autodoc.Options, optional
options : Optional[sphinx.ext.autodoc.Options]
The options given to the directive: an object with attributes
inherited_members, undoc_members, show_inheritance and noindex that
are True if the flag option of same name was given to the auto
@ -168,7 +166,7 @@ class GoogleDocstring(UnicodeMixin):
Returns
-------
list of str
List[str]
The lines of the docstring in a list.
"""
@ -202,20 +200,14 @@ class GoogleDocstring(UnicodeMixin):
def _consume_field(self, parse_type=True, prefer_type=False):
line = next(self._line_iter)
match = None
_name, _type, _desc = line.strip(), '', ''
if parse_type:
match = _google_typed_arg_regex.match(line)
if match:
_name = match.group(1).strip()
_type = match.group(2).strip()
_desc = match.group(3).strip()
before, colon, after = self._partition_field_on_colon(line)
_name, _type, _desc = before, '', after
if not match:
match = _google_untyped_arg_regex.match(line)
if parse_type:
match = _google_typed_arg_regex.match(before)
if match:
_name = match.group(1).strip()
_desc = match.group(2).strip()
_name = match.group(1)
_type = match.group(2)
if _name[:2] == '**':
_name = r'\*\*'+_name[2:]
@ -238,23 +230,33 @@ class GoogleDocstring(UnicodeMixin):
fields.append((_name, _type, _desc,))
return fields
def _consume_inline_attribute(self):
line = next(self._line_iter)
_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 = self.__class__(_desc, self._config).lines()
return _type, _desc
def _consume_returns_section(self):
lines = self._dedent(self._consume_to_next_section())
if lines:
before, colon, after = self._partition_field_on_colon(lines[0])
_name, _type, _desc = '', '', lines
match = _google_typed_arg_regex.match(lines[0])
if match:
_name = match.group(1).strip()
_type = match.group(2).strip()
_desc = match.group(3).strip()
if colon:
if after:
_desc = [after] + lines[1:]
else:
match = _google_untyped_arg_regex.match(lines[0])
_desc = lines[1:]
match = _google_typed_arg_regex.match(before)
if match:
_type = match.group(1).strip()
_desc = match.group(2).strip()
if match:
lines[0] = _desc
_desc = lines
_name = match.group(1)
_type = match.group(2)
else:
_type = before
_desc = self.__class__(_desc, self._config).lines()
return [(_name, _type, _desc,)]
@ -272,6 +274,12 @@ class GoogleDocstring(UnicodeMixin):
section = stripped_section
return section
def _consume_to_end(self):
lines = []
while self._line_iter.has_next():
lines.append(next(self._line_iter))
return lines
def _consume_to_next_section(self):
self._consume_empty()
lines = []
@ -313,23 +321,29 @@ class GoogleDocstring(UnicodeMixin):
return [prefix]
def _format_field(self, _name, _type, _desc):
separator = any([s for s in _desc]) and ' --' or ''
_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)
else:
field = ['**%s** (*%s*)%s' % (_name, _type, separator)]
field = '**%s** (*%s*)%s' % (_name, _type, separator)
else:
field = ['**%s**%s' % (_name, separator)]
field = '**%s**%s' % (_name, separator)
elif _type:
if '`' in _type:
field = ['%s%s' % (_type, separator)]
field = '%s%s' % (_type, separator)
else:
field = ['*%s*%s' % (_type, separator)]
field = '*%s*%s' % (_type, separator)
else:
field = []
return field + _desc
field = ''
if has_desc:
return [field + _desc[0]] + _desc[1:]
else:
return [field]
def _format_fields(self, field_type, fields):
field_type = ':%s:' % field_type.strip()
@ -345,6 +359,8 @@ class GoogleDocstring(UnicodeMixin):
lines.extend(self._format_block(field_type + ' * ', field))
else:
lines.extend(self._format_block(field_type + ' ', field))
if lines and lines[-1]:
lines.append('')
return lines
def _get_current_indent(self, peek_ahead=0):
@ -407,6 +423,11 @@ class GoogleDocstring(UnicodeMixin):
def _parse(self):
self._parsed_lines = self._consume_empty()
if self._name and (self._what == 'attribute' or self._what == 'data'):
self._parsed_lines.extend(self._parse_attribute_docstring())
return
while self._line_iter.has_next():
if self._is_section_header():
try:
@ -427,6 +448,10 @@ class GoogleDocstring(UnicodeMixin):
lines = self._consume_to_next_section()
self._parsed_lines.extend(lines)
def _parse_attribute_docstring(self):
_type, _desc = self._consume_inline_attribute()
return self._format_field('', _type, _desc)
def _parse_attributes_section(self, section):
lines = []
for _name, _type, _desc in self._consume_fields():
@ -436,15 +461,9 @@ class GoogleDocstring(UnicodeMixin):
if _type:
lines.append(':vartype %s: %s' % (_name, _type))
else:
lines.append('.. attribute:: ' + _name)
if _type:
lines.append('')
if '`' in _type:
lines.append(' %s' % _type)
else:
lines.append(' *%s*' % _type)
if _desc:
lines.extend([''] + self._indent(_desc, 3))
lines.extend(['.. attribute:: ' + _name, ''])
field = self._format_field('', _type, _desc)
lines.extend(self._indent(field, 3))
lines.append('')
if self._config.napoleon_use_ivar:
lines.append('')
@ -511,33 +530,32 @@ class GoogleDocstring(UnicodeMixin):
return self._format_fields('Parameters', fields)
def _parse_raises_section(self, section):
fields = self._consume_fields()
fields = self._consume_fields(parse_type=False, prefer_type=True)
field_type = ':raises:'
padding = ' ' * len(field_type)
multi = len(fields) > 1
lines = []
for _name, _type, _desc in fields:
sep = _desc and ' -- ' or ''
if _name:
if ' ' in _name:
_name = '**%s**' % _name
else:
_name = ':exc:`%s`' % _name
for _, _type, _desc in fields:
_desc = self._strip_empty(_desc)
has_desc = any(_desc)
separator = has_desc and ' -- ' or ''
if _type:
if '`' in _type:
field = ['%s (%s)%s' % (_name, _type, sep)]
has_refs = '`' in _type or ':' in _type
has_space = any(c in ' \t\n\v\f ' for c in _type)
if not has_refs and not has_space:
_type = ':exc:`%s`%s' % (_type, separator)
elif has_desc and has_space:
_type = '*%s*%s' % (_type, separator)
else:
field = ['%s (*%s*)%s' % (_name, _type, sep)]
_type = '%s%s' % (_type, separator)
if has_desc:
field = [_type + _desc[0]] + _desc[1:]
else:
field = ['%s%s' % (_name, sep)]
elif _type:
if '`' in _type:
field = ['%s%s' % (_type, sep)]
field = [_type]
else:
field = ['*%s*%s' % (_type, sep)]
else:
field = []
field = field + _desc
field = _desc
if multi:
if lines:
lines.extend(self._format_block(padding + ' * ', field))
@ -545,6 +563,8 @@ class GoogleDocstring(UnicodeMixin):
lines.extend(self._format_block(field_type + ' * ', field))
else:
lines.extend(self._format_block(field_type + ' ', field))
if lines and lines[-1]:
lines.append('')
return lines
def _parse_references_section(self, section):
@ -574,7 +594,8 @@ class GoogleDocstring(UnicodeMixin):
else:
lines.extend(self._format_block(':returns: ', field))
if _type and use_rtype:
lines.append(':rtype: %s' % _type)
lines.extend([':rtype: %s' % _type, ''])
if lines and lines[-1]:
lines.append('')
return lines
@ -593,6 +614,27 @@ class GoogleDocstring(UnicodeMixin):
fields = self._consume_returns_section()
return self._format_fields('Yields', fields)
def _partition_field_on_colon(self, line):
before_colon = []
after_colon = []
colon = ''
found_colon = False
for i, source in enumerate(_xref_regex.split(line)):
if found_colon:
after_colon.append(source)
else:
if (i % 2) == 0 and ":" in source:
found_colon = True
before, colon, after = source.partition(":")
before_colon.append(before)
after_colon.append(after)
else:
before_colon.append(source)
return ("".join(before_colon).strip(),
colon,
"".join(after_colon).strip())
def _strip_empty(self, lines):
if lines:
start = -1
@ -614,16 +656,14 @@ class GoogleDocstring(UnicodeMixin):
class NumpyDocstring(GoogleDocstring):
"""Parse NumPy style docstrings.
Convert NumPy style docstrings to reStructuredText.
"""Convert NumPy style docstrings to reStructuredText.
Parameters
----------
docstring : str or list of str
docstring : str or List[str]
The docstring to parse, given either as a string or split into
individual lines.
config : sphinx.ext.napoleon.Config or sphinx.config.Config, optional
config : Optional[sphinx.ext.napoleon.Config or sphinx.config.Config]
The configuration settings to use. If not given, defaults to the
config object on `app`; or if `app` is not given defaults to the
a new `sphinx.ext.napoleon.Config` object.
@ -634,17 +674,17 @@ class NumpyDocstring(GoogleDocstring):
Other Parameters
----------------
app : sphinx.application.Sphinx, optional
app : Optional[sphinx.application.Sphinx]
Application object representing the Sphinx process.
what : str, optional
what : Optional[str]
A string specifying the type of the object to which the docstring
belongs. Valid values: "module", "class", "exception", "function",
"method", "attribute".
name : str, optional
name : Optional[str]
The fully qualified name of the object.
obj : module, class, exception, function, method, or attribute
The object to which the docstring belongs.
options : sphinx.ext.autodoc.Options, optional
options : Optional[sphinx.ext.autodoc.Options]
The options given to the directive: an object with attributes
inherited_members, undoc_members, show_inheritance and noindex that
are True if the flag option of same name was given to the auto
@ -706,7 +746,7 @@ class NumpyDocstring(GoogleDocstring):
Returns
-------
list of str
List[str]
The lines of the docstring in a list.
"""
@ -719,9 +759,7 @@ class NumpyDocstring(GoogleDocstring):
def _consume_field(self, parse_type=True, prefer_type=False):
line = next(self._line_iter)
if parse_type:
_name, _, _type = line.partition(':')
if not _name:
_type = line
_name, _, _type = self._partition_field_on_colon(line)
else:
_name, _type = line, ''
_name, _type = _name.strip(), _type.strip()

View File

@ -164,7 +164,7 @@ class PygmentsBridge(object):
lexer = lexers[lang]
else:
try:
lexer = lexers[lang] = get_lexer_by_name(lang, **opts or {})
lexer = lexers[lang] = get_lexer_by_name(lang, **(opts or {}))
except ClassNotFound:
if warn:
warn('Pygments lexer name %r is not known' % lang)

View File

@ -13,6 +13,7 @@ import re
from six import iteritems, itervalues, text_type, string_types
from six.moves import cPickle as pickle
from docutils.nodes import raw, comment, title, Text, NodeVisitor, SkipNode
from os import path
from sphinx.util import jsdump, rpartition
@ -42,6 +43,7 @@ class SearchLanguage(object):
lang = None
language_name = None
stopwords = set()
js_stemmer_rawcode = None
js_stemmer_code = """
/**
* Dummy stemmer for languages without stemming rules.
@ -377,3 +379,11 @@ class IndexBuilder(object):
search_language_stop_words = jsdump.dumps(sorted(self.lang.stopwords)),
search_scorer_tool = self.js_scorer_code,
)
def get_js_stemmer_rawcode(self):
if self.lang.js_stemmer_rawcode:
return path.join(
path.dirname(path.abspath(__file__)),
'non-minified-js',
self.lang.js_stemmer_rawcode
)

View File

@ -120,6 +120,7 @@ var Stemmer = JSX.require("src/danish-stemmer.jsx").DanishStemmer;
class SearchDanish(SearchLanguage):
lang = 'da'
language_name = 'Danish'
js_stemmer_rawcode = 'danish-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = danish_stopwords

View File

@ -303,6 +303,7 @@ var Stemmer = JSX.require("src/german-stemmer.jsx").GermanStemmer;
class SearchGerman(SearchLanguage):
lang = 'de'
language_name = 'German'
js_stemmer_rawcode = 'german-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = german_stopwords

View File

@ -363,6 +363,7 @@ var Stemmer = JSX.require("src/spanish-stemmer.jsx").SpanishStemmer;
class SearchSpanish(SearchLanguage):
lang = 'es'
language_name = 'Spanish'
js_stemmer_rawcode = 'spanish-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = spanish_stopwords

View File

@ -113,6 +113,7 @@ var Stemmer = JSX.require("src/finnish-stemmer.jsx").FinnishStemmer;
class SearchFinnish(SearchLanguage):
lang = 'fi'
language_name = 'Finnish'
js_stemmer_rawcode = 'finnish-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = finnish_stopwords

View File

@ -199,6 +199,7 @@ var Stemmer = JSX.require("src/french-stemmer.jsx").FrenchStemmer;
class SearchFrench(SearchLanguage):
lang = 'fr'
language_name = 'French'
js_stemmer_rawcode = 'french-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = french_stopwords

View File

@ -227,6 +227,7 @@ var Stemmer = JSX.require("src/hungarian-stemmer.jsx").HungarianStemmer;
class SearchHungarian(SearchLanguage):
lang = 'hu'
language_name = 'Hungarian'
js_stemmer_rawcode = 'hungarian-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = hungarian_stopwords

View File

@ -316,6 +316,7 @@ var Stemmer = JSX.require("src/italian-stemmer.jsx").ItalianStemmer;
class SearchItalian(SearchLanguage):
lang = 'it'
language_name = 'Italian'
js_stemmer_rawcode = 'italian-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = italian_stopwords

View File

@ -120,6 +120,7 @@ var Stemmer = JSX.require("src/dutch-stemmer.jsx").DutchStemmer;
class SearchDutch(SearchLanguage):
lang = 'nl'
language_name = 'Dutch'
js_stemmer_rawcode = 'dutch-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = danish_stopwords

View File

@ -202,6 +202,7 @@ var Stemmer = JSX.require("src/norwegian-stemmer.jsx").NorwegianStemmer;
class SearchNorwegian(SearchLanguage):
lang = 'no'
language_name = 'Norwegian'
js_stemmer_rawcode = 'norwegian-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = norwegian_stopwords

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -262,6 +262,7 @@ var Stemmer = JSX.require("src/portuguese-stemmer.jsx").PortugueseStemmer;
class SearchPortuguese(SearchLanguage):
lang = 'pt'
language_name = 'Portuguese'
js_stemmer_rawcode = 'portuguese-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = portuguese_stopwords

View File

@ -22,6 +22,7 @@ var Stemmer = JSX.require("src/romanian-stemmer.jsx").RomanianStemmer;
class SearchRomanian(SearchLanguage):
lang = 'ro'
language_name = 'Romanian'
js_stemmer_rawcode = 'romanian-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = []

View File

@ -251,6 +251,7 @@ var Stemmer = JSX.require("src/russian-stemmer.jsx").RussianStemmer;
class SearchRussian(SearchLanguage):
lang = 'ru'
language_name = 'Russian'
js_stemmer_rawcode = 'russian-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = russian_stopwords

View File

@ -140,6 +140,7 @@ var Stemmer = JSX.require("src/swedish-stemmer.jsx").SwedishStemmer;
class SearchSwedish(SearchLanguage):
lang = 'sv'
language_name = 'Swedish'
js_stemmer_rawcode = 'swedish-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = swedish_stopwords

View File

@ -22,6 +22,7 @@ var Stemmer = JSX.require("src/turkish-stemmer.jsx").TurkishStemmer;
class SearchTurkish(SearchLanguage):
lang = 'tr'
language_name = 'Turkish'
js_stemmer_rawcode = 'turkish-stemmer.js'
js_stemmer_code = js_stemmer
stopwords = []

View File

@ -2,13 +2,15 @@
* searchtools.js_t
* ~~~~~~~~~~~~~~~~
*
* Sphinx JavaScript utilties for the full-text search.
* Sphinx JavaScript utilities for the full-text search.
*
* :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
{% if search_language_stemming_code %}
/* Non-minified version JS is _stemmer.js if file is provided */ {% endif -%}
{{ search_language_stemming_code|safe }}
{% if search_scorer_tool %}
@ -414,7 +416,7 @@ var Search = {
* helper function to return a node containing the
* search summary for a given text. keywords is a list
* of stemmed words, hlwords is the list of normal, unstemmed
* words. the first one is used to find the occurance, the
* words. the first one is used to find the occurrence, the
* latter for highlighting it.
*/
makeSearchSummary : function(text, keywords, hlwords) {

View File

@ -2,7 +2,7 @@
* websupport.js
* ~~~~~~~~~~~~~
*
* sphinx.websupport utilties for all documentation.
* sphinx.websupport utilities for all documentation.
*
* :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.

View File

@ -0,0 +1 @@
@import url("classic.css");

View File

@ -1,8 +1,8 @@
{%- extends "basic/layout.html" %}
{%- block extrahead %}
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="{{ pathto('_static/ie6.css', 1) }}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->

View File

@ -71,26 +71,26 @@ class Theme(object):
@classmethod
def load_extra_theme(cls, name):
if name in ('alabaster', 'sphinx_rtd_theme'):
if name == 'alabaster':
cls.themes[name] = (os.path.join(alabaster.get_path(), name), None)
# alabaster theme also requires 'alabaster' extension, it will be loaded at
# sphinx.******* module.
return
if name == 'sphinx_rtd_theme':
cls.themes[name] = (
os.path.join(sphinx_rtd_theme.get_html_theme_path(), name), None)
return
themedir = alabaster.get_path()
# alabaster theme also requires 'alabaster' extension, it will be loaded
# at sphinx.application module.
elif name == 'sphinx_rtd_theme':
themedir = sphinx_rtd_theme.get_html_theme_path()
else:
raise NotImplementedError('Programming Error')
else:
for themedir in load_theme_plugins():
if not path.isdir(themedir):
continue
for theme in os.listdir(themedir):
if theme != name:
continue
if not path.isfile(path.join(themedir, theme, THEMECONF)):
continue
cls.themes[theme] = (path.join(themedir, theme), None)
if path.isfile(path.join(themedir, name, THEMECONF)):
break
else:
# specified theme is not found
return
cls.themepath.append(themedir)
cls.themes[name] = (path.join(themedir, name), None)
return
def __init__(self, name, warn=None):
@ -101,11 +101,13 @@ class Theme(object):
'(missing theme.conf?)' % name)
self.name = name
if name == 'default' and warn:
warn("'default' html theme has been renamed to 'classic'. "
"Please change your html_theme setting either to "
"the new 'alabaster' default theme, or to 'classic' "
"to keep using the old default.")
# Do not warn yet -- to be compatible with old Sphinxes, people *have*
# to use "default".
# if name == 'default' and warn:
# warn("'default' html theme has been renamed to 'classic'. "
# "Please change your html_theme setting either to "
# "the new 'alabaster' default theme, or to 'classic' "
# "to keep using the old default.")
tdir, tinfo = self.themes[name]
if tinfo is None:
@ -133,6 +135,11 @@ class Theme(object):
inherit = self.themeconf.get('theme', 'inherit')
except configparser.NoOptionError:
raise ThemeError('theme %r doesn\'t have "inherit" setting' % name)
if inherit in ['alabaster', 'sphinx_rtd_theme']:
# include 'alabaster' or 'sphinx_themes' automatically #1794
self.load_extra_theme(inherit)
if inherit == 'none':
self.base = None
elif inherit not in self.themes:
@ -211,7 +218,7 @@ def load_theme_plugins():
func_or_path = plugin.load()
try:
path = func_or_path()
except:
except Exception:
path = func_or_path
if isinstance(path, string_types):

View File

@ -33,9 +33,7 @@ def get_terminal_width():
struct.pack('hhhh', 0, 0, 0, 0))
height, width = struct.unpack('hhhh', call)[:2]
terminal_width = width
except (SystemExit, KeyboardInterrupt):
raise
except:
except Exception:
# FALLBACK
terminal_width = int(os.environ.get('COLUMNS', 80)) - 1
return terminal_width

View File

@ -119,6 +119,10 @@ class BaseSearch(object):
"""Required by the HTML builder."""
return {}
def get_js_stemmer_rawcode(self):
"""Required by the HTML builder."""
return None
# The built-in search adapters.
SEARCH_ADAPTERS = {

View File

@ -349,8 +349,9 @@ class HTMLTranslator(BaseTranslator):
if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
self.add_permalink_ref(node.parent, _('Permalink to this code'))
elif isinstance(node.parent, nodes.figure):
self.add_permalink_ref(
node.parent.traverse(nodes.image)[0], _('Permalink to this image'))
image_nodes = node.parent.traverse(nodes.image)
target_node = image_nodes and image_nodes[0] or node.parent
self.add_permalink_ref(target_node, _('Permalink to this image'))
elif node.parent.get('toctree'):
self.add_permalink_ref(node.parent.parent, _('Permalink to this toctree'))

View File

@ -31,6 +31,9 @@ class NamedtupleSubclass(namedtuple('NamedtupleSubclass', ('attr1', 'attr2'))):
Quick description of attr1
attr2 : Another arbitrary type
Quick description of attr2
attr3 : Type
Adds a newline after the type
"""
# To avoid creating a dict, as a namedtuple doesn't have it:
@ -50,21 +53,21 @@ class NamedtupleSubclassTest(BaseDocstringTest):
actual = str(NumpyDocstring(cleandoc(NamedtupleSubclass.__doc__),
config=config, app=None, what='class',
name='NamedtupleSubclass', obj=NamedtupleSubclass))
expected = dedent("""\
Sample namedtuple subclass
expected = """\
Sample namedtuple subclass
.. attribute:: attr1
.. attribute:: attr1
*Arbitrary type*
*Arbitrary type* -- Quick description of attr1
Quick description of attr1
.. attribute:: attr2
.. attribute:: attr2
*Another arbitrary type* -- Quick description of attr2
*Another arbitrary type*
.. attribute:: attr3
Quick description of attr2
""")
*Type* -- Adds a newline after the type
"""
self.assertEqual(expected, actual)
@ -96,9 +99,9 @@ class GoogleDocstringTest(BaseDocstringTest):
"""
Single line summary
:Parameters: **arg1** (*str*) --
Extended
description of arg1"""
:Parameters: **arg1** (*str*) -- Extended
description of arg1
"""
), (
"""
Single line summary
@ -117,19 +120,16 @@ class GoogleDocstringTest(BaseDocstringTest):
"""
Single line summary
:Parameters: * **arg1** (*str*) --
Extended
:Parameters: * **arg1** (*str*) -- Extended
description of arg1
* **arg2** (*int*) --
Extended
* **arg2** (*int*) -- Extended
description of arg2
:Keyword Arguments: * **kwarg1** (*str*) --
Extended
:Keyword Arguments: * **kwarg1** (*str*) -- Extended
description of kwarg1
* **kwarg2** (*int*) --
Extended
description of kwarg2"""
* **kwarg2** (*int*) -- Extended
description of kwarg2
"""
), (
"""
Single line summary
@ -148,19 +148,16 @@ class GoogleDocstringTest(BaseDocstringTest):
"""
Single line summary
:Parameters: * **arg1** (*str*) --
Extended
:Parameters: * **arg1** (*str*) -- Extended
description of arg1
* **arg2** (*int*) --
Extended
* **arg2** (*int*) -- Extended
description of arg2
:Keyword Arguments: * **kwarg1** (*str*) --
Extended
:Keyword Arguments: * **kwarg1** (*str*) -- Extended
description of kwarg1
* **kwarg2** (*int*) --
Extended
description of kwarg2"""
* **kwarg2** (*int*) -- Extended
description of kwarg2
"""
), (
"""
Single line summary
@ -172,9 +169,9 @@ class GoogleDocstringTest(BaseDocstringTest):
"""
Single line summary
:returns: *str* --
Extended
description of return value"""
:returns: *str* -- Extended
description of return value
"""
), (
"""
Single line summary
@ -186,9 +183,9 @@ class GoogleDocstringTest(BaseDocstringTest):
"""
Single line summary
:returns: *str* --
Extended
description of return value"""
:returns: *str* -- Extended
description of return value
"""
), (
"""
Single line summary
@ -201,7 +198,8 @@ class GoogleDocstringTest(BaseDocstringTest):
Single line summary
:returns: Extended
description of return value"""
description of return value
"""
), (
"""
Single line summary
@ -215,13 +213,11 @@ class GoogleDocstringTest(BaseDocstringTest):
"""
Single line summary
:Parameters: * **arg1** (*str*) --
Extended
:Parameters: * **arg1** (*str*) -- Extended
description of arg1
* **\\*args** --
Variable length argument list.
* **\\*\\*kwargs** --
Arbitrary keyword arguments."""
* **\\*args** -- Variable length argument list.
* **\\*\\*kwargs** -- Arbitrary keyword arguments.
"""
), (
"""
Single line summary
@ -233,9 +229,9 @@ class GoogleDocstringTest(BaseDocstringTest):
"""
Single line summary
:Yields: *str* --
Extended
description of yielded value"""
:Yields: *str* -- Extended
description of yielded value
"""
), (
"""
Single line summary
@ -248,7 +244,8 @@ class GoogleDocstringTest(BaseDocstringTest):
Single line summary
:Yields: Extended
description of yielded value"""
description of yielded value
"""
)]
def test_docstrings(self):
@ -305,9 +302,7 @@ Attributes:
expected = """\
.. attribute:: in_attr
:class:`numpy.ndarray`
super-dooper attribute
:class:`numpy.ndarray` -- super-dooper attribute
"""
self.assertEqual(expected, actual)
@ -320,9 +315,7 @@ Attributes:
expected = """\
.. attribute:: in_attr
*numpy.ndarray*
super-dooper attribute
*numpy.ndarray* -- super-dooper attribute
"""
self.assertEqual(expected, actual)
@ -360,6 +353,183 @@ Returns:
actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual)
def test_xrefs_in_return_type(self):
docstring = """Example Function
Returns:
:class:`numpy.ndarray`: A :math:`n \\times 2` array containing
a bunch of math items
"""
expected = """Example Function
:returns: A :math:`n \\times 2` array containing
a bunch of math items
:rtype: :class:`numpy.ndarray`
"""
actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual)
def test_raises_types(self):
docstrings = [("""
Example Function
Raises:
RuntimeError:
A setting wasn't specified, or was invalid.
ValueError:
Something something value error.
""", """
Example Function
:raises: * :exc:`RuntimeError` -- A setting wasn't specified, or was invalid.
* :exc:`ValueError` -- Something something value error.
"""),
################################
("""
Example Function
Raises:
InvalidDimensionsError
""", """
Example Function
:raises: :exc:`InvalidDimensionsError`
"""),
################################
("""
Example Function
Raises:
Invalid Dimensions Error
""", """
Example Function
:raises: Invalid Dimensions Error
"""),
################################
("""
Example Function
Raises:
Invalid Dimensions Error: With description
""", """
Example Function
:raises: *Invalid Dimensions Error* -- With description
"""),
################################
("""
Example Function
Raises:
InvalidDimensionsError: If the dimensions couldn't be parsed.
""", """
Example Function
:raises: :exc:`InvalidDimensionsError` -- If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises:
Invalid Dimensions Error: If the dimensions couldn't be parsed.
""", """
Example Function
:raises: *Invalid Dimensions Error* -- If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises:
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError`
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`: If the dimensions couldn't be parsed.
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError` -- If the dimensions couldn't """
"""be parsed.
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`: If the dimensions couldn't be parsed,
then a :class:`exc.InvalidDimensionsError` will be raised.
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError` -- If the dimensions couldn't """
"""be parsed,
then a :class:`exc.InvalidDimensionsError` will be raised.
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`: If the dimensions couldn't be parsed.
:class:`exc.InvalidArgumentsError`: If the arguments are invalid.
""", """
Example Function
:raises: * :class:`exc.InvalidDimensionsError` -- If the dimensions """
"""couldn't be parsed.
* :class:`exc.InvalidArgumentsError` -- If the arguments are invalid.
"""),
################################
("""
Example Function
Raises:
:class:`exc.InvalidDimensionsError`
:class:`exc.InvalidArgumentsError`
""", """
Example Function
:raises: * :class:`exc.InvalidDimensionsError`
* :class:`exc.InvalidArgumentsError`
""")]
for docstring, expected in docstrings:
actual = str(GoogleDocstring(docstring))
self.assertEqual(expected, actual)
def test_kwargs_in_arguments(self):
docstring = """Allows to create attributes binded to this device.
@ -421,9 +591,9 @@ class NumpyDocstringTest(BaseDocstringTest):
"""
Single line summary
:Parameters: **arg1** (*str*) --
Extended
description of arg1"""
:Parameters: **arg1** (*str*) -- Extended
description of arg1
"""
), (
"""
Single line summary
@ -449,19 +619,16 @@ class NumpyDocstringTest(BaseDocstringTest):
"""
Single line summary
:Parameters: * **arg1** (*str*) --
Extended
:Parameters: * **arg1** (*str*) -- Extended
description of arg1
* **arg2** (*int*) --
Extended
* **arg2** (*int*) -- Extended
description of arg2
:Keyword Arguments: * **kwarg1** (*str*) --
Extended
:Keyword Arguments: * **kwarg1** (*str*) -- Extended
description of kwarg1
* **kwarg2** (*int*) --
Extended
description of kwarg2"""
* **kwarg2** (*int*) -- Extended
description of kwarg2
"""
), (
"""
Single line summary
@ -475,9 +642,9 @@ class NumpyDocstringTest(BaseDocstringTest):
"""
Single line summary
:returns: *str* --
Extended
description of return value"""
:returns: *str* -- Extended
description of return value
"""
), (
"""
Single line summary
@ -491,9 +658,9 @@ class NumpyDocstringTest(BaseDocstringTest):
"""
Single line summary
:returns: *str* --
Extended
description of return value"""
:returns: *str* -- Extended
description of return value
"""
), (
"""
Single line summary
@ -510,12 +677,10 @@ class NumpyDocstringTest(BaseDocstringTest):
"""
Single line summary
:Parameters: * **arg1** (*str*) --
Extended description of arg1
* ***args** --
Variable length argument list.
* ****kwargs** --
Arbitrary keyword arguments."""
:Parameters: * **arg1** (*str*) -- Extended description of arg1
* ***args** -- Variable length argument list.
* ****kwargs** -- Arbitrary keyword arguments.
"""
), (
"""
Single line summary
@ -529,9 +694,9 @@ class NumpyDocstringTest(BaseDocstringTest):
"""
Single line summary
:Yields: *str* --
Extended
description of yielded value"""
:Yields: *str* -- Extended
description of yielded value
"""
), (
"""
Single line summary
@ -545,9 +710,9 @@ class NumpyDocstringTest(BaseDocstringTest):
"""
Single line summary
:Yields: *str* --
Extended
description of yielded value"""
:Yields: *str* -- Extended
description of yielded value
"""
)]
def test_docstrings(self):
@ -696,3 +861,210 @@ arg_ : type
actual = str(NumpyDocstring(docstring, config, app, "class"))
self.assertEqual(expected, actual)
def test_raises_types(self):
docstrings = [("""
Example Function
Raises
------
RuntimeError
A setting wasn't specified, or was invalid.
ValueError
Something something value error.
""", """
Example Function
:raises: * :exc:`RuntimeError` -- A setting wasn't specified, or was invalid.
* :exc:`ValueError` -- Something something value error.
"""),
################################
("""
Example Function
Raises
------
InvalidDimensionsError
""", """
Example Function
:raises: :exc:`InvalidDimensionsError`
"""),
################################
("""
Example Function
Raises
------
Invalid Dimensions Error
""", """
Example Function
:raises: Invalid Dimensions Error
"""),
################################
("""
Example Function
Raises
------
Invalid Dimensions Error
With description
""", """
Example Function
:raises: *Invalid Dimensions Error* -- With description
"""),
################################
("""
Example Function
Raises
------
InvalidDimensionsError
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: :exc:`InvalidDimensionsError` -- If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises
------
Invalid Dimensions Error
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: *Invalid Dimensions Error* -- If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises
------
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: If the dimensions couldn't be parsed.
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError`
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
If the dimensions couldn't be parsed.
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError` -- If the dimensions couldn't """
"""be parsed.
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
If the dimensions couldn't be parsed,
then a :class:`exc.InvalidDimensionsError` will be raised.
""", """
Example Function
:raises: :class:`exc.InvalidDimensionsError` -- If the dimensions couldn't """
"""be parsed,
then a :class:`exc.InvalidDimensionsError` will be raised.
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
If the dimensions couldn't be parsed.
:class:`exc.InvalidArgumentsError`
If the arguments are invalid.
""", """
Example Function
:raises: * :class:`exc.InvalidDimensionsError` -- If the dimensions """
"""couldn't be parsed.
* :class:`exc.InvalidArgumentsError` -- If the arguments """
"""are invalid.
"""),
################################
("""
Example Function
Raises
------
:class:`exc.InvalidDimensionsError`
:class:`exc.InvalidArgumentsError`
""", """
Example Function
:raises: * :class:`exc.InvalidDimensionsError`
* :class:`exc.InvalidArgumentsError`
""")]
for docstring, expected in docstrings:
config = Config()
app = mock.Mock()
actual = str(NumpyDocstring(docstring, config, app, "method"))
self.assertEqual(expected, actual)
def test_xrefs_in_return_type(self):
docstring = """
Example Function
Returns
-------
:class:`numpy.ndarray`
A :math:`n \\times 2` array containing
a bunch of math items
"""
expected = """
Example Function
:returns: A :math:`n \\times 2` array containing
a bunch of math items
:rtype: :class:`numpy.ndarray`
"""
config = Config()
app = mock.Mock()
actual = str(NumpyDocstring(docstring, config, app, "method"))
self.assertEqual(expected, actual)