Merge remote-tracking branch 'upstream/master' into 5842-apidoc-extensions

This commit is contained in:
cocodrips
2018-12-26 11:31:44 +09:00
59 changed files with 711 additions and 386 deletions

59
CHANGES
View File

@@ -17,6 +17,7 @@ Dependencies
which in Ubuntu xenial are provided by package ``fonts-freefont-otf``, and
e.g. in Fedora 29 via package ``texlive-gnu-freefont``.
* requests 2.5.0 or above
* The six package is no longer a dependency.
Incompatible changes
--------------------
@@ -45,6 +46,11 @@ Incompatible changes
block. As a result, they are highlighted as python3 by default.
* The order of argument for ``HTMLTranslator``, ``HTML5Translator`` and
``ManualPageTranslator`` are changed
* LaTeX: hard-coded redefinitions of ``\l@section`` and ``\l@subsection``
formerly done during loading of ``'manual'`` docclass get executed later, at
time of ``\sphinxtableofcontents``. This means that custom user definitions
from LaTeX preamble now get overwritten. Use ``\sphinxtableofcontentshook``
to insert custom user definitions. See :ref:`latex-macros`.
Deprecated
----------
@@ -127,6 +133,10 @@ Features added
* LaTeX: support rendering (not in math, yet) of Greek and Cyrillic Unicode
letters in non-Cyrillic document even with ``'pdflatex'`` as
:confval:`latex_engine` (refs: #5645)
* #5660: The ``versionadded``, ``versionchanged`` and ``deprecated`` directives
are now generated with their own specific CSS classes
(``added``, ``changed`` and ``deprecated``, respectively) in addition to the
generic ``versionmodified`` class.
* #5841: apidoc: Add --extensions option to sphinx-apidoc
Bugs fixed
@@ -149,7 +159,7 @@ Bugs fixed
Testing
--------
Release 1.8.3 (in development)
Release 1.8.4 (in development)
==============================
Dependencies
@@ -167,6 +177,22 @@ Features added
Bugs fixed
----------
Testing
--------
Release 1.8.3 (released Dec 26, 2018)
=====================================
Features added
--------------
* LaTeX: it is possible to insert custom material to appear on back of title
page, see discussion of ``'maketitle'`` key of :confval:`latex_elements`
(``'manual'`` docclass only)
Bugs fixed
----------
* #5725: mathjax: Use CDN URL for "latest" version by default
* #5460: html search does not work with some 3rd party themes
* #5520: LaTeX, caption package incompatibility since Sphinx 1.6
@@ -179,9 +205,13 @@ Bugs fixed
* #5636: C++, fix parsing of floating point literals.
* #5496 (again): C++, fix assertion in partial builds with duplicates.
* #5724: quickstart: sphinx-quickstart fails when $LC_ALL is empty
Testing
--------
* #1956: Default conf.py is not PEP8-compliant
* #5849: LaTeX: document class ``\maketitle`` is overwritten with no
possibility to use original meaning in place of Sphinx custom one
* #5834: apidoc: wrong help for ``--tocfile``
* #5800: todo: crashed if todo is defined in TextElement
* #5846: htmlhelp: convert hex escaping to decimal escaping in .hhc/.hhk files
* htmlhelp: broken .hhk file generated when title contains a double quote
Release 1.8.2 (released Nov 11, 2018)
=====================================
@@ -551,27 +581,6 @@ Documentation
* #5083: Fix wrong make.bat option for internationalization.
* #5115: napoleon: add admonitions added by #4613 to the docs.
Release 1.7.10 (in development)
===============================
Dependencies
------------
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
Testing
--------
Release 1.7.9 (released Sep 05, 2018)
=====================================

View File

@@ -25,6 +25,7 @@ Sphinx documentation contents
templating
latex
extdev/index
development/tutorials/index
faq
glossary

View File

@@ -100,7 +100,7 @@ This is the current list of contributed extensions in that repository:
- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_
See the :ref:`extension tutorial <exttut>` on getting started with writing your
See the :doc:`extension tutorials <../development/tutorials/index>` on getting started with writing your
own extensions.

View File

@@ -0,0 +1,162 @@
Developing a "Hello world" directive
====================================
The objective of this tutorial is to create a very basic extension that adds a new
directive that outputs a paragraph containing `hello world`.
Only basic information is provided in this tutorial. For more information,
refer to the :doc:`other tutorials <index>` that go into more
details.
.. warning:: For this extension, you will need some basic understanding of docutils_
and Python.
Creating a new extension file
-----------------------------
Your extension file could be in any folder of your project. In our case,
let's do the following:
#. Create an :file:`_ext` folder in :file:`source`.
#. Create a new Python file in the :file:`_ext` folder called
:file:`helloworld.py`.
Here is an example of the folder structure you might obtain:
.. code-block:: text
└── source
   ├── _ext
  └── helloworld.py
   ├── _static
   ├── _themes
   ├── conf.py
   ├── somefolder
   ├── somefile.rst
   └── someotherfile.rst
Writing the extension
---------------------
Open :file:`helloworld.py` and paste the following code in it:
.. code-block:: python
from docutils import nodes
from docutils.parsers.rst import Directive
class HelloWorld(Directive):
def run(self):
paragraph_node = nodes.paragraph(text='Hello World!')
return [paragraph_node]
def setup(app):
app.add_directive("helloworld", HelloWorld)
Some essential things are happening in this example, and you will see them
in all directives:
.. rubric:: Directive declaration
Our new directive is declared in the ``HelloWorld`` class, it extends
docutils_' ``Directive`` class. All extensions that create directives
should extend this class.
.. rubric:: ``run`` method
This method is a requirement and it is part of every directive. It contains
the main logic of the directive and it returns a list of docutils nodes to
be processed by Sphinx.
.. seealso::
:doc:`todo`
.. rubric:: docutils nodes
The ``run`` method returns a list of nodes. Nodes are docutils' way of
representing the content of a document. There are many types of nodes
available: text, paragraph, reference, table, etc.
.. seealso::
`The docutils documentation on nodes <docutils nodes>`_
The ``nodes.paragraph`` class creates a new paragraph node. A paragraph
node typically contains some text that we can set during instantiation using
the ``text`` parameter.
.. rubric:: ``setup`` function
This function is a requirement. We use it to plug our new directive into
Sphinx.
The simplest thing you can do it call the ``app.add_directive`` method.
.. note::
The first argument is the name of the directive itself as used in an rST file.
In our case, we would use ``helloworld``:
.. code-block:: rst
Some intro text here...
.. helloworld::
Some more text here...
Updating the conf.py file
-------------------------
The extension file has to be declared in your :file:`conf.py` file to make
Sphinx aware of it:
#. Open :file:`conf.py`. It is in the :file:`source` folder by default.
#. Add ``sys.path.append(os.path.abspath("./_ext"))`` before
the ``extensions`` variable declaration (if it exists).
#. Update or create the ``extensions`` list and add the
extension file name to the list:
.. code-block:: python
extensions.append('helloworld')
You can now use the extension.
.. admonition:: Example
.. code-block:: rst
Some intro text here...
.. helloworld::
Some more text here...
The sample above would generate:
.. code-block:: text
Some intro text here...
Hello World!
Some more text here...
This is the very basic principle of an extension that creates a new directive.
For a more advanced example, refer to :doc:`todo`.
Further reading
---------------
You can create your own nodes if needed, refer to the
:doc:`todo` for more information.
.. _docutils: http://docutils.sourceforge.net/
.. _`docutils nodes`: http://docutils.sourceforge.net/docs/ref/doctree.html

View File

@@ -0,0 +1,11 @@
Extension tutorials
===================
Refer to the following tutorials to get started with extension development.
.. toctree::
:caption: Directive tutorials
:maxdepth: 1
helloworld
todo

View File

@@ -1,7 +1,5 @@
.. _exttut:
Tutorial: Writing a simple extension
====================================
Developing a "TODO" extension
=============================
This section is intended as a walkthrough for the creation of custom extensions.
It covers the basics of writing and activating an extension, as well as
@@ -12,112 +10,12 @@ include todo entries in the documentation, and to collect these in a central
place. (A similar "todo" extension is distributed with Sphinx.)
Important objects
-----------------
There are several key objects whose API you will use while writing an
extension. These are:
**Application**
The application object (usually called ``app``) is an instance of
: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
``env.app``.
**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 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
persist for incremental rebuilds.
If you have the application or builder object, the environment is available
as ``app.env`` or ``builder.env``.
**Builder**
The builder object (usually called ``builder``) is an instance of a specific
subclass of :class:`.Builder`. Each builder class knows how to convert the
parsed documents into an output format, or otherwise process them (e.g. check
external links).
If you have the application object, the builder is available as
``app.builder``.
**Config**
The config object (usually called ``config``) provides the values of
configuration values set in :file:`conf.py` as attributes. It is an instance
of :class:`.Config`.
The config is available as ``app.config`` or ``env.config``.
Build Phases
------------
One thing that is vital in order to understand extension mechanisms is the way
in which a Sphinx project is built: this works in several phases.
**Phase 0: Initialization**
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.
**Phase 1: Reading**
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 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.
There are nodes provided by docutils, which are documented `in the docutils
documentation <http://docutils.sourceforge.net/docs/ref/doctree.html>`__.
Additional nodes are provided by Sphinx and :ref:`documented here <nodes>`.
During reading, the build environment is updated with all meta- and cross
reference data of the read documents, such as labels, the names of headings,
described Python objects and index entries. This will later be used to
replace the temporary nodes.
The parsed doctrees are stored on the disk, because it is not possible to
hold all of them in memory.
**Phase 2: Consistency checks**
Some checking is done to ensure no surprises in the built documents.
**Phase 3: Resolving**
Now that the metadata and cross-reference data of all existing documents is
known, all temporary nodes are replaced by nodes that can be converted into
output using components called tranform. For example, links are created for
object references that exist, and simple literal nodes are created for those
that don't.
**Phase 4: Writing**
This phase converts the resolved doctrees to the desired output format, such
as HTML or LaTeX. This happens via a so-called docutils writer that visits
the individual nodes of each doctree and produces some output in the process.
.. note::
Some builders deviate from this general build plan, for example, the builder
that checks external links does not need anything more than the parsed
doctrees and therefore does not have phases 2--4.
Extension Design
----------------
.. note:: To understand the design this extension, refer to
:ref:`important-objects` and :ref:`build-phases`.
We want the extension to add the following to Sphinx:
* A "todo" directive, containing some content that is marked with "TODO", and
@@ -174,12 +72,13 @@ the individual calls do is the following:
If the third argument was ``'html'``, HTML documents would be full rebuild if the
config value changed its value. This is needed for config values that
influence reading (build phase 1).
influence reading (build :ref:`phase 1 <build-phases>`).
* :meth:`~Sphinx.add_node` adds a new *node class* to the build system. It also
can specify visitor functions for each supported output format. These visitor
functions are needed when the new nodes stay until phase 4 -- since the
``todolist`` node is always replaced in phase 3, it doesn't need any.
functions are needed when the new nodes stay until :ref:`phase 4 <build-phases>`
-- since the ``todolist`` node is always replaced in :ref:`phase 3 <build-phases>`,
it doesn't need any.
We need to create the two node classes ``todo`` and ``todolist`` later.
@@ -276,7 +175,7 @@ The ``todo`` directive function looks like this::
return [targetnode, todo_node]
Several important things are covered here. First, as you can see, you can refer
to the build environment instance using ``self.state.document.settings.env``.
to the :ref:`build environment instance <important-objects>` using ``self.state.document.settings.env``.
Then, to act as a link target (from the todolist), the todo directive needs to
return a target node in addition to the todo node. The target ID (in HTML, this
@@ -340,7 +239,8 @@ Here we clear out all todos whose docname matches the given one from the
added again during parsing.
The other handler belongs to the :event:`doctree-resolved` event. This event is
emitted at the end of phase 3 and allows custom resolving to be done::
emitted at the end of :ref:`phase 3 <build-phases>` and allows custom resolving
to be done::
def process_todo_nodes(app, doctree, fromdocname):
if not app.config.todo_include_todos:

View File

@@ -52,6 +52,115 @@ Note that it is still necessary to register the builder using
.. _entry points: https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins
.. _important-objects:
Important objects
-----------------
There are several key objects whose API you will use while writing an
extension. These are:
**Application**
The application object (usually called ``app``) is an instance of
: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
``env.app``.
**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 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
persist for incremental rebuilds.
If you have the application or builder object, the environment is available
as ``app.env`` or ``builder.env``.
**Builder**
The builder object (usually called ``builder``) is an instance of a specific
subclass of :class:`.Builder`. Each builder class knows how to convert the
parsed documents into an output format, or otherwise process them (e.g. check
external links).
If you have the application object, the builder is available as
``app.builder``.
**Config**
The config object (usually called ``config``) provides the values of
configuration values set in :file:`conf.py` as attributes. It is an instance
of :class:`.Config`.
The config is available as ``app.config`` or ``env.config``.
To see an example of use of these objects, refer to :doc:`../development/tutorials/index`.
.. _build-phases:
Build Phases
------------
One thing that is vital in order to understand extension mechanisms is the way
in which a Sphinx project is built: this works in several phases.
**Phase 0: Initialization**
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.
**Phase 1: Reading**
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 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.
There are nodes provided by docutils, which are documented `in the docutils
documentation <http://docutils.sourceforge.net/docs/ref/doctree.html>`__.
Additional nodes are provided by Sphinx and :ref:`documented here <nodes>`.
During reading, the build environment is updated with all meta- and cross
reference data of the read documents, such as labels, the names of headings,
described Python objects and index entries. This will later be used to
replace the temporary nodes.
The parsed doctrees are stored on the disk, because it is not possible to
hold all of them in memory.
**Phase 2: Consistency checks**
Some checking is done to ensure no surprises in the built documents.
**Phase 3: Resolving**
Now that the metadata and cross-reference data of all existing documents is
known, all temporary nodes are replaced by nodes that can be converted into
output using components called tranform. For example, links are created for
object references that exist, and simple literal nodes are created for those
that don't.
**Phase 4: Writing**
This phase converts the resolved doctrees to the desired output format, such
as HTML or LaTeX. This happens via a so-called docutils writer that visits
the individual nodes of each doctree and produces some output in the process.
.. note::
Some builders deviate from this general build plan, for example, the builder
that checks external links does not need anything more than the parsed
doctrees and therefore does not have phases 2--4.
To see an example of application, refer to :doc:`../development/tutorials/todo`.
.. _ext-metadata:
Extension metadata
@@ -82,8 +191,8 @@ APIs used for writing extensions
--------------------------------
.. toctree::
:maxdepth: 2
tutorial
appapi
projectapi
envapi

View File

@@ -30,7 +30,7 @@ How do I...
``sidebartoc`` block.
... write my own extension?
See the :ref:`extension tutorial <exttut>`.
See the :doc:`/development/tutorials/index`.
... convert from my existing docs using MoinMoin markup?
The easiest way is to convert to xhtml, then convert `xhtml to reST`_.

View File

@@ -365,6 +365,8 @@ Here are some macros from the package file :file:`sphinx.sty` and class files
:file:`sphinxhowto.cls`, :file:`sphinxmanual.cls`, which have public names
thus allowing redefinitions. Check the respective files for the defaults.
.. _latex-macros:
Macros
~~~~~~
@@ -390,13 +392,32 @@ Macros
.. versionadded:: 1.6.3
``\sphinxstylecodecontinued`` and ``\sphinxstylecodecontinues``.
- 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``.
wrapper (defined differently in :file:`sphinxhowto.cls` and in
:file:`sphinxmanual.cls`) of standard ``\tableofcontents``. The macro
``\sphinxtableofcontentshook`` is executed during its expansion right before
``\tableofcontents`` itself.
.. versionchanged:: 1.5
formerly, the meaning of ``\tableofcontents`` was modified by Sphinx.
- the ``\maketitle`` command is redefined by the class files
:file:`sphinxmanual.cls` and :file:`sphinxhowto.cls`.
.. versionchanged:: 2.0
hard-coded redefinitions of ``\l@section`` and ``\l@subsection`` formerly
done during loading of ``'manual'`` docclass are now executed later via
``\sphinxtableofcontentshook``. This macro is also executed by the
``'howto'`` docclass, but defaults to empty with it.
- a custom ``\sphinxmaketitle`` is defined in the class files
:file:`sphinxmanual.cls` and :file:`sphinxhowto.cls` and is used as
default setting of ``'maketitle'`` :confval:`latex_elements` key.
.. versionchanged:: 1.8.3
formerly, ``\maketitle`` from LaTeX document class was modified by
Sphinx.
- for ``'manual'`` docclass a macro ``\sphinxbackoftitlepage``, if it is
defined, gets executed at end of ``\sphinxmaketitle``, before the final
``\clearpage``. Use either the ``'maketitle'`` key or the ``'preamble'`` key
of :confval:`latex_elements` to add a custom definition of
``\sphinxbackoftitlepage``.
.. versionadded:: 1.8.3
- the citation reference is typeset via ``\sphinxcite`` which is a wrapper
of standard ``\cite``.

View File

@@ -2279,10 +2279,22 @@ information.
Previously this was done from inside :file:`sphinx.sty`.
``'maketitle'``
"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.
"maketitle" call, default ``'\\sphinxmaketitle'``. Override
if you want to generate a differently styled title page.
.. hint::
If the key value is set to
``r'\newcommand\sphinxbackoftitlepage{<Extra
material>}\sphinxmaketitle'``, then ``<Extra material>`` will be
typeset on back of title page (``'manual'`` docclass only).
.. versionchanged:: 1.8.3
Original ``\maketitle`` from document class is not overwritten,
hence is re-usable as part of some custom setting for this key.
.. versionadded:: 1.8.3
``\sphinxbackoftitlepage`` optional macro. It can also be defined
inside ``'preamble'`` key rather than this one.
``'releasename'``
value that prefixes ``'release'`` element on title page, default
``'Release'``. As for *title* and *author* used in the tuples of

View File

@@ -41,10 +41,9 @@ Configuration
.. confval:: viewcode_follow_imported_members
If this is ``True``, viewcode extension will follow alias objects that
imported from another module such as functions, classes and attributes. As
side effects, this option else they produce nothing. The default is
``True``.
If this is ``True``, viewcode extension will emit
:event:`viewcode-follow-imported` event to resolve the name of the module
by other extensions. The default is ``True``.
.. versionadded:: 1.3

View File

@@ -113,8 +113,7 @@ Prompt* (:kbd:`⊞Win-r` and type :command:`cmd`). Once the command prompt is
open, type :command:`python --version` and press Enter. If Python is
available, you will see the version of Python printed to the screen. If you do
not have Python installed, refer to the `Hitchhikers Guide to Python's`__
Python on Windows installation guides. You can install either `Python 3`__ or
`Python 2.7`__. Python 3 is recommended.
Python on Windows installation guides. You must install `Python 3`__.
Once Python is installed, you can install Sphinx using :command:`pip`. Refer
to the :ref:`pip installation instructions <install-pypi>` below for more
@@ -122,7 +121,6 @@ information.
__ https://docs.python-guide.org/
__ https://docs.python-guide.org/starting/install3/win/
__ https://docs.python-guide.org/starting/install/win/
.. _install-pypi:

View File

@@ -22,26 +22,41 @@ Configuration
To configure your Sphinx project for Markdown support, proceed as follows:
#. Install *recommonmark*::
#. Install the Markdown parser *recommonmark* from its source on GitHub::
pip install recommonmark
pip install git+https://github.com/rtfd/recommonmark
#. Add the Markdown parser to the ``source_parsers`` configuration variable in
your Sphinx configuration file::
.. note::
source_parsers = {
'.md': 'recommonmark.parser.CommonMarkParser',
The configuration as explained here requires recommonmark version
0.5.0.dev or higher, which is at the time of writing not available on
PyPI. If you want to use a released recommonmark version, follow the
instructions in the `Sphinx 1.8 documentation`__.
__ https://www.sphinx-doc.org/en/1.8/usage/markdown.html
#. Add *recommonmark* to the
:confval:`list of configured extensions <extensions>`::
extensions = ['recommonmark']
.. versionchanged:: 1.8
Version 1.8 deprecates and version 3.0 removes the ``source_parsers``
configuration variable that was used by older *recommonmark* versions.
#. If you want to use Markdown files with extensions other than ``.md``, adjust
the :confval:`source_suffix` variable. The following example configures
Sphinx to parse all files with the extensions ``.md`` and ``.txt`` as
Markdown::
source_suffix = {
'.rst': 'restructuredtext',
'.txt': 'markdown',
'.md': 'markdown',
}
You can replace ``.md`` with a filename extension of your choice.
#. Add the Markdown filename extension to the ``source_suffix`` configuration
variable::
source_suffix = ['.rst', '.md']
#. You can further configure *recommonmark* to allow custom syntax that
standard *CommonMark* doesn't support. Read more in the `recommonmark
standard *CommonMark* doesn't support. Read more in the `recommonmark
documentation`__.
__ https://recommonmark.readthedocs.io/en/latest/auto_structify.html

View File

@@ -15,7 +15,6 @@ if sys.version_info < (3, 5):
sys.exit(1)
install_requires = [
'six>=1.5',
'Jinja2>=2.3',
'Pygments>=2.0',
'docutils>=0.12',

View File

@@ -25,7 +25,6 @@ from docutils.frontend import OptionParser
from docutils.io import DocTreeInput, StringOutput
from docutils.readers.doctree import Reader as DoctreeReader
from docutils.utils import relative_path
from six import text_type
from sphinx import package_dir, __display_version__
from sphinx.application import ENV_PICKLE_FILENAME
@@ -86,10 +85,10 @@ def get_stable_hash(obj):
return get_stable_hash(list(obj.items()))
elif isinstance(obj, (list, tuple)):
obj = sorted(get_stable_hash(o) for o in obj)
return md5(text_type(obj).encode()).hexdigest()
return md5(str(obj).encode()).hexdigest()
class Stylesheet(text_type):
class Stylesheet(str):
"""A metadata of stylesheet.
To keep compatibility with old themes, an instance of stylesheet behaves as
@@ -101,7 +100,7 @@ class Stylesheet(text_type):
def __new__(cls, filename, *args, **attributes):
# type: (str, str, str) -> None
self = text_type.__new__(cls, filename) # type: ignore
self = str.__new__(cls, filename) # type: ignore
self.filename = filename
self.attributes = attributes
self.attributes.setdefault('rel', 'stylesheet')
@@ -146,7 +145,7 @@ class JSContainer(list):
return ret
class JavaScript(text_type):
class JavaScript(str):
"""A metadata of javascript file.
To keep compatibility with old themes, an instance of javascript behaves as
@@ -158,7 +157,7 @@ class JavaScript(text_type):
def __new__(cls, filename, **attributes):
# type: (str, **str) -> None
self = text_type.__new__(cls, filename) # type: ignore
self = str.__new__(cls, filename) # type: ignore
self.filename = filename
self.attributes = attributes
self.attributes.setdefault('type', 'text/javascript')
@@ -1633,7 +1632,7 @@ def setup(app):
app.add_config_value('html_sidebars', {}, 'html')
app.add_config_value('html_additional_pages', {}, 'html')
app.add_config_value('html_domain_indices', True, 'html', [list])
app.add_config_value('html_add_permalinks', '\u00B6', 'html')
app.add_config_value('html_add_permalinks', '', 'html')
app.add_config_value('html_use_index', True, 'html')
app.add_config_value('html_split_index', False, 'html')
app.add_config_value('html_copy_source', True, 'html')

View File

@@ -25,7 +25,7 @@ from sphinx.util.osutil import make_filename_from_project
if False:
# For type annotation
from typing import Any, Dict, IO, List, Tuple # NOQA
from typing import Any, Dict, IO, List, Match, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
@@ -169,6 +169,20 @@ chm_locales = {
}
def chm_htmlescape(s, quote=True):
# type: (str, bool) -> str
"""
chm_htmlescape() is a wrapper of html.escape().
.hhc/.hhk files don't recognize hex escaping, we need convert
hex escaping to decimal escaping. for example: ``&#x27;`` -> ``&#39;``
html.escape() may generates a hex escaping ``&#x27;`` for single
quote ``'``, this wrapper fixes this.
"""
s = html.escape(s, quote)
s = s.replace('&#x27;', '&#39;') # re-escape as decimal
return s
class HTMLHelpBuilder(StandaloneHTMLBuilder):
"""
Builder that also outputs Windows HTML help project, contents and
@@ -278,7 +292,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
write_toc(subnode, ullevel)
elif isinstance(node, nodes.reference):
link = node['refuri']
title = html.escape(node.astext()).replace('"', '&quot;')
title = chm_htmlescape(node.astext(), True)
f.write(object_sitemap % (title, link))
elif isinstance(node, nodes.bullet_list):
if ullevel != 0:
@@ -305,10 +319,9 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
# type: (str, List[Tuple[str, str]], List[Tuple[str, List[Tuple[str, str]]]]) -> None # NOQA
def write_param(name, value):
# type: (str, str) -> None
item = ' <param name="%s" value="%s">\n' % \
(name, value)
item = ' <param name="%s" value="%s">\n' % (name, value)
f.write(item)
title = html.escape(title)
title = chm_htmlescape(title, True)
f.write('<LI> <OBJECT type="text/sitemap">\n')
write_param('Keyword', title)
if len(refs) == 0:

View File

@@ -12,7 +12,6 @@ import os
from os import path
from docutils.frontend import OptionParser
from six import text_type
from sphinx import package_dir, addnodes, highlighting
from sphinx.builders import Builder
@@ -24,7 +23,7 @@ from sphinx.builders.latex.transforms import (
from sphinx.config import ENUM
from sphinx.environment import NoUri
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import SphinxError, ConfigError
from sphinx.errors import SphinxError
from sphinx.locale import _, __
from sphinx.transforms import SphinxTransformer
from sphinx.util import texescape, logging, status_iterator
@@ -413,23 +412,6 @@ class LaTeXBuilder(Builder):
def validate_config_values(app, config):
# type: (Sphinx, Config) -> None
for document in config.latex_documents:
try:
text_type(document[2])
except UnicodeDecodeError:
raise ConfigError(
__('Invalid latex_documents.title found (might contain non-ASCII chars. '
'Please use u"..." notation instead): %r') % (document,)
)
try:
text_type(document[3])
except UnicodeDecodeError:
raise ConfigError(
__('Invalid latex_documents.author found (might contain non-ASCII chars. '
'Please use u"..." notation instead): %r') % (document,)
)
for key in list(config.latex_elements):
if key not in DEFAULT_SETTINGS:
msg = __("Unknown configure key: latex_elements[%r]. ignored.")

View File

@@ -16,7 +16,6 @@ import sys
import traceback
from docutils.utils import SystemMessage
from six import text_type
import sphinx.locale
from sphinx import __display_version__, package_dir
@@ -53,17 +52,17 @@ def handle_exception(app, args, exception, stderr=sys.stderr):
print(terminal_safe(exception.args[0]), file=stderr)
elif isinstance(exception, SphinxError):
print(red('%s:' % exception.category), file=stderr)
print(terminal_safe(text_type(exception)), file=stderr)
print(terminal_safe(str(exception)), file=stderr)
elif isinstance(exception, UnicodeError):
print(red(__('Encoding error:')), file=stderr)
print(terminal_safe(text_type(exception)), file=stderr)
print(terminal_safe(str(exception)), file=stderr)
tbpath = save_traceback(app)
print(red(__('The full traceback has been saved in %s, if you want '
'to report the issue to the developers.') % tbpath),
file=stderr)
elif isinstance(exception, RuntimeError) and 'recursion depth' in str(exception):
print(red(__('Recursion error:')), file=stderr)
print(terminal_safe(text_type(exception)), file=stderr)
print(terminal_safe(str(exception)), file=stderr)
print(file=stderr)
print(__('This can happen with very large or deeply nested source '
'files. You can carefully increase the default Python '

View File

@@ -32,7 +32,6 @@ except ImportError:
USE_LIBEDIT = False
from docutils.utils import column_width
from six import text_type
import sphinx.locale
from sphinx import __display_version__, package_dir
@@ -158,7 +157,7 @@ def term_decode(text):
warnings.warn('term_decode() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
if isinstance(text, text_type):
if isinstance(text, str):
return text
# Use the known encoding, if possible
@@ -391,10 +390,9 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
d['project_underline'] = column_width(d['project']) * '='
d.setdefault('extensions', [])
d['copyright'] = time.strftime('%Y') + ', ' + d['author']
d['author_texescaped'] = text_type(d['author']).\
translate(texescape.tex_escape_map)
d['author_texescaped'] = d['author'].translate(texescape.tex_escape_map)
d['project_doc'] = d['project'] + ' Documentation'
d['project_doc_texescaped'] = text_type(d['project'] + ' Documentation').\
d['project_doc_texescaped'] = (d['project'] + ' Documentation').\
translate(texescape.tex_escape_map)
# escape backslashes and single quotes in strings that are put into

View File

@@ -16,8 +16,6 @@ from collections import OrderedDict
from os import path, getenv
from typing import Any, NamedTuple, Union
from six import text_type
from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning
from sphinx.errors import ConfigError, ExtensionError
from sphinx.locale import _, __
@@ -41,7 +39,7 @@ copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])')
ConfigValue = NamedTuple('ConfigValue', [('name', str),
('value', Any),
('rebuild', Union[bool, text_type])])
('rebuild', Union[bool, str])])
def is_serializable(obj):
@@ -78,7 +76,7 @@ class ENUM:
# RemovedInSphinx40Warning
string_classes = [text_type] # type: List
string_classes = [str] # type: List
class Config:

View File

@@ -34,6 +34,12 @@ versionlabels = {
'deprecated': _('Deprecated since version %s'),
}
versionlabel_classes = {
'versionadded': 'added',
'versionchanged': 'changed',
'deprecated': 'deprecated',
}
locale.versionlabels = DeprecatedDict(
versionlabels,
'sphinx.locale.versionlabels is deprecated. '
@@ -78,6 +84,7 @@ class VersionChange(SphinxDirective):
messages = []
if self.content:
self.state.nested_parse(self.content, self.content_offset, node)
classes = ['versionmodified', versionlabel_classes[self.name]]
if len(node):
if isinstance(node[0], nodes.paragraph) and node[0].rawsource:
content = nodes.inline(node[0].rawsource, translatable=True)
@@ -87,11 +94,11 @@ class VersionChange(SphinxDirective):
node[0].replace_self(nodes.paragraph('', '', content, translatable=False))
para = cast(nodes.paragraph, node[0])
para.insert(0, nodes.inline('', '%s: ' % text, classes=['versionmodified']))
para.insert(0, nodes.inline('', '%s: ' % text, classes=classes))
else:
para = nodes.paragraph('', '',
nodes.inline('', '%s.' % text,
classes=['versionmodified']),
classes=classes),
translatable=False)
node.append(para)

View File

@@ -14,7 +14,6 @@ from copy import deepcopy
from docutils import nodes, utils
from docutils.parsers.rst import directives
from six import text_type
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx40Warning
@@ -635,7 +634,7 @@ class ASTBase:
def __str__(self):
# type: () -> str
return self._stringify(lambda ast: text_type(ast))
return self._stringify(lambda ast: str(ast))
def get_display_string(self):
# type: () -> str
@@ -666,7 +665,7 @@ class ASTCPPAttribute(ASTBase):
def describe_signature(self, signode):
# type: (addnodes.desc_signature) -> None
txt = text_type(self)
txt = str(self)
signode.append(nodes.Text(txt, txt))
@@ -705,7 +704,7 @@ class ASTGnuAttributeList(ASTBase):
def describe_signature(self, signode):
# type: (addnodes.desc_signature) -> None
txt = text_type(self)
txt = str(self)
signode.append(nodes.Text(txt, txt))
@@ -739,7 +738,7 @@ class ASTParenAttribute(ASTBase):
def describe_signature(self, signode):
# type: (addnodes.desc_signature) -> None
txt = text_type(self)
txt = str(self)
signode.append(nodes.Text(txt, txt))
@@ -779,7 +778,7 @@ class ASTBooleanLiteral(ASTBase):
return 'L0E'
def describe_signature(self, signode, mode, env, symbol):
signode.append(nodes.Text(text_type(self)))
signode.append(nodes.Text(str(self)))
class ASTNumberLiteral(ASTBase):
@@ -796,7 +795,7 @@ class ASTNumberLiteral(ASTBase):
return "L%sE" % self.data
def describe_signature(self, signode, mode, env, symbol):
txt = text_type(self)
txt = str(self)
signode.append(nodes.Text(txt, txt))
@@ -835,7 +834,7 @@ class ASTCharLiteral(ASTBase):
return self.type + str(self.value)
def describe_signature(self, signode, mode, env, symbol):
txt = text_type(self)
txt = str(self)
signode.append(nodes.Text(txt, txt))
@@ -854,7 +853,7 @@ class ASTStringLiteral(ASTBase):
return "LA%d_KcE" % (len(self.data) - 2)
def describe_signature(self, signode, mode, env, symbol):
txt = text_type(self)
txt = str(self)
signode.append(nodes.Text(txt, txt))
@@ -917,7 +916,7 @@ class ASTFoldExpr(ASTBase):
# type: (int) -> str
assert version >= 3
if version == 3:
return text_type(self)
return str(self)
# TODO: find the right mangling scheme
assert False
@@ -1473,7 +1472,7 @@ class ASTFallbackExpr(ASTBase):
def get_id(self, version):
# type: (int) -> str
return text_type(self.expr)
return str(self.expr)
def describe_signature(self, signode, mode, env, symbol):
signode += nodes.Text(self.expr)
@@ -1511,7 +1510,7 @@ class ASTIdentifier(ASTBase):
if self.is_anon():
return 'Ut%d_%s' % (len(self.identifier) - 1, self.identifier[1:])
else:
return text_type(len(self.identifier)) + self.identifier
return str(len(self.identifier)) + self.identifier
# and this is where we finally make a difference between __str__ and the display string
@@ -1994,7 +1993,7 @@ class ASTOperator(ASTBase):
def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol):
# type: (addnodes.desc_signature, str, Any, str, str, Symbol) -> None
_verify_description_mode(mode)
identifier = text_type(self)
identifier = str(self)
if mode == 'lastIsName':
signode += addnodes.desc_name(identifier, identifier)
else:
@@ -2043,7 +2042,7 @@ class ASTOperatorType(ASTOperator):
def get_name_no_template(self):
# type: () -> str
return text_type(self)
return str(self)
class ASTOperatorLiteral(ASTOperator):
@@ -2078,9 +2077,9 @@ class ASTTemplateArgConstant(ASTBase):
def get_id(self, version):
# type: (int) -> str
if version == 1:
return text_type(self).replace(' ', '-')
return str(self).replace(' ', '-')
if version == 2:
return 'X' + text_type(self) + 'E'
return 'X' + str(self) + 'E'
return 'X' + self.value.get_id(version) + 'E'
def describe_signature(self, signode, mode, env, symbol):
@@ -2155,7 +2154,7 @@ class ASTNestedNameElement(ASTBase):
def describe_signature(self, signode, mode, env, prefix, symbol):
# type: (addnodes.desc_signature, str, BuildEnvironment, str, Symbol) -> None
tArgs = text_type(self.templateArgs) if self.templateArgs is not None else ''
tArgs = str(self.templateArgs) if self.templateArgs is not None else ''
self.identOrOp.describe_signature(signode, mode, env, prefix, tArgs, symbol)
if self.templateArgs is not None:
self.templateArgs.describe_signature(signode, mode, env, symbol)
@@ -2188,7 +2187,7 @@ class ASTNestedName(ASTBase):
def get_id(self, version, modifiers=''):
# type: (int, str) -> str
if version == 1:
tt = text_type(self)
tt = str(self)
if tt in _id_shorthands_v1:
return _id_shorthands_v1[tt]
else:
@@ -2223,9 +2222,9 @@ class ASTNestedName(ASTBase):
_verify_description_mode(mode)
# just print the name part, with template args, not template params
if mode == 'noneIsName':
signode += nodes.Text(text_type(self))
signode += nodes.Text(str(self))
elif mode == 'param':
name = text_type(self)
name = str(self)
signode += nodes.emphasis(name, name)
elif mode == 'markType' or mode == 'lastIsName':
# Each element should be a pending xref targeting the complete
@@ -2258,10 +2257,10 @@ class ASTNestedName(ASTBase):
if template:
dest += nodes.Text("template ")
first = False
txt_nne = text_type(nne)
txt_nne = str(nne)
if txt_nne != '':
if nne.templateArgs and iTemplateParams < len(templateParams):
templateParamsPrefix += text_type(templateParams[iTemplateParams])
templateParamsPrefix += str(templateParams[iTemplateParams])
iTemplateParams += 1
nne.describe_signature(dest, 'markType',
env, templateParamsPrefix + prefix, symbol)
@@ -2306,7 +2305,7 @@ class ASTTrailingTypeSpecFundamental(ASTBase):
def describe_signature(self, signode, mode, env, symbol):
# type: (addnodes.desc_signature, str, BuildEnvironment, Symbol) -> None
signode += nodes.Text(text_type(self.name))
signode += nodes.Text(str(self.name))
class ASTTrailingTypeSpecName(ASTBase):
@@ -2354,7 +2353,7 @@ class ASTTrailingTypeSpecDecltypeAuto(ASTBase):
def describe_signature(self, signode, mode, env, symbol):
# type: (addnodes.desc_signature, str, BuildEnvironment, Symbol) -> None
signode.append(nodes.Text(text_type(self)))
signode.append(nodes.Text(str(self)))
class ASTTrailingTypeSpecDecltype(ASTBase):
@@ -2467,7 +2466,7 @@ class ASTParametersQualifiers(ASTBase):
if not first:
res.append(', ')
first = False
res.append(text_type(a))
res.append(str(a))
res.append(')')
if self.volatile:
res.append(' volatile')
@@ -2478,7 +2477,7 @@ class ASTParametersQualifiers(ASTBase):
res.append(self.refQual)
if self.exceptionSpec:
res.append(' ')
res.append(text_type(self.exceptionSpec))
res.append(str(self.exceptionSpec))
if self.final:
res.append(' final')
if self.override:
@@ -2515,13 +2514,13 @@ class ASTParametersQualifiers(ASTBase):
if self.refQual:
_add_text(signode, self.refQual)
if self.exceptionSpec:
_add_anno(signode, text_type(self.exceptionSpec))
_add_anno(signode, str(self.exceptionSpec))
if self.final:
_add_anno(signode, 'final')
if self.override:
_add_anno(signode, 'override')
if self.initializer:
_add_text(signode, '= ' + text_type(self.initializer))
_add_text(signode, '= ' + str(self.initializer))
class ASTDeclSpecsSimple(ASTBase):
@@ -2653,7 +2652,7 @@ class ASTDeclSpecs(ASTBase):
if len(res) > 0:
res.append(" ")
res.append(transform(self.trailingTypeSpec))
r = text_type(self.rightSpecs)
r = str(self.rightSpecs)
if len(r) > 0:
if len(res) > 0:
res.append(" ")
@@ -2704,7 +2703,7 @@ class ASTArray(ASTBase):
return 'A'
if version == 2:
if self.size:
return 'A' + text_type(self.size) + '_'
return 'A' + str(self.size) + '_'
else:
return 'A_'
if self.size:
@@ -3321,7 +3320,7 @@ class ASTType(ASTBase):
_verify_description_mode(mode)
self.declSpecs.describe_signature(signode, 'markType', env, symbol)
if (self.decl.require_space_after_declSpecs() and
len(text_type(self.declSpecs)) > 0):
len(str(self.declSpecs)) > 0):
signode += nodes.Text(' ')
# for parameters that don't really declare new names we get 'markType',
# this should not be propagated, but be 'noneIsName'.
@@ -3929,8 +3928,8 @@ class Symbol:
param = templateParams.params[i]
arg = templateArgs.args[i]
# TODO: doing this by string manipulation is probably not the most efficient
paramName = text_type(param.name)
argTxt = text_type(arg)
paramName = str(param.name)
argTxt = str(arg)
isArgPackExpansion = argTxt.endswith('...')
if param.isPack != isArgPackExpansion:
return True
@@ -3958,13 +3957,13 @@ class Symbol:
return False
if templateParams:
# TODO: do better comparison
if text_type(s.templateParams) != text_type(templateParams):
if str(s.templateParams) != str(templateParams):
return False
if (s.templateArgs is None) != (templateArgs is None):
return False
if s.templateArgs:
# TODO: do better comparison
if text_type(s.templateArgs) != text_type(templateArgs):
if str(s.templateArgs) != str(templateArgs):
return False
return True
if matchSelf and matches(self):
@@ -4253,7 +4252,7 @@ class Symbol:
if not ourChild.declaration:
ourChild._fill_empty(otherChild.declaration, otherChild.docname)
elif ourChild.docname != otherChild.docname:
name = text_type(ourChild.declaration)
name = str(ourChild.declaration)
msg = __("Duplicate declaration, also defined in '%s'.\n"
"Declaration is '%s'.")
msg = msg % (ourChild.docname, name)
@@ -4401,20 +4400,20 @@ class Symbol:
res.append('::')
else:
if self.templateParams:
res.append(text_type(self.templateParams))
res.append(str(self.templateParams))
res.append('\n')
res.append('\t' * indent)
if self.identOrOp:
res.append(text_type(self.identOrOp))
res.append(str(self.identOrOp))
else:
res.append(text_type(self.declaration))
res.append(str(self.declaration))
if self.templateArgs:
res.append(text_type(self.templateArgs))
res.append(str(self.templateArgs))
if self.declaration:
res.append(": ")
if self.isRedeclaration:
res.append('!!duplicate!! ')
res.append(text_type(self.declaration))
res.append(str(self.declaration))
if self.docname:
res.append('\t(')
res.append(self.docname)
@@ -6151,7 +6150,7 @@ class DefinitionParser:
msg += " Declaration:\n\t"
if templatePrefix:
msg += "%s\n\t" % templatePrefix
msg += text_type(nestedName)
msg += str(nestedName)
self.warn(msg)
newTemplates = []
@@ -6445,7 +6444,7 @@ class CPPObject(ObjectDescription):
parentDecl = parentSymbol.declaration
if parentDecl is not None and parentDecl.objectType == 'function':
self.warn("C++ declarations inside functions are not supported." +
" Parent function is " + text_type(parentSymbol.get_full_nested_name()))
" Parent function is " + str(parentSymbol.get_full_nested_name()))
name = _make_phony_error_name()
symbol = parentSymbol.add_name(name)
env.temp_data['cpp:last_symbol'] = symbol
@@ -6928,7 +6927,7 @@ class CPPDomain(Domain):
templateShorthand=True,
matchSelf=True, recurseInAnon=True)
if s is None or s.declaration is None:
txtName = text_type(name)
txtName = str(name)
if txtName.startswith('std::') or txtName == 'std':
raise NoUri()
return None, None
@@ -7031,7 +7030,7 @@ class CPPDomain(Domain):
continue
assert symbol.docname
fullNestedName = symbol.get_full_nested_name()
name = text_type(fullNestedName).lstrip(':')
name = str(fullNestedName).lstrip(':')
dispname = fullNestedName.get_display_string().lstrip(':')
objectType = symbol.declaration.objectType
docname = symbol.docname
@@ -7050,7 +7049,7 @@ class CPPDomain(Domain):
rootSymbol = self.data['root_symbol']
parentSymbol = rootSymbol.direct_lookup(parentKey)
parentName = parentSymbol.get_full_nested_name()
return '::'.join([text_type(parentName), target])
return '::'.join([str(parentName), target])
def setup(app):

View File

@@ -12,8 +12,6 @@ import re
import unicodedata
from itertools import groupby
from six import text_type
from sphinx.locale import _, __
from sphinx.util import split_into, logging
@@ -44,7 +42,7 @@ class IndexEntries:
# 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)
word = str(word)
entry = dic.get(word)
if not entry:
dic[word] = entry = [[], {}, key]

View File

@@ -8,8 +8,6 @@
:license: BSD, see LICENSE for details.
"""
from six import text_type
from sphinx import addnodes
from sphinx.environment.collectors import EnvironmentCollector
from sphinx.util import split_index_msg, logging
@@ -45,7 +43,7 @@ class IndexEntriesCollector(EnvironmentCollector):
for entry in node['entries']:
split_index_msg(entry[0], entry[1])
except ValueError as exc:
logger.warning(text_type(exc), location=node)
logger.warning(str(exc), location=node)
node.parent.remove(node)
else:
for entry in node['entries']:

View File

@@ -336,7 +336,7 @@ Note: By default this script will not overwrite already created files."""))
dest='includeprivate',
help=__('include "_private" modules'))
parser.add_argument('--tocfile', action='store', dest='tocfile', default='modules',
help=__("don't create a table of contents file"))
help=__("filename of table of contents (default: modules)"))
parser.add_argument('-T', '--no-toc', action='store_false', dest='tocfile',
help=__("don't create a table of contents file"))
parser.add_argument('-E', '--no-headings', action='store_true',

View File

@@ -12,12 +12,10 @@
import inspect
import re
import sys
import warnings
from typing import Any
from docutils.statemachine import StringList
from six import text_type
import sphinx
from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning
@@ -461,13 +459,7 @@ class Documenter:
def get_sourcename(self):
# type: () -> str
if self.analyzer:
# prevent encoding errors when the file name is non-ASCII
if not isinstance(self.analyzer.srcname, text_type):
filename = text_type(self.analyzer.srcname,
sys.getfilesystemencoding(), 'replace')
else:
filename = self.analyzer.srcname
return '%s:docstring of %s' % (filename, self.fullname)
return '%s:docstring of %s' % (self.analyzer.srcname, self.fullname)
return 'docstring of %s' % self.fullname
def add_content(self, more_content, no_docstring=False):

View File

@@ -65,7 +65,6 @@ from docutils import nodes
from docutils.parsers.rst import directives
from docutils.parsers.rst.states import RSTStateMachine, state_classes
from docutils.statemachine import StringList
from six import text_type
import sphinx
from sphinx import addnodes
@@ -160,8 +159,7 @@ def autosummary_table_visit_html(self, node):
par = cast(nodes.paragraph, col1_entry[0])
for j, subnode in enumerate(list(par)):
if isinstance(subnode, nodes.Text):
new_text = text_type(subnode.astext())
new_text = new_text.replace(" ", "\u00a0")
new_text = subnode.astext().replace(" ", "\u00a0")
par[j] = nodes.Text(new_text)
except IndexError:
pass

View File

@@ -17,7 +17,6 @@ from os import path
from subprocess import Popen, PIPE
from docutils import nodes
from six import text_type
import sphinx
from sphinx.errors import SphinxError
@@ -290,7 +289,7 @@ def html_visit_math(self, node):
try:
fname, depth = render_math(self, '$' + node.astext() + '$')
except MathExtError as exc:
msg = text_type(exc)
msg = str(exc)
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node.astext())
sm.walkabout(self)
@@ -317,7 +316,7 @@ def html_visit_displaymath(self, node):
try:
fname, depth = render_math(self, latex)
except MathExtError as exc:
msg = text_type(exc)
msg = str(exc)
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node.astext())
sm.walkabout(self)

View File

@@ -173,7 +173,10 @@ def process_todo_nodes(app, doctree, fromdocname):
try:
newnode['refuri'] = app.builder.get_relative_uri(
fromdocname, todo_info['docname'])
newnode['refuri'] += '#' + todo_info['target']['refid']
if 'refid' in todo_info['target']:
newnode['refuri'] += '#' + todo_info['target']['refid']
else:
newnode['refuri'] += '#' + todo_info['target']['ids'][0]
except NoUri:
# ignore if no URI can be determined, e.g. for LaTeX output
pass

View File

@@ -20,7 +20,6 @@ from pygments.lexers import PythonLexer, Python3Lexer, PythonConsoleLexer, \
CLexer, TextLexer, RstLexer
from pygments.styles import get_style_by_name
from pygments.util import ClassNotFound
from six import text_type
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.ext import doctest
@@ -113,7 +112,7 @@ class PygmentsBridge:
def highlight_block(self, source, lang, opts=None, location=None, force=False, **kwargs):
# type: (str, str, Any, Any, bool, Any) -> str
if not isinstance(source, text_type):
if not isinstance(source, str):
source = source.decode()
# find out which lexer to use

View File

@@ -14,8 +14,6 @@ import warnings
from collections import UserString, defaultdict
from gettext import NullTranslations
from six import text_type
from sphinx.deprecation import RemovedInSphinx30Warning
if False:
@@ -41,7 +39,7 @@ class _TranslationProxy(UserString):
# type: (Callable, str) -> object
if not args:
# not called with "function" and "arguments", but a plain string
return text_type(func)
return str(func)
return object.__new__(cls)
def __getnewargs__(self):
@@ -73,7 +71,7 @@ class _TranslationProxy(UserString):
def __dir__(self):
# type: () -> List[str]
return dir(text_type)
return dir(str)
def __str__(self):
# type: () -> str
@@ -124,7 +122,7 @@ class _TranslationProxy(UserString):
def __repr__(self):
# type: () -> str
try:
return 'i' + repr(text_type(self.data))
return 'i' + repr(str(self.data))
except Exception:
return '<%s broken>' % self.__class__.__name__

View File

@@ -16,8 +16,6 @@ import tokenize
from token import NAME, NEWLINE, INDENT, DEDENT, NUMBER, OP, STRING
from tokenize import COMMENT, NL
from six import text_type
if False:
# For type annotation
from typing import Any, Dict, IO, List, Tuple # NOQA
@@ -349,7 +347,7 @@ class VariableCommentPicker(ast.NodeVisitor):
targets = get_assign_targets(self.previous)
varnames = get_lvar_names(targets[0], self.get_self())
for varname in varnames:
if isinstance(node.value.s, text_type):
if isinstance(node.value.s, str):
docstring = node.value.s
else:
docstring = node.value.s.decode(self.encoding or 'utf-8')

View File

@@ -13,8 +13,6 @@ import re
import warnings
from os import path
from six import text_type
from docutils import nodes
from sphinx import addnodes
@@ -351,9 +349,9 @@ class IndexBuilder:
otypes[domainname, type] = typeindex
otype = domain.object_types.get(type)
if otype:
# use unicode() to fire translation proxies
# use str() to fire translation proxies
onames[typeindex] = (domainname, type,
text_type(domain.get_type_name(otype)))
str(domain.get_type_name(otype)))
else:
onames[typeindex] = (domainname, type, type)
if anchor == fullname:

View File

@@ -1,7 +1,7 @@
# Configuration file for the Sphinx documentation builder.
#
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
@@ -167,3 +167,4 @@ intersphinx_mapping = {'https://docs.python.org/': None}
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
{%- endif %}

View File

@@ -9,8 +9,6 @@ import os
import shutil
import sys
from six import text_type
if False:
# For type annotation
import builtins # NOQA
@@ -20,7 +18,7 @@ if False:
FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding()
class path(text_type):
class path(str):
"""
Represents a path which behaves like a string.
"""
@@ -222,4 +220,4 @@ class path(text_type):
def __repr__(self):
# type: () -> str
return '%s(%s)' % (self.__class__.__name__, text_type.__repr__(self))
return '%s(%s)' % (self.__class__.__name__, super().__repr__())

View File

@@ -3,7 +3,7 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesClass{sphinxhowto}[2018/09/18 v1.8.1 Document class (Sphinx HOWTO)]
\ProvidesClass{sphinxhowto}[2018/12/23 v2.0 Document class (Sphinx howto)]
% 'oneside' option overriding the 'twoside' default
\newif\if@oneside
@@ -30,7 +30,7 @@
% Change the title page to look a bit better, and fit in with the fncychap
% ``Bjarne'' style a bit better.
%
\renewcommand{\maketitle}{%
\newcommand{\sphinxmaketitle}{%
\noindent\rule{\textwidth}{1pt}\par
\begingroup % for PDF information dictionary
\def\endgraf{ }\def\and{\& }%
@@ -57,15 +57,16 @@
%\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
}
\newcommand{\sphinxtableofcontents}{
\newcommand{\sphinxtableofcontents}{%
\begingroup
\parskip = 0mm
\parskip \z@skip
\sphinxtableofcontentshook
\tableofcontents
\endgroup
\rule{\textwidth}{1pt}
\vspace{12pt}
\noindent\rule{\textwidth}{1pt}\par
\vspace{12pt}%
}
\newcommand\sphinxtableofcontentshook{}
\pagenumbering{arabic}
% Fix the bibliography environment to add an entry to the Table of

View File

@@ -3,7 +3,7 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesClass{sphinxmanual}[2018/09/18 v1.8.1 Document class (Sphinx manual)]
\ProvidesClass{sphinxmanual}[2018/12/23 v2.0 Document class (Sphinx manual)]
% chapters starting at odd pages (overridden by 'openany' document option)
\PassOptionsToClass{openright}{\sphinxdocclass}
@@ -33,9 +33,9 @@
% Change the title page to look a bit better, and fit in with the fncychap
% ``Bjarne'' style a bit better.
%
\renewcommand{\maketitle}{%
\let\spx@tempa\relax
\ifHy@pageanchor\def\spx@tempa{\Hy@pageanchortrue}\fi
\newcommand{\sphinxmaketitle}{%
\let\sphinxrestorepageanchorsetting\relax
\ifHy@pageanchor\def\sphinxrestorepageanchorsetting{\Hy@pageanchortrue}\fi
\hypersetup{pageanchor=false}% avoid duplicate destination warnings
\begin{titlepage}%
\let\footnotesize\small
@@ -69,14 +69,17 @@
\setcounter{footnote}{0}%
\let\thanks\relax\let\maketitle\relax
%\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
\clearpage
\ifdefined\sphinxbackoftitlepage\sphinxbackoftitlepage\fi
\if@openright\cleardoublepage\else\clearpage\fi
\spx@tempa
\sphinxrestorepageanchorsetting
}
\newcommand{\sphinxtableofcontents}{%
\pagenumbering{roman}%
\begingroup
\parskip \z@skip
\sphinxtableofcontentshook
\tableofcontents
\endgroup
% before resetting page counter, let's do the right thing.
@@ -87,8 +90,10 @@
% This is needed to get the width of the section # area wide enough in the
% library reference. Doing it here keeps it the same for all the manuals.
%
\renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.6em}}
\renewcommand*\l@subsection{\@dottedtocline{2}{4.1em}{3.5em}}
\newcommand{\sphinxtableofcontentshook}{%
\renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.6em}}%
\renewcommand*\l@subsection{\@dottedtocline{2}{4.1em}{3.5em}}%
}
% Fix the bibliography environment to add an entry to the Table of
% Contents.

View File

@@ -13,7 +13,6 @@ from typing import NamedTuple
from docutils import nodes
from pygments.lexers import PythonConsoleLexer, guess_lexer
from six import text_type
from sphinx import addnodes
from sphinx.ext import doctest
@@ -25,7 +24,7 @@ if False:
from sphinx.application import Sphinx # NOQA
HighlightSetting = NamedTuple('HighlightSetting', [('language', text_type),
HighlightSetting = NamedTuple('HighlightSetting', [('language', str),
('lineno_threshold', int)])

View File

@@ -13,7 +13,6 @@ from hashlib import sha1
from math import ceil
from docutils import nodes
from six import text_type
from sphinx.locale import __
from sphinx.transforms import SphinxTransform
@@ -118,8 +117,7 @@ class ImageDownloader(BaseImageConverter):
node['uri'] = path
self.app.env.images.add_file(self.env.docname, path)
except Exception as exc:
logger.warning(__('Could not fetch remote image: %s [%s]') %
(node['uri'], text_type(exc)))
logger.warning(__('Could not fetch remote image: %s [%s]') % (node['uri'], exc))
class DataURIExtractor(BaseImageConverter):

View File

@@ -26,7 +26,6 @@ from time import mktime, strptime
from urllib.parse import urlsplit, urlunsplit, quote_plus, parse_qsl, urlencode
from docutils.utils import relative_path
from six import text_type
from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning
from sphinx.errors import PycodeError, SphinxParallelError, ExtensionError
@@ -70,9 +69,7 @@ def path_stabilize(filepath):
# type: (str) -> str
"normalize path separater and unicode string"
newpath = filepath.replace(os.path.sep, SEP)
if isinstance(newpath, text_type):
newpath = unicodedata.normalize('NFC', newpath)
return newpath
return unicodedata.normalize('NFC', newpath)
def get_matching_files(dirname, exclude_matchers=()):
@@ -637,9 +634,9 @@ def display_chunk(chunk):
# type: (Any) -> str
if isinstance(chunk, (list, tuple)):
if len(chunk) == 1:
return text_type(chunk[0])
return str(chunk[0])
return '%s .. %s' % (chunk[0], chunk[-1])
return text_type(chunk)
return str(chunk)
def old_status_iterator(iterable, summary, color="darkgreen", stringify_func=display_chunk):
@@ -696,15 +693,12 @@ def rfc1123_to_epoch(rfc1123):
def xmlname_checker():
# type: () -> Pattern
# https://www.w3.org/TR/REC-xml/#NT-Name
# Only Python 3.3 or newer support character code in regular expression
name_start_chars = [
':', ['A', 'Z'], '_', ['a', 'z'], ['\u00C0', '\u00D6'],
['\u00D8', '\u00F6'], ['\u00F8', '\u02FF'], ['\u0370', '\u037D'],
['\u037F', '\u1FFF'], ['\u200C', '\u200D'], ['\u2070', '\u218F'],
['\u2C00', '\u2FEF'], ['\u3001', '\uD7FF'], ['\uF900', '\uFDCF'],
['\uFDF0', '\uFFFD']]
name_start_chars.append(['\U00010000', '\U000EFFFF'])
['\uFDF0', '\uFFFD'], ['\U00010000', '\U000EFFFF']]
name_chars = [
"\\-", "\\.", ['0', '9'], '\u00B7', ['\u0300', '\u036F'],

View File

@@ -17,7 +17,6 @@ from os import path
from typing import NamedTuple
import imagesize
from six import text_type
from sphinx.deprecation import RemovedInSphinx30Warning
@@ -42,8 +41,8 @@ mime_suffixes = OrderedDict([
('.svgz', 'image/svg+xml'),
])
DataURI = NamedTuple('DataURI', [('mimetype', text_type),
('charset', text_type),
DataURI = NamedTuple('DataURI', [('mimetype', str),
('charset', str),
('data', bytes)])

View File

@@ -103,16 +103,12 @@ def getargspec(func):
def isenumclass(x):
# type: (Type) -> bool
"""Check if the object is subclass of enum."""
if enum is None:
return False
return inspect.isclass(x) and issubclass(x, enum.Enum)
def isenumattribute(x):
# type: (Any) -> bool
"""Check if the object is attribute of enum."""
if enum is None:
return False
return isinstance(x, enum.Enum)

View File

@@ -11,8 +11,6 @@
import json
from collections import UserString
from six import text_type
if False:
# For type annotation
from typing import Any, IO # NOQA
@@ -23,7 +21,7 @@ class SphinxJSONEncoder(json.JSONEncoder):
def default(self, obj):
# type: (Any) -> str
if isinstance(obj, UserString):
return text_type(obj)
return str(obj)
return super().default(obj)

View File

@@ -12,7 +12,6 @@ import re
from typing import Any, cast
from docutils import nodes
from six import text_type
from sphinx import addnodes
from sphinx.locale import __
@@ -115,7 +114,7 @@ def repr_domxml(node, length=80):
try:
text = node.asdom().toxml()
except Exception:
text = text_type(node)
text = str(node)
if length and len(text) > length:
text = text[:length] + '...'
return text
@@ -398,7 +397,7 @@ def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc, traversed
tree = cast(nodes.document, tree.deepcopy())
for toctreenode in tree.traverse(addnodes.toctree):
newnodes = []
includefiles = map(text_type, toctreenode['includefiles'])
includefiles = map(str, toctreenode['includefiles'])
for includefile in includefiles:
if includefile not in traversed:
try:

View File

@@ -14,8 +14,6 @@ from html import escape as htmlescape # NOQA
from io import TextIOWrapper # NOQA
from textwrap import indent # NOQA
from six import text_type
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.locale import __
from sphinx.util import logging
@@ -64,7 +62,7 @@ def convert_with_2to3(filepath):
lineno, offset = err.context[1]
# try to match ParseError details with SyntaxError details
raise SyntaxError(err.msg, (filepath, lineno, offset, err.value))
return text_type(tree)
return str(tree)
class UnicodeMixin:

View File

@@ -12,7 +12,6 @@ from typing import Any, Callable, Dict, List, Tuple, Union
from docutils import nodes
from docutils.parsers.rst.states import Inliner
from six import text_type
# An entry of Directive.option_spec
@@ -22,11 +21,11 @@ DirectiveOption = Callable[[str], Any]
TextlikeNode = Union[nodes.Text, nodes.TextElement]
# common role functions
RoleFunction = Callable[[text_type, text_type, text_type, int, Inliner, Dict, List[text_type]],
RoleFunction = Callable[[str, str, str, int, Inliner, Dict, List[str]],
Tuple[List[nodes.Node], List[nodes.system_message]]]
# title getter functions for enumerable nodes (see sphinx.domains.std)
TitleGetter = Callable[[nodes.Node], text_type]
TitleGetter = Callable[[nodes.Node], str]
# inventory data on memory
Inventory = Dict[str, Dict[str, Tuple[str, str, str, str]]]

View File

@@ -92,7 +92,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
self.permalink_text = self.config.html_add_permalinks
# support backwards-compatible setting to a bool
if not isinstance(self.permalink_text, str):
self.permalink_text = self.permalink_text and '\u00B6' or ''
self.permalink_text = self.permalink_text and '' or ''
self.permalink_text = self.encode(self.permalink_text)
self.secnumber_suffix = self.config.html_secnumber_suffix
self.param_separator = ''

View File

@@ -62,7 +62,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
self.permalink_text = self.config.html_add_permalinks
# support backwards-compatible setting to a bool
if not isinstance(self.permalink_text, str):
self.permalink_text = self.permalink_text and '\u00B6' or ''
self.permalink_text = self.permalink_text and '' or ''
self.permalink_text = self.encode(self.permalink_text)
self.secnumber_suffix = self.config.html_secnumber_suffix
self.param_separator = ''

View File

@@ -20,7 +20,6 @@ from typing import Iterable, cast
from docutils import nodes, writers
from docutils.writers.latex2e import Babel
from six import text_type
from sphinx import addnodes
from sphinx import highlighting
@@ -159,7 +158,7 @@ DEFAULT_SETTINGS = {
'releasename': '',
'makeindex': '\\makeindex',
'shorthandoff': '',
'maketitle': '\\maketitle',
'maketitle': '\\sphinxmaketitle',
'tableofcontents': '\\sphinxtableofcontents',
'atendofbody': '',
'printindex': '\\printindex',
@@ -759,7 +758,7 @@ class LaTeXTranslator(SphinxTranslator):
def idescape(self, id):
# type: (str) -> str
return '\\detokenize{%s}' % text_type(id).translate(tex_replace_map).\
return '\\detokenize{%s}' % str(id).translate(tex_replace_map).\
encode('ascii', 'backslashreplace').decode('ascii').\
replace('\\', '_')
@@ -780,34 +779,34 @@ class LaTeXTranslator(SphinxTranslator):
figure = self.builder.config.numfig_format['figure'].split('%s', 1)
if len(figure) == 1:
ret.append('\\def\\fnum@figure{%s}\n' %
text_type(figure[0]).strip().translate(tex_escape_map))
str(figure[0]).strip().translate(tex_escape_map))
else:
definition = text_type(figure[0]).strip().translate(tex_escape_map)
definition = str(figure[0]).strip().translate(tex_escape_map)
ret.append(self.babel_renewcommand('\\figurename', definition))
if figure[1]:
ret.append('\\makeatletter\n')
ret.append('\\def\\fnum@figure{\\figurename\\thefigure%s}\n' %
text_type(figure[1]).strip().translate(tex_escape_map))
str(figure[1]).strip().translate(tex_escape_map))
ret.append('\\makeatother\n')
table = self.builder.config.numfig_format['table'].split('%s', 1)
if len(table) == 1:
ret.append('\\def\\fnum@table{%s}\n' %
text_type(table[0]).strip().translate(tex_escape_map))
str(table[0]).strip().translate(tex_escape_map))
else:
definition = text_type(table[0]).strip().translate(tex_escape_map)
definition = str(table[0]).strip().translate(tex_escape_map)
ret.append(self.babel_renewcommand('\\tablename', definition))
if table[1]:
ret.append('\\makeatletter\n')
ret.append('\\def\\fnum@table{\\tablename\\thetable%s}\n' %
text_type(table[1]).strip().translate(tex_escape_map))
str(table[1]).strip().translate(tex_escape_map))
ret.append('\\makeatother\n')
codeblock = self.builder.config.numfig_format['code-block'].split('%s', 1)
if len(codeblock) == 1:
pass # FIXME
else:
definition = text_type(codeblock[0]).strip().translate(tex_escape_map)
definition = str(codeblock[0]).strip().translate(tex_escape_map)
ret.append(self.babel_renewcommand('\\literalblockname', definition))
if codeblock[1]:
pass # FIXME
@@ -824,7 +823,7 @@ class LaTeXTranslator(SphinxTranslator):
if i > 0:
ret.append('\\indexspace\n')
ret.append('\\bigletter{%s}\n' %
text_type(letter).translate(tex_escape_map))
str(letter).translate(tex_escape_map))
for entry in entries:
if not entry[3]:
continue
@@ -2003,7 +2002,7 @@ class LaTeXTranslator(SphinxTranslator):
id = node.get('refuri', '')[1:].replace('#', ':')
title = node.get('title', '%s')
title = text_type(title).translate(tex_escape_map).replace('\\%s', '%s')
title = str(title).translate(tex_escape_map).replace('\\%s', '%s')
if '\\{name\\}' in title or '\\{number\\}' in title:
# new style format (cf. "Fig.%{number}")
title = title.replace('\\{name\\}', '{name}').replace('\\{number\\}', '{number}')
@@ -2451,7 +2450,7 @@ class LaTeXTranslator(SphinxTranslator):
def encode(self, text):
# type: (str) -> str
text = text_type(text).translate(tex_escape_map)
text = str(text).translate(tex_escape_map)
if self.literal_whitespace:
# Insert a blank before the newline, to avoid
# ! LaTeX Error: There's no line here to end.

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
project = 'test'
master_doc = 'index'

View File

@@ -0,0 +1,19 @@
Index markup
------------
.. index::
single: entry
pair: entry; pair
double: entry; double
triple: index; entry; triple
keyword: with
see: from; to
seealso: fromalso; toalso
.. index::
!Main, !Other
!single: entry; pair
.. index:: triple-quoted string, Unicode Consortium, raw string
single: """; string literal
single: '''; string literal

View File

@@ -0,0 +1,64 @@
@echo off
setlocal
pushd %~dp0
set this=%~n0
if not defined PYTHON set PYTHON=py
if not defined SPHINXBUILD (
%PYTHON% -c "import sphinx" > nul 2> nul
if errorlevel 1 (
echo Installing sphinx with %PYTHON%
%PYTHON% -m pip install sphinx
if errorlevel 1 exit /B
)
set SPHINXBUILD=%PYTHON% -c "import sphinx.cmd.build, sys; sys.exit(sphinx.cmd.build.main())"
)
rem Search for HHC in likely places
set HTMLHELP=
where hhc /q && set HTMLHELP=hhc && goto :skiphhcsearch
where /R ..\externals hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc"
if not exist "%HTMLHELP%" where /R "%ProgramFiles(x86)%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc"
if not exist "%HTMLHELP%" where /R "%ProgramFiles%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc"
if not exist "%HTMLHELP%" (
echo.
echo.The HTML Help Workshop was not found. Set the HTMLHELP variable
echo.to the path to hhc.exe or download and install it from
echo.http://msdn.microsoft.com/en-us/library/ms669985
exit /B 1
)
echo hhc.exe path: %HTMLHELP%
if "%BUILDDIR%" EQU "" set BUILDDIR=build
%SPHINXBUILD% >nul 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.
popd
exit /B 1
)
set SPHINXOPTS=-D html_theme_options.body_max_width=none %SPHINXOPTS%
cmd /S /C "%SPHINXBUILD% %SPHINXOPTS% -bhtmlhelp -dbuild\doctrees . "%BUILDDIR%\htmlhelp"
"%HTMLHELP%" "%BUILDDIR%\htmlhelp\test.hhp"
rem hhc.exe seems to always exit with code 1, reset to 0 for less than 2
if not errorlevel 2 cmd /C exit /b 0
echo.
if errorlevel 1 (
echo.Build failed (exit code %ERRORLEVEL%^), check for error messages
echo.above. Any output will be found in %BUILDDIR%\%1
) else (
echo.Build succeeded. All output should be in %BUILDDIR%\%1
)
popd

View File

@@ -2,3 +2,9 @@ foo
===
.. todo:: todo in foo
.. py:function:: hello()
:param bug: #5800
.. todo:: todo in param field

View File

@@ -8,8 +8,12 @@
:license: BSD, see LICENSE for details.
"""
import re
import pytest
from sphinx.builders.htmlhelp import chm_htmlescape
from sphinx.builders.htmlhelp import default_htmlhelp_basename
from sphinx.config import Config
@@ -29,3 +33,31 @@ def test_default_htmlhelp_basename():
config = Config({'project': 'Sphinx Documentation'})
config.init_values()
assert default_htmlhelp_basename(config) == 'sphinxdoc'
@pytest.mark.sphinx('htmlhelp', testroot='build-htmlhelp')
def test_chm(app):
app.build()
# check .hhk file
outname = app.builder.config.htmlhelp_basename
hhk_path = str(app.outdir / outname + '.hhk')
with open(hhk_path, 'rb') as f:
data = f.read()
m = re.search(br'&#[xX][0-9a-fA-F]+;', data)
assert m is None, 'Hex escaping exists in .hhk file: ' + str(m.group(0))
def test_chm_htmlescape():
assert chm_htmlescape('Hello world') == 'Hello world'
assert chm_htmlescape(u'Unicode 文字') == u'Unicode 文字'
assert chm_htmlescape('&#x45') == '&amp;#x45'
assert chm_htmlescape('<Hello> "world"') == '&lt;Hello&gt; &quot;world&quot;'
assert chm_htmlescape('<Hello> "world"', True) == '&lt;Hello&gt; &quot;world&quot;'
assert chm_htmlescape('<Hello> "world"', False) == '&lt;Hello&gt; "world"'
assert chm_htmlescape("Hello 'world'") == "Hello &#39;world&#39;"
assert chm_htmlescape("Hello 'world'", True) == "Hello &#39;world&#39;"
assert chm_htmlescape("Hello 'world'", False) == "Hello 'world'"

View File

@@ -12,7 +12,6 @@ import re
import sys
import pytest
from six import text_type
import sphinx.domains.cpp as cppDomain
from sphinx import addnodes
@@ -39,7 +38,7 @@ def check(name, input, idDict, output=None):
if output is None:
output = input
ast = parse(name, input)
res = text_type(ast)
res = str(ast)
if res != output:
print("")
print("Input: ", input)

View File

@@ -11,7 +11,6 @@
import pytest
from docutils import nodes
from mock import Mock
from six import text_type
from sphinx import addnodes
from sphinx.domains.python import py_sig_re, _pseudo_parse_arglist, PythonDomain
@@ -30,22 +29,22 @@ def parse(sig):
def test_function_signatures():
rv = parse('func(a=1) -> int object')
assert text_type(rv) == 'a=1'
assert rv == 'a=1'
rv = parse('func(a=1, [b=None])')
assert text_type(rv) == 'a=1, [b=None]'
assert rv == 'a=1, [b=None]'
rv = parse('func(a=1[, b=None])')
assert text_type(rv) == 'a=1, [b=None]'
assert rv == 'a=1, [b=None]'
rv = parse("compile(source : string, filename, symbol='file')")
assert text_type(rv) == "source : string, filename, symbol='file'"
assert rv == "source : string, filename, symbol='file'"
rv = parse('func(a=[], [b=None])')
assert text_type(rv) == 'a=[], [b=None]'
assert rv == 'a=[], [b=None]'
rv = parse('func(a=[][, b=None])')
assert text_type(rv) == 'a=[], [b=None]'
assert rv == 'a=[], [b=None]'
@pytest.mark.sphinx('dummy', testroot='domain-py')

View File

@@ -40,13 +40,19 @@ def test_todo(app, status, warning):
'<p class="last">todo in foo</p>')
assert re.search(html, content, re.S)
html = ('<p class="first admonition-title">Todo</p>\n'
'<p class="last">todo in param field</p>')
assert re.search(html, content, re.S)
# check emitted warnings
assert 'WARNING: TODO entry found: todo in foo' in warning.getvalue()
assert 'WARNING: TODO entry found: todo in bar' in warning.getvalue()
# check handled event
assert len(todos) == 2
assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar'])
assert len(todos) == 3
assert set(todo[1].astext() for todo in todos) == {'todo in foo',
'todo in bar',
'todo in param field'}
@pytest.mark.sphinx('html', testroot='ext-todo', freshenv=True,
@@ -81,8 +87,10 @@ def test_todo_not_included(app, status, warning):
assert 'WARNING: TODO entry found: todo in bar' in warning.getvalue()
# check handled event
assert len(todos) == 2
assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar'])
assert len(todos) == 3
assert set(todo[1].astext() for todo in todos) == {'todo in foo',
'todo in bar',
'todo in param field'}
@pytest.mark.sphinx('latex', testroot='ext-todo', freshenv=True,
@@ -105,7 +113,7 @@ def test_todo_valid_link(app, status, warning):
link = r'\{\\hyperref\[\\detokenize\{(.*?foo.*?)}]\{\\sphinxcrossref{' \
r'\\sphinxstyleemphasis{original entry}}}}'
m = re.findall(link, content)
assert len(m) == 2
assert len(m) == 4
target = m[0]
# Look for the targets of this link.

View File

@@ -705,20 +705,20 @@ def test_html_versionchanges(app):
return ''
expect1 = (
"""<p><span class="versionmodified">Deprecated since version 1.0: </span>"""
"""<p><span class="versionmodified deprecated">Deprecated since version 1.0: </span>"""
"""THIS IS THE <em>FIRST</em> PARAGRAPH OF DEPRECATED.</p>\n"""
"""<p>THIS IS THE <em>SECOND</em> PARAGRAPH OF DEPRECATED.</p>\n""")
matched_content = get_content(result, "deprecated")
assert expect1 == matched_content
expect2 = (
"""<p><span class="versionmodified">New in version 1.0: </span>"""
"""<p><span class="versionmodified added">New in version 1.0: </span>"""
"""THIS IS THE <em>FIRST</em> PARAGRAPH OF VERSIONADDED.</p>\n""")
matched_content = get_content(result, "versionadded")
assert expect2 == matched_content
expect3 = (
"""<p><span class="versionmodified">Changed in version 1.0: </span>"""
"""<p><span class="versionmodified changed">Changed in version 1.0: </span>"""
"""THIS IS THE <em>FIRST</em> PARAGRAPH OF VERSIONCHANGED.</p>\n""")
matched_content = get_content(result, "versionchanged")
assert expect3 == matched_content

View File

@@ -12,7 +12,6 @@ import time
from io import StringIO
import pytest
from six import text_type
from sphinx import application
from sphinx.cmd import quickstart as qs
@@ -35,7 +34,6 @@ def mock_input(answers, needanswer=False):
raise AssertionError('answer for %r missing and no default '
'present' % prompt)
called.add(prompt)
prompt = text_type(prompt)
for question in answers:
if prompt.startswith(qs.PROMPT_PREFIX + question):
return answers[question]