diff --git a/CHANGES b/CHANGES index 201074afd..541cfff94 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,7 @@ Incompatible changes API directly * #6230: The anchor of term in glossary directive is changed if it is consisted by non-ASCII characters +* #4550: html: Centering tables by default using CSS Deprecated ---------- @@ -73,7 +74,8 @@ Features added * #6180: Support ``--keep-going`` with BuildDoc setup command * ``math`` directive now supports ``:class:`` option * todo: ``todo`` directive now supports ``:name:`` option -* #6232: Enable CLI override of Makefile variables +* Enable override via environment of ``SPHINXOPTS`` and ``SPHINXBUILD`` Makefile + variables (refs: #6232, #6303) * #6287: autodoc: Unable to document bound instance methods exported as module functions * #6289: autodoc: :confval:`autodoc_default_options` now supports @@ -83,8 +85,16 @@ Features added imported members on autosummary * #6271: ``make clean`` is catastrophically broken if building into '.' * #4777: py domain: Add ``:async:`` option to :rst:dir:`py:function` directive -* py domain: Add ``:async:``, ``:classmethod:`` and ``:staticmethod:`` options - to :rst:dir:`py:method` directive +* py domain: Add new options to :rst:dir:`py:method` directive + + - ``:async:`` + - ``:classmethod:`` + - ``:property:`` + - ``:staticmethod:`` + +* rst domain: Add :rst:dir:`directive:option` directive to describe the option + for directive +* #6306: html: Add a label to search form for accessability purposes Bugs fixed ---------- @@ -95,7 +105,11 @@ Bugs fixed * commented term in glossary directive is wrongly recognized * #6299: rst domain: rst:directive directive generates waste space * #6331: man: invalid output when doctest follows rubric +* #6351: "Hyperlink target is not referenced" message is shown even if + referenced +* #6165: autodoc: ``tab_width`` setting of docutils has been ignored * #6311: autosummary: autosummary table gets confused by complex type hints +* Generated Makefiles lack a final EOL (refs: #6232) Testing -------- diff --git a/doc/develop.rst b/doc/develop.rst index d061aae61..3828b709d 100644 --- a/doc/develop.rst +++ b/doc/develop.rst @@ -31,7 +31,8 @@ This is the current list of contributed extensions in that repository: - actdiag: embed activity diagrams by using actdiag_ - adadomain: an extension for Ada support (Sphinx 1.0 needed) - ansi: parse ANSI color sequences inside documents -- argdoc: automatically generate documentation for command-line arguments, descriptions, and help text +- argdoc: automatically generate documentation for command-line arguments, + descriptions and help text - astah: embed diagram by using astah - autoanysrc: Gather reST documentation from any source files - autorun: Execute code in a ``runblock`` directive @@ -64,7 +65,8 @@ This is the current list of contributed extensions in that repository: - imgur: embed Imgur images, albums, and metadata in documents - inlinesyntaxhighlight_: inline syntax highlighting - lassodomain: a domain for documenting Lasso_ source code -- libreoffice: an extension to include any drawing supported by LibreOffice (e.g. odg, vsd, ...) +- libreoffice: an extension to include any drawing supported by LibreOffice + (e.g. odg, vsd, ...) - lilypond: an extension inserting music scripts from Lilypond_ in PNG format - makedomain_: a domain for `GNU Make`_ - matlabdomain: document MATLAB_ code @@ -100,8 +102,8 @@ This is the current list of contributed extensions in that repository: - zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_ -See the :doc:`extension tutorials <../development/tutorials/index>` on getting started with writing your -own extensions. +See the :doc:`extension tutorials <../development/tutorials/index>` on getting +started with writing your own extensions. .. _aafigure: https://launchpad.net/aafigure diff --git a/doc/extdev/index.rst b/doc/extdev/index.rst index eac4ded40..c70ca37be 100644 --- a/doc/extdev/index.rst +++ b/doc/extdev/index.rst @@ -97,7 +97,8 @@ extension. These are: 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`. +To see an example of use of these objects, refer to +:doc:`../development/tutorials/index`. .. _build-phases: diff --git a/doc/extdev/markupapi.rst b/doc/extdev/markupapi.rst index ffa08cae7..fc25c2327 100644 --- a/doc/extdev/markupapi.rst +++ b/doc/extdev/markupapi.rst @@ -147,5 +147,6 @@ return ``node.children`` from the Directive. .. seealso:: - `Creating directives `_ - HOWTO of the Docutils documentation + `Creating directives`_ HOWTO of the Docutils documentation + +.. _Creating directives: http://docutils.sourceforge.net/docs/howto/rst-directives.html diff --git a/doc/templating.rst b/doc/templating.rst index b3a26c4b1..3790275f5 100644 --- a/doc/templating.rst +++ b/doc/templating.rst @@ -354,8 +354,8 @@ are in HTML form), these variables are also available: .. data:: body - A string containing the content of the page in HTML form as produced by the HTML builder, - before the theme is applied. + A string containing the content of the page in HTML form as produced by the + HTML builder, before the theme is applied. .. data:: display_toc @@ -382,8 +382,9 @@ are in HTML form), these variables are also available: .. 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. + 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. .. data:: parents diff --git a/doc/usage/restructuredtext/domains.rst b/doc/usage/restructuredtext/domains.rst index 10fbf6f6f..8b06bf0e0 100644 --- a/doc/usage/restructuredtext/domains.rst +++ b/doc/usage/restructuredtext/domains.rst @@ -229,9 +229,13 @@ The following directives are provided for module and class contents: The ``classmethod`` option and ``staticmethod`` option can be given (with no value) to indicate the method is a class method (or a static method). + The ``property`` option can be given (with no value) to indicate the method + is a property. + .. versionchanged:: 2.1 - ``:async:``, ``:classmethod:`` and ``:staticmethod:`` options added. + ``:async:``, ``:classmethod:``, ``:property:`` and ``:staticmethod:`` + options added. .. rst:directive:: .. py:staticmethod:: name(parameters) @@ -1079,15 +1083,16 @@ These roles link to the given declaration types: .. admonition:: Note on References with Templates Parameters/Arguments - These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must be - taken when referencing a (partial) template specialization, e.g. if the link looks like - this: ``:cpp:class:`MyClass```. + These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must + be taken when referencing a (partial) template specialization, e.g. if the + link looks like this: ``:cpp:class:`MyClass```. This is interpreted as a link to ``int`` with a title of ``MyClass``. In this case, escape the opening angle bracket with a backslash, like this: ``:cpp:class:`MyClass\```. - When a custom title is not needed it may be useful to use the roles for inline expressions, - :rst:role:`cpp:expr` and :rst:role:`cpp:texpr`, where angle brackets do not need escaping. + When a custom title is not needed it may be useful to use the roles for + inline expressions, :rst:role:`cpp:expr` and :rst:role:`cpp:texpr`, where + angle brackets do not need escaping. Declarations without template parameters and template arguments ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1419,6 +1424,43 @@ The reStructuredText domain (name **rst**) provides the following directives: Bar description. +.. rst:directive:: .. rst:directive:option:: name + + Describes an option for reST directive. The *name* can be a single option + name or option name with arguments which separated with colon (``:``). + For example:: + + .. rst:directive:: toctree + + .. rst:directive:option:: caption: caption of ToC + + .. rst:directive:option:: glob + + will be rendered as: + + .. rst:directive:: toctree + :noindex: + + .. rst:directive:option:: caption: caption of ToC + + .. rst:directive:option:: glob + + .. rubric:: options + + .. rst:directive:option:: type + :type: description for the option of directive + + Describe the type of option value. + + For example:: + + .. rst:directive:: toctree + + .. rst:directive:option:: maxdepth + :type: integer or no value + + .. versionadded:: 2.1 + .. rst:directive:: .. rst:role:: name Describes a reST role. For example:: diff --git a/setup.cfg b/setup.cfg index 2db007339..c91a31879 100644 --- a/setup.cfg +++ b/setup.cfg @@ -55,6 +55,11 @@ strict_optional = False filterwarnings = all ignore::DeprecationWarning:docutils.io +markers = + sphinx + apidoc + setup_command + test_params [coverage:run] branch = True diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index c1ef3f990..c4971ba60 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -587,22 +587,28 @@ class PyMethod(PyObject): option_spec.update({ 'async': directives.flag, 'classmethod': directives.flag, + 'property': directives.flag, 'staticmethod': directives.flag, }) def needs_arglist(self): # type: () -> bool - return True + if 'property' in self.options: + return False + else: + return True def get_signature_prefix(self, sig): # type: (str) -> str prefix = [] if 'async' in self.options: prefix.append('async') - if 'staticmethod' in self.options: - prefix.append('static') if 'classmethod' in self.options: prefix.append('classmethod') + if 'property' in self.options: + prefix.append('property') + if 'staticmethod' in self.options: + prefix.append('static') if prefix: return ' '.join(prefix) + ' ' @@ -622,10 +628,12 @@ class PyMethod(PyObject): else: return '%s()' % name - if 'staticmethod' in self.options: - return _('%s() (%s static method)') % (methname, clsname) - elif 'classmethod' in self.options: + if 'classmethod' in self.options: return _('%s() (%s class method)') % (methname, clsname) + elif 'property' in self.options: + return _('%s() (%s property)') % (methname, clsname) + elif 'staticmethod' in self.options: + return _('%s() (%s static method)') % (methname, clsname) else: return _('%s() (%s method)') % (methname, clsname) diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py index bccad0628..f054abf28 100644 --- a/sphinx/domains/rst.py +++ b/sphinx/domains/rst.py @@ -11,6 +11,8 @@ import re from typing import cast +from docutils.parsers.rst import directives + from sphinx import addnodes from sphinx.directives import ObjectDescription from sphinx.domains import Domain, ObjType @@ -98,6 +100,74 @@ class ReSTDirective(ReSTMarkup): # type: (str, str) -> str return _('%s (directive)') % name + def before_content(self): + # type: () -> None + if self.names: + directives = self.env.ref_context.setdefault('rst:directives', []) + directives.append(self.names[0]) + + def after_content(self): + # type: () -> None + directives = self.env.ref_context.setdefault('rst:directives', []) + if directives: + directives.pop() + + +class ReSTDirectiveOption(ReSTMarkup): + """ + Description of an option for reST directive. + """ + option_spec = ReSTMarkup.option_spec.copy() + option_spec.update({ + 'type': directives.unchanged, + }) + + def handle_signature(self, sig, signode): + # type: (str, addnodes.desc_signature) -> str + try: + name, argument = re.split(r'\s*:\s+', sig.strip(), 1) + except ValueError: + name, argument = sig, None + + signode += addnodes.desc_name(':%s:' % name, ':%s:' % name) + if argument: + signode += addnodes.desc_annotation(' ' + argument, ' ' + argument) + if self.options.get('type'): + text = ' (%s)' % self.options['type'] + signode += addnodes.desc_annotation(text, text) + return name + + def add_target_and_index(self, name, sig, signode): + # type: (str, str, addnodes.desc_signature) -> None + targetname = '-'.join([self.objtype, self.current_directive, name]) + if targetname not in self.state.document.ids: + signode['names'].append(targetname) + signode['ids'].append(targetname) + signode['first'] = (not self.names) + self.state.document.note_explicit_target(signode) + + domain = cast(ReSTDomain, self.env.get_domain('rst')) + domain.note_object(self.objtype, name, location=(self.env.docname, self.lineno)) + + if self.current_directive: + key = name[0].upper() + pair = [_('%s (directive)') % self.current_directive, + _(':%s: (directive option)') % name] + self.indexnode['entries'].append(('pair', '; '.join(pair), targetname, '', key)) + else: + key = name[0].upper() + text = _(':%s: (directive option)') % name + self.indexnode['entries'].append(('single', text, targetname, '', key)) + + @property + def current_directive(self): + # type: () -> str + directives = self.env.ref_context.get('rst:directives') + if directives: + return directives[-1] + else: + return '' + class ReSTRole(ReSTMarkup): """ @@ -119,11 +189,13 @@ class ReSTDomain(Domain): label = 'reStructuredText' object_types = { - 'directive': ObjType(_('directive'), 'dir'), - 'role': ObjType(_('role'), 'role'), + 'directive': ObjType(_('directive'), 'dir'), + 'directive:option': ObjType(_('directive-option'), 'dir'), + 'role': ObjType(_('role'), 'role'), } directives = { 'directive': ReSTDirective, + 'directive:option': ReSTDirectiveOption, 'role': ReSTRole, } roles = { diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index f1d052866..26936956e 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -448,7 +448,8 @@ class Documenter: docstring = getdoc(self.object, self.get_attr, self.env.config.autodoc_inherit_docstrings) if docstring: - return [prepare_docstring(docstring, ignore)] + tab_width = self.directive.state.document.settings.tab_width + return [prepare_docstring(docstring, ignore, tab_width)] return [] def process_doc(self, docstrings): @@ -942,7 +943,9 @@ class DocstringSignatureMixin: if base not in valid_names: continue # re-prepare docstring to ignore more leading indentation - self._new_docstrings[i] = prepare_docstring('\n'.join(doclines[1:])) + tab_width = self.directive.state.document.settings.tab_width # type: ignore + self._new_docstrings[i] = prepare_docstring('\n'.join(doclines[1:]), + tabsize=tab_width) result = args, retann # don't look any further break @@ -1186,7 +1189,9 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: docstrings = [initdocstring] else: docstrings.append(initdocstring) - return [prepare_docstring(docstring, ignore) for docstring in docstrings] + + tab_width = self.directive.state.document.settings.tab_width + return [prepare_docstring(docstring, ignore, tab_width) for docstring in docstrings] def add_content(self, more_content, no_docstring=False): # type: (Any, bool) -> None @@ -1422,6 +1427,37 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): super().add_content(more_content, no_docstring) +class PropertyDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore + """ + Specialized Documenter subclass for properties. + """ + objtype = 'property' + directivetype = 'method' + member_order = 60 + + # before AttributeDocumenter + priority = AttributeDocumenter.priority + 1 + + @classmethod + def can_document_member(cls, member, membername, isattr, parent): + # type: (Any, str, bool, Any) -> bool + return inspect.isproperty(member) and isinstance(parent, ClassDocumenter) + + def document_members(self, all_members=False): + # type: (bool) -> None + pass + + def get_real_modname(self): + # type: () -> str + return self.get_attr(self.parent or self.object, '__module__', None) \ + or self.modname + + def add_directive_header(self, sig): + # type: (str) -> None + super().add_directive_header(sig) + self.add_line(' :property:', self.get_sourcename()) + + class InstanceAttributeDocumenter(AttributeDocumenter): """ Specialized Documenter subclass for attributes that cannot be imported @@ -1513,6 +1549,7 @@ def setup(app): app.add_autodocumenter(DecoratorDocumenter) app.add_autodocumenter(MethodDocumenter) app.add_autodocumenter(AttributeDocumenter) + app.add_autodocumenter(PropertyDocumenter) app.add_autodocumenter(InstanceAttributeDocumenter) app.add_config_value('autoclass_content', 'class', True) diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py index 42415433b..6b002b101 100644 --- a/sphinx/ext/autodoc/directive.py +++ b/sphinx/ext/autodoc/directive.py @@ -6,10 +6,14 @@ :license: BSD, see LICENSE for details. """ +import warnings + from docutils import nodes +from docutils.parsers.rst.states import Struct from docutils.statemachine import StringList from docutils.utils import assemble_option_dict +from sphinx.deprecation import RemovedInSphinx40Warning from sphinx.ext.autodoc import Options, get_documenters from sphinx.util import logging from sphinx.util.docutils import SphinxDirective, switch_source_input @@ -17,7 +21,7 @@ from sphinx.util.nodes import nested_parse_with_titles if False: # For type annotation - from typing import Callable, Dict, List, Set, Type # NOQA + from typing import Any, Callable, Dict, List, Set, Type # NOQA from docutils.parsers.rst.state import RSTState # NOQA from docutils.utils import Reporter # NOQA from sphinx.config import Config # NOQA @@ -50,8 +54,8 @@ class DummyOptionSpec(dict): class DocumenterBridge: """A parameters container for Documenters.""" - def __init__(self, env, reporter, options, lineno): - # type: (BuildEnvironment, Reporter, Options, int) -> None + def __init__(self, env, reporter, options, lineno, state=None): + # type: (BuildEnvironment, Reporter, Options, int, Any) -> None self.env = env self.reporter = reporter self.genopt = options @@ -59,6 +63,16 @@ class DocumenterBridge: self.filename_set = set() # type: Set[str] self.result = StringList() + if state: + self.state = state + else: + # create fake object for self.state.document.settings.tab_width + warnings.warn('DocumenterBridge requires a state object on instantiation.', + RemovedInSphinx40Warning) + settings = Struct(tab_width=8) + document = Struct(settings=settings) + self.state = Struct(document=document) + def warn(self, msg): # type: (str) -> None logger.warning(msg, location=(self.env.docname, self.lineno)) @@ -131,7 +145,7 @@ class AutodocDirective(SphinxDirective): return [] # generate the output - params = DocumenterBridge(self.env, reporter, documenter_options, lineno) + params = DocumenterBridge(self.env, reporter, documenter_options, lineno, self.state) documenter = doccls(params, self.arguments[0]) documenter.generate(more_content=self.content) if not params.result: diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 7da65153a..656e67bf1 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -175,7 +175,7 @@ _app = None # type: Sphinx class FakeDirective(DocumenterBridge): def __init__(self): # type: () -> None - super().__init__({}, None, Options(), 0) # type: ignore + super().__init__({}, None, Options(), 0, None) # type: ignore def get_documenter(app, obj, parent): @@ -236,7 +236,7 @@ class Autosummary(SphinxDirective): def run(self): # type: () -> List[nodes.Node] self.bridge = DocumenterBridge(self.env, self.state.document.reporter, - Options(), self.lineno) + Options(), self.lineno, self.state) names = [x.strip().split()[0] for x in self.content if x.strip() and re.search(r'^[~a-zA-Z_]', x.strip()[0])] diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 1e9dbedc8..eac25697a 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -40,7 +40,7 @@ from sphinx.util.rst import escape as rst_escape if False: # For type annotation - from typing import Any, Callable, Dict, List, Tuple, Type, Union # NOQA + from typing import Any, Callable, Dict, List, Set, Tuple, Type, Union # NOQA from sphinx.builders import Builder # NOQA from sphinx.ext.autodoc import Documenter # NOQA @@ -169,8 +169,8 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', except TemplateNotFound: template = template_env.get_template('autosummary/base.rst') - def get_members(obj, typ, include_public=[], imported=True): - # type: (Any, str, List[str], bool) -> Tuple[List[str], List[str]] + def get_members(obj, types, include_public=[], imported=True): + # type: (Any, Set[str], List[str], bool) -> Tuple[List[str], List[str]] # NOQA items = [] # type: List[str] for name in dir(obj): try: @@ -178,7 +178,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', except AttributeError: continue documenter = get_documenter(app, value, obj) - if documenter.objtype == typ: + if documenter.objtype in types: if imported or getattr(value, '__module__', None) == obj.__name__: # skip imported members if expected items.append(name) @@ -191,19 +191,19 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', if doc.objtype == 'module': ns['members'] = dir(obj) ns['functions'], ns['all_functions'] = \ - get_members(obj, 'function', imported=imported_members) + get_members(obj, {'function'}, imported=imported_members) ns['classes'], ns['all_classes'] = \ - get_members(obj, 'class', imported=imported_members) + get_members(obj, {'class'}, imported=imported_members) ns['exceptions'], ns['all_exceptions'] = \ - get_members(obj, 'exception', imported=imported_members) + get_members(obj, {'exception'}, imported=imported_members) elif doc.objtype == 'class': ns['members'] = dir(obj) ns['inherited_members'] = \ set(dir(obj)) - set(obj.__dict__.keys()) ns['methods'], ns['all_methods'] = \ - get_members(obj, 'method', ['__init__']) + get_members(obj, {'method'}, ['__init__']) ns['attributes'], ns['all_attributes'] = \ - get_members(obj, 'attribute') + get_members(obj, {'attribute', 'property'}) parts = name.split('.') if doc.objtype in ('method', 'attribute'): diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index c53149ce6..dd602708a 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -32,6 +32,7 @@ if False: # For type annotation from typing import Any, Dict # NOQA from pygments.formatter import Formatter # NOQA + from pygments.style import Style # NOQA logger = logging.getLogger(__name__) @@ -69,16 +70,8 @@ class PygmentsBridge: def __init__(self, dest='html', stylename='sphinx', trim_doctest_flags=None): # type: (str, str, bool) -> None self.dest = dest - if stylename is None or stylename == 'sphinx': - style = SphinxStyle - elif stylename == 'none': - style = NoneStyle - elif '.' in stylename: - module, stylename = stylename.rsplit('.', 1) - style = getattr(__import__(module, None, None, ['__name__']), - stylename) - else: - style = get_style_by_name(stylename) + + style = self.get_style(stylename) self.formatter_args = {'style': style} # type: Dict[str, Any] if dest == 'html': self.formatter = self.html_formatter @@ -91,6 +84,18 @@ class PygmentsBridge: warnings.warn('trim_doctest_flags option for PygmentsBridge is now deprecated.', RemovedInSphinx30Warning, stacklevel=2) + def get_style(self, stylename): + # type: (str) -> Style + if stylename is None or stylename == 'sphinx': + return SphinxStyle + elif stylename == 'none': + return NoneStyle + elif '.' in stylename: + module, stylename = stylename.rsplit('.', 1) + return getattr(__import__(module, None, None, ['__name__']), stylename) + else: + return get_style_by_name(stylename) + def get_formatter(self, **kwargs): # type: (Any) -> Formatter kwargs.update(self.formatter_args) @@ -110,11 +115,8 @@ class PygmentsBridge: return '\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n' + \ source + '\\end{Verbatim}\n' - 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, str): - source = source.decode() - + def get_lexer(self, source, lang, opts=None, location=None): + # type: (str, str, Any, Any) -> Lexer # find out which lexer to use if lang in ('py', 'python'): if source.startswith('>>>'): @@ -145,6 +147,15 @@ class PygmentsBridge: else: lexer.add_filter('raiseonerror') + return lexer + + 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, str): + source = source.decode() + + lexer = self.get_lexer(source, lang, opts, location) + # trim doctest options if wanted if isinstance(lexer, PythonConsoleLexer) and self.trim_doctest_flags: source = doctest.blankline_re.sub('', source) @@ -165,6 +176,7 @@ class PygmentsBridge: type='misc', subtype='highlighting_failure', location=location) hlsource = highlight(source, lexers['none'], formatter) + if self.dest == 'html': return hlsource else: diff --git a/sphinx/io.py b/sphinx/io.py index b5b57d065..5f4ec3351 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -16,6 +16,7 @@ from docutils.io import FileInput, NullOutput from docutils.parsers.rst import Parser as RSTParser from docutils.readers import standalone from docutils.statemachine import StringList, string2lines +from docutils.transforms.references import DanglingReferences from docutils.writers import UnfilteredWriter from sphinx.deprecation import RemovedInSphinx30Warning @@ -64,7 +65,15 @@ class SphinxBaseReader(standalone.Reader): def get_transforms(self): # type: () -> List[Type[Transform]] - return super().get_transforms() + self.transforms + transforms = super().get_transforms() + self.transforms + + # remove transforms which is not needed for Sphinx + unused = [DanglingReferences] + for transform in unused: + if transform in transforms: + transforms.remove(transform) + + return transforms def new_document(self): # type: () -> nodes.document diff --git a/sphinx/templates/latex/longtable.tex_t b/sphinx/templates/latex/longtable.tex_t index ade1a54af..8fe5369df 100644 --- a/sphinx/templates/latex/longtable.tex_t +++ b/sphinx/templates/latex/longtable.tex_t @@ -1,5 +1,5 @@ \begin{savenotes}\sphinxatlongtablestart\begin{longtable} -<%- if table.align == 'center' -%> +<%- if table.align in ('center', 'default') -%> [c] <%- elif table.align == 'left' -%> [l] diff --git a/sphinx/templates/latex/tabular.tex_t b/sphinx/templates/latex/tabular.tex_t index a4f56feb3..a0db7faff 100644 --- a/sphinx/templates/latex/tabular.tex_t +++ b/sphinx/templates/latex/tabular.tex_t @@ -1,6 +1,6 @@ \begin{savenotes}\sphinxattablestart <% if table.align -%> - <%- if table.align == 'center' -%> + <%- if table.align in ('center', 'default') -%> \centering <%- elif table.align == 'left' -%> \raggedright diff --git a/sphinx/templates/latex/tabulary.tex_t b/sphinx/templates/latex/tabulary.tex_t index e3534725b..3236b798a 100644 --- a/sphinx/templates/latex/tabulary.tex_t +++ b/sphinx/templates/latex/tabulary.tex_t @@ -1,6 +1,6 @@ \begin{savenotes}\sphinxattablestart <% if table.align -%> - <%- if table.align == 'center' -%> + <%- if table.align in ('center', 'default') -%> \centering <%- elif table.align == 'left' -%> \raggedright diff --git a/sphinx/templates/quickstart/Makefile.new_t b/sphinx/templates/quickstart/Makefile.new_t index 7532398b2..1a527578b 100644 --- a/sphinx/templates/quickstart/Makefile.new_t +++ b/sphinx/templates/quickstart/Makefile.new_t @@ -1,14 +1,12 @@ # Minimal makefile for Sphinx documentation # -# You can set these variables from the command line. For example: -# SPHINXOPTS='-E -W -n' make html -# will run the html builder in a clean environment (-E), treating warnings -# as errors (-W), in nitpicky mode (-n). +# You can set these variables from the command line, and also +# from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build -SOURCEDIR ?= {{ rsrcdir }} -BUILDDIR ?= {{ rbuilddir }} +SOURCEDIR = {{ rsrcdir }} +BUILDDIR = {{ rbuilddir }} # Put it first so that "make" without argument is like "make help". help: diff --git a/sphinx/themes/basic/searchbox.html b/sphinx/themes/basic/searchbox.html index 2ed7fa137..6679ca6b5 100644 --- a/sphinx/themes/basic/searchbox.html +++ b/sphinx/themes/basic/searchbox.html @@ -9,10 +9,10 @@ #} {%- if pagename != "search" and builder != "singlehtml" %}