diff options
author | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2019-12-22 18:47:30 +0900 |
---|---|---|
committer | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2019-12-22 18:47:30 +0900 |
commit | 5640cf879f91c8ca5e71b68ab5a5fd24b536703a (patch) | |
tree | 6fc2107d8adc1ade4f9a8ca260db4e156fdde609 /sphinx | |
parent | e83bb29789a093c651a255a509430a03346a5afb (diff) | |
parent | 43c089fd28dfdc33cc67b364724db51d3f5c1804 (diff) | |
download | sphinx-git-5640cf879f91c8ca5e71b68ab5a5fd24b536703a.tar.gz |
Merge branch '2.0'
Diffstat (limited to 'sphinx')
-rw-r--r-- | sphinx/application.py | 8 | ||||
-rw-r--r-- | sphinx/builders/html.py | 11 | ||||
-rw-r--r-- | sphinx/builders/latex/__init__.py | 14 | ||||
-rw-r--r-- | sphinx/cmd/quickstart.py | 10 | ||||
-rw-r--r-- | sphinx/directives/other.py | 2 | ||||
-rw-r--r-- | sphinx/domains/index.py | 65 | ||||
-rw-r--r-- | sphinx/domains/javascript.py | 4 | ||||
-rw-r--r-- | sphinx/domains/python.py | 6 | ||||
-rw-r--r-- | sphinx/environment/__init__.py | 136 | ||||
-rw-r--r-- | sphinx/environment/adapters/toctree.py | 2 | ||||
-rw-r--r-- | sphinx/environment/collectors/indexentries.py | 7 | ||||
-rw-r--r-- | sphinx/ext/autodoc/__init__.py | 12 | ||||
-rw-r--r-- | sphinx/ext/autosummary/__init__.py | 2 | ||||
-rw-r--r-- | sphinx/ext/doctest.py | 6 | ||||
-rw-r--r-- | sphinx/ext/intersphinx.py | 4 | ||||
-rw-r--r-- | sphinx/ext/napoleon/docstring.py | 4 | ||||
-rw-r--r-- | sphinx/jinja2glue.py | 2 | ||||
-rw-r--r-- | sphinx/pycode/parser.py | 2 | ||||
-rw-r--r-- | sphinx/transforms/__init__.py | 2 | ||||
-rw-r--r-- | sphinx/transforms/post_transforms/__init__.py | 2 | ||||
-rw-r--r-- | sphinx/util/jsdump.py | 2 | ||||
-rw-r--r-- | sphinx/writers/html.py | 2 | ||||
-rw-r--r-- | sphinx/writers/html5.py | 2 | ||||
-rw-r--r-- | sphinx/writers/latex.py | 32 | ||||
-rw-r--r-- | sphinx/writers/texinfo.py | 6 |
25 files changed, 277 insertions, 68 deletions
diff --git a/sphinx/application.py b/sphinx/application.py index d3d0b07b1..99490cecd 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -78,6 +78,7 @@ builtin_extensions = ( 'sphinx.domains.changeset', 'sphinx.domains.citation', 'sphinx.domains.cpp', + 'sphinx.domains.index', 'sphinx.domains.javascript', 'sphinx.domains.math', 'sphinx.domains.python', @@ -106,7 +107,6 @@ builtin_extensions = ( 'sphinx.environment.collectors.metadata', 'sphinx.environment.collectors.title', 'sphinx.environment.collectors.toctree', - 'sphinx.environment.collectors.indexentries', # 1st party extensions 'sphinxcontrib.applehelp', 'sphinxcontrib.devhelp', @@ -350,8 +350,8 @@ class Sphinx: if self._warncount and self.keep_going: self.statuscode = 1 - status = (self.statuscode == 0 and - __('succeeded') or __('finished with problems')) + status = (__('succeeded') if self.statuscode == 0 + else __('finished with problems')) if self._warncount: if self.warningiserror: msg = __('build %s, %s warning (with warnings treated as errors).', @@ -494,7 +494,7 @@ class Sphinx: logger.debug('[app] adding config value: %r', (name, default, rebuild) + ((types,) if types else ())) # type: ignore if rebuild in (False, True): - rebuild = rebuild and 'env' or '' + rebuild = 'env' if rebuild else '' self.config.add(name, default, rebuild, types) def add_event(self, name): diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 48b21fa4e..7257b32ef 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -432,11 +432,8 @@ class StandaloneHTMLBuilder(Builder): else: self.last_updated = None - logo = self.config.html_logo and \ - path.basename(self.config.html_logo) or '' - - favicon = self.config.html_favicon and \ - path.basename(self.config.html_favicon) or '' + logo = path.basename(self.config.html_logo) if self.config.html_logo else '' + favicon = path.basename(self.config.html_favicon) if self.config.html_favicon else '' if not isinstance(self.config.html_use_opensearch, str): logger.warning(__('html_use_opensearch config value must now be a string')) @@ -538,7 +535,7 @@ class StandaloneHTMLBuilder(Builder): # title rendered as HTML title_node = self.env.longtitles.get(docname) - title = title_node and self.render_partial(title_node)['title'] or '' + title = self.render_partial(title_node)['title'] if title_node else '' # Suffix for the document source_suffix = path.splitext(self.env.doc2path(docname))[1] @@ -595,7 +592,7 @@ class StandaloneHTMLBuilder(Builder): self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir) self.post_process_images(doctree) title_node = self.env.longtitles.get(docname) - title = title_node and self.render_partial(title_node)['title'] or '' + title = self.render_partial(title_node)['title'] if title_node else '' self.index_page(docname, doctree, title) def finish(self) -> None: diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index de4223a0e..8111044d5 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -243,7 +243,7 @@ class LaTeXBuilder(Builder): doctree = self.assemble_doctree( docname, toctree_only, - appendices=((docclass != 'howto') and self.config.latex_appendices or [])) + appendices=(self.config.latex_appendices if docclass != 'howto' else [])) doctree['tocdepth'] = tocdepth self.post_process_images(doctree) self.update_doc_context(title, author) @@ -360,13 +360,6 @@ class LaTeXBuilder(Builder): copy_asset_file(path.join(staticdirname, 'Makefile_t'), self.outdir, context=context) - # the logo is handled differently - if self.config.latex_logo: - if not path.isfile(path.join(self.confdir, self.config.latex_logo)): - raise SphinxError(__('logo file %r does not exist') % self.config.latex_logo) - else: - copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir) - @progress_message(__('copying additional files')) def copy_latex_additional_files(self) -> None: for filename in self.config.latex_additional_files: @@ -386,6 +379,11 @@ class LaTeXBuilder(Builder): except Exception as err: logger.warning(__('cannot copy image file %r: %s'), path.join(self.srcdir, src), err) + if self.config.latex_logo: + if not path.isfile(path.join(self.confdir, self.config.latex_logo)): + raise SphinxError(__('logo file %r does not exist') % self.config.latex_logo) + else: + copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir) def write_message_catalog(self) -> None: formats = self.config.numfig_format diff --git a/sphinx/cmd/quickstart.py b/sphinx/cmd/quickstart.py index b28cd3519..83182ebf4 100644 --- a/sphinx/cmd/quickstart.py +++ b/sphinx/cmd/quickstart.py @@ -359,7 +359,7 @@ def generate(d: Dict, overwrite: bool = True, silent: bool = False, templatedir: ensuredir(d['path']) - srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] + srcdir = path.join(d['path'], 'source') if d['sep'] else d['path'] ensuredir(srcdir) if d['sep']: @@ -405,15 +405,15 @@ def generate(d: Dict, overwrite: bool = True, silent: bool = False, templatedir: batchfile_template = 'quickstart/make.bat_t' if d['makefile'] is True: - d['rsrcdir'] = d['sep'] and 'source' or '.' - d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' + d['rsrcdir'] = 'source' if d['sep'] else '.' + d['rbuilddir'] = 'build' if d['sep'] else d['dot'] + 'build' # use binary mode, to avoid writing \r\n on Windows write_file(path.join(d['path'], 'Makefile'), template.render(makefile_template, d), '\n') if d['batchfile'] is True: - d['rsrcdir'] = d['sep'] and 'source' or '.' - d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' + d['rsrcdir'] = 'source' if d['sep'] else '.' + d['rbuilddir'] = 'build' if d['sep'] else d['dot'] + 'build' write_file(path.join(d['path'], 'make.bat'), template.render(batchfile_template, d), '\r\n') diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index 1113e8241..a5a2831d6 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -300,7 +300,7 @@ class HList(SphinxDirective): index = 0 newnode = addnodes.hlist() for column in range(ncolumns): - endindex = index + (column < nmore and (npercol + 1) or npercol) + endindex = index + ((npercol + 1) if column < nmore else npercol) bullet_list = nodes.bullet_list() bullet_list += fulllist.children[index:endindex] newnode += addnodes.hlistcol('', bullet_list) diff --git a/sphinx/domains/index.py b/sphinx/domains/index.py new file mode 100644 index 000000000..4b1fd2bb6 --- /dev/null +++ b/sphinx/domains/index.py @@ -0,0 +1,65 @@ +""" + sphinx.domains.index + ~~~~~~~~~~~~~~~~~~~~ + + The index domain. + + :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from typing import Any, Dict, Iterable, List, Tuple + +from docutils.nodes import Node + +from sphinx import addnodes +from sphinx.application import Sphinx +from sphinx.domains import Domain +from sphinx.environment import BuildEnvironment +from sphinx.util import logging +from sphinx.util import split_index_msg + + +logger = logging.getLogger(__name__) + + +class IndexDomain(Domain): + """Mathematics domain.""" + name = 'index' + label = 'index' + + @property + def entries(self) -> Dict[str, List[Tuple[str, str, str, str, str]]]: + return self.data.setdefault('entries', {}) + + def clear_doc(self, docname: str) -> None: + self.entries.pop(docname, None) + + def merge_domaindata(self, docnames: Iterable[str], otherdata: Dict) -> None: + for docname in docnames: + self.entries[docname] = otherdata['entries'][docname] + + def process_doc(self, env: BuildEnvironment, docname: str, document: Node) -> None: + """Process a document after it is read by the environment.""" + entries = self.entries.setdefault(env.docname, []) + for node in document.traverse(addnodes.index): + try: + for entry in node['entries']: + split_index_msg(entry[0], entry[1]) + except ValueError as exc: + logger.warning(str(exc), location=node) + node.parent.remove(node) + else: + for entry in node['entries']: + entries.append(entry) + + +def setup(app: Sphinx) -> Dict[str, Any]: + app.add_domain(IndexDomain) + + return { + 'version': 'builtin', + 'env_version': 1, + 'parallel_read_safe': True, + 'parallel_write_safe': True, + } diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py index 121d5582d..da695065b 100644 --- a/sphinx/domains/javascript.py +++ b/sphinx/domains/javascript.py @@ -105,7 +105,7 @@ class JSObject(ObjectDescription): def add_target_and_index(self, name_obj: Tuple[str, str], sig: str, signode: desc_signature) -> None: mod_name = self.env.ref_context.get('js:module') - fullname = (mod_name and mod_name + '.' or '') + name_obj[0] + fullname = (mod_name + '.' if mod_name else '') + name_obj[0] if fullname not in self.state.document.ids: signode['names'].append(fullname) signode['ids'].append(fullname.replace('$', '_S_')) @@ -385,7 +385,7 @@ class JavaScriptDomain(Domain): ) -> Element: mod_name = node.get('js:module') prefix = node.get('js:object') - searchorder = node.hasattr('refspecific') and 1 or 0 + searchorder = 1 if node.hasattr('refspecific') else 0 name, obj = self.find_obj(env, mod_name, prefix, target, typ, searchorder) if not obj: return None diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index 653dbf562..3e11173dc 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -306,7 +306,7 @@ class PyObject(ObjectDescription): def add_target_and_index(self, name_cls: Tuple[str, str], sig: str, signode: desc_signature) -> None: modname = self.options.get('module', self.env.ref_context.get('py:module')) - fullname = (modname and modname + '.' or '') + name_cls[0] + fullname = (modname + '.' if modname else '') + name_cls[0] # note target if fullname not in self.state.document.ids: signode['names'].append(fullname) @@ -821,7 +821,7 @@ class PythonModuleIndex(Index): num_toplevels += 1 subtype = 0 - qualifier = deprecated and _('Deprecated') or '' + qualifier = _('Deprecated') if deprecated else '' entries.append(IndexEntry(stripped + modname, subtype, docname, 'module-' + stripped + modname, platforms, qualifier, synopsis)) @@ -999,7 +999,7 @@ class PythonDomain(Domain): ) -> Element: modname = node.get('py:module') clsname = node.get('py:class') - searchmode = node.hasattr('refspecific') and 1 or 0 + searchmode = 1 if node.hasattr('refspecific') else 0 matches = self.find_obj(env, modname, clsname, target, type, searchmode) if not matches: diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index bc9bf49a7..6d9af2a33 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -14,7 +14,8 @@ import warnings from collections import defaultdict from copy import copy from os import path -from typing import Any, Callable, Dict, Generator, Iterator, List, Set, Tuple, Union +from typing import Any, Callable, Dict, Generator, IO, Iterator, List, Set, Tuple, Union +from typing import cast from docutils import nodes from docutils.nodes import Node @@ -167,11 +168,6 @@ class BuildEnvironment: self.domaindata = {} # type: Dict[str, Dict] # domainname -> domain-specific dict - # Other inventories - self.indexentries = {} # type: Dict[str, List[Tuple[str, str, str, str, str]]] - # docname -> list of - # (type, str, target, aliasname) - # these map absolute path -> (docnames, unique filename) self.images = FilenameUniqDict() # type: FilenameUniqDict self.dlfiles = DownloadFiles() # type: DownloadFiles @@ -640,3 +636,131 @@ class BuildEnvironment: for domain in self.domains.values(): domain.check_consistency() self.events.emit('env-check-consistency', self) +<<<<<<< HEAD +======= + + # --------- METHODS FOR COMPATIBILITY -------------------------------------- + + def update(self, config: Config, srcdir: str, doctreedir: str) -> List[str]: + warnings.warn('env.update() is deprecated. Please use builder.read() instead.', + RemovedInSphinx30Warning, stacklevel=2) + return self.app.builder.read() + + def _read_serial(self, docnames: List[str], app: "Sphinx") -> None: + warnings.warn('env._read_serial() is deprecated. Please use builder.read() instead.', + RemovedInSphinx30Warning, stacklevel=2) + return self.app.builder._read_serial(docnames) + + def _read_parallel(self, docnames: List[str], app: "Sphinx", nproc: int) -> None: + warnings.warn('env._read_parallel() is deprecated. Please use builder.read() instead.', + RemovedInSphinx30Warning, stacklevel=2) + return self.app.builder._read_parallel(docnames, nproc) + + def read_doc(self, docname: str, app: "Sphinx" = None) -> None: + warnings.warn('env.read_doc() is deprecated. Please use builder.read_doc() instead.', + RemovedInSphinx30Warning, stacklevel=2) + self.app.builder.read_doc(docname) + + def write_doctree(self, docname: str, doctree: nodes.document) -> None: + warnings.warn('env.write_doctree() is deprecated. ' + 'Please use builder.write_doctree() instead.', + RemovedInSphinx30Warning, stacklevel=2) + self.app.builder.write_doctree(docname, doctree) + + @property + def _nitpick_ignore(self) -> List[str]: + warnings.warn('env._nitpick_ignore is deprecated. ' + 'Please use config.nitpick_ignore instead.', + RemovedInSphinx30Warning, stacklevel=2) + return self.config.nitpick_ignore + + @staticmethod + def load(f: IO, app: "Sphinx" = None) -> "BuildEnvironment": + warnings.warn('BuildEnvironment.load() is deprecated. ' + 'Please use pickle.load() instead.', + RemovedInSphinx30Warning, stacklevel=2) + try: + env = pickle.load(f) + except Exception as exc: + # This can happen for example when the pickle is from a + # different version of Sphinx. + raise OSError(exc) + if app: + env.app = app + env.config.values = app.config.values + return env + + @classmethod + def loads(cls, string: bytes, app: "Sphinx" = None) -> "BuildEnvironment": + warnings.warn('BuildEnvironment.loads() is deprecated. ' + 'Please use pickle.loads() instead.', + RemovedInSphinx30Warning, stacklevel=2) + io = BytesIO(string) + return cls.load(io, app) + + @classmethod + def frompickle(cls, filename: str, app: "Sphinx") -> "BuildEnvironment": + warnings.warn('BuildEnvironment.frompickle() is deprecated. ' + 'Please use pickle.load() instead.', + RemovedInSphinx30Warning, stacklevel=2) + with open(filename, 'rb') as f: + return cls.load(f, app) + + @staticmethod + def dump(env: "BuildEnvironment", f: IO) -> None: + warnings.warn('BuildEnvironment.dump() is deprecated. ' + 'Please use pickle.dump() instead.', + RemovedInSphinx30Warning, stacklevel=2) + pickle.dump(env, f, pickle.HIGHEST_PROTOCOL) + + @classmethod + def dumps(cls, env: "BuildEnvironment") -> bytes: + warnings.warn('BuildEnvironment.dumps() is deprecated. ' + 'Please use pickle.dumps() instead.', + RemovedInSphinx30Warning, stacklevel=2) + io = BytesIO() + cls.dump(env, io) + return io.getvalue() + + def topickle(self, filename: str) -> None: + warnings.warn('env.topickle() is deprecated. ' + 'Please use pickle.dump() instead.', + RemovedInSphinx30Warning, stacklevel=2) + with open(filename, 'wb') as f: + self.dump(self, f) + + @property + def versionchanges(self) -> Dict[str, List[Tuple[str, str, int, str, str, str]]]: + warnings.warn('env.versionchanges() is deprecated. ' + 'Please use ChangeSetDomain instead.', + RemovedInSphinx30Warning, stacklevel=2) + return self.domaindata['changeset']['changes'] + + def note_versionchange(self, type: str, version: str, + node: addnodes.versionmodified, lineno: int) -> None: + warnings.warn('env.note_versionchange() is deprecated. ' + 'Please use ChangeSetDomain.note_changeset() instead.', + RemovedInSphinx30Warning, stacklevel=2) + node['type'] = type + node['version'] = version + node.line = lineno + self.get_domain('changeset').note_changeset(node) # type: ignore + + @property + def indexentries(self) -> Dict[str, List[Tuple[str, str, str, str, str]]]: + warnings.warn('env.indexentries() is deprecated. Please use IndexDomain instead.', + RemovedInSphinx40Warning) + from sphinx.domains.index import IndexDomain + domain = cast(IndexDomain, self.get_domain('index')) + return domain.entries + + +from sphinx.errors import NoUri # NOQA + + +deprecated_alias('sphinx.environment', + { + 'NoUri': NoUri, + }, + RemovedInSphinx30Warning) +>>>>>>> 2.0 diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index d5f827dde..0975b33cd 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -252,7 +252,7 @@ class TocTree: # prune the tree to maxdepth, also set toc depth and current classes _toctree_add_classes(newnode, 1) - self._toctree_prune(newnode, 1, prune and maxdepth or 0, collapse) + self._toctree_prune(newnode, 1, maxdepth if prune else 0, collapse) if isinstance(newnode[-1], nodes.Element) and len(newnode[-1]) == 0: # No titles found return None diff --git a/sphinx/environment/collectors/indexentries.py b/sphinx/environment/collectors/indexentries.py index 9c86779fc..640eb915b 100644 --- a/sphinx/environment/collectors/indexentries.py +++ b/sphinx/environment/collectors/indexentries.py @@ -8,22 +8,29 @@ :license: BSD, see LICENSE for details. """ +import warnings from typing import Any, Dict, Set from docutils import nodes from sphinx import addnodes from sphinx.application import Sphinx +from sphinx.deprecation import RemovedInSphinx40Warning from sphinx.environment import BuildEnvironment from sphinx.environment.collectors import EnvironmentCollector from sphinx.util import split_index_msg, logging + logger = logging.getLogger(__name__) class IndexEntriesCollector(EnvironmentCollector): name = 'indices' + def __init__(self) -> None: + warnings.warn('IndexEntriesCollector is deprecated.', + RemovedInSphinx40Warning) + def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None: env.indexentries.pop(docname, None) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index a89f01d36..39c68a3cc 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -301,7 +301,7 @@ class Documenter: # support explicit module and class name separation via :: if explicit_modname is not None: modname = explicit_modname[:-2] - parents = path and path.rstrip('.').split('.') or [] + parents = path.rstrip('.').split('.') if path else [] else: modname = None parents = [] @@ -314,7 +314,7 @@ class Documenter: self.args = args self.retann = retann self.fullname = (self.modname or '') + \ - (self.objpath and '.' + '.'.join(self.objpath) or '') + ('.' + '.'.join(self.objpath) if self.objpath else '') return True def import_object(self) -> bool: @@ -405,7 +405,7 @@ class Documenter: args, retann = result if args is not None: - return args + (retann and (' -> %s' % retann) or '') + return args + ((' -> %s' % retann) if retann else '') else: return '' @@ -1126,9 +1126,9 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: sourcename = self.get_sourcename() self.add_line('', sourcename) if hasattr(self.object, '__bases__') and len(self.object.__bases__): - bases = [b.__module__ in ('__builtin__', 'builtins') and - ':class:`%s`' % b.__name__ or - ':class:`%s.%s`' % (b.__module__, b.__name__) + bases = [':class:`%s`' % b.__name__ + if b.__module__ in ('__builtin__', 'builtins') + else ':class:`%s.%s`' % (b.__module__, b.__name__) for b in self.object.__bases__] self.add_line(' ' + _('Bases: %s') % ', '.join(bases), sourcename) diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 5c50c165f..7d92fa06a 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -722,7 +722,7 @@ def process_generate_options(app: Sphinx) -> None: if os.path.isfile(env.doc2path(x))] else: ext = list(app.config.source_suffix) - genfiles = [genfile + (not genfile.endswith(tuple(ext)) and ext[0] or '') + genfiles = [genfile + (ext[0] if not genfile.endswith(tuple(ext)) else '') for genfile in genfiles] for entry in genfiles[:]: diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index 996f8394f..1c356ff6d 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -326,7 +326,7 @@ class DocTestBuilder(Builder): def finish(self) -> None: # write executive summary def s(v: int) -> str: - return v != 1 and 's' or '' + return 's' if v != 1 else '' repl = (self.total_tries, s(self.total_tries), self.total_failures, s(self.total_failures), self.setup_failures, s(self.setup_failures), @@ -523,8 +523,8 @@ Doctest summary self.type = 'single' # as for ordinary doctests else: # testcode and output separate - output = code[1] and code[1].code or '' - options = code[1] and code[1].options or {} + output = code[1].code if code[1] else '' + options = code[1].options if code[1] else {} # disable <BLANKLINE> processing as it is not needed options[doctest.DONT_ACCEPT_BLANKLINE] = True # find out if we're testing an exception diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index 7745d43d4..a403698f2 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -176,7 +176,7 @@ def fetch_inventory(app: Sphinx, uri: str, inv: Any) -> Any: uri = path.dirname(newinv) with f: try: - join = localuri and path.join or posixpath.join + join = path.join if localuri else posixpath.join invdata = InventoryFile.load(f, uri, join) except ValueError as exc: raise ValueError('unknown or unsupported inventory version: %r' % exc) @@ -401,7 +401,7 @@ def inspect_main(argv: List[str]) -> None: print(key) for entry, einfo in sorted(invdata[key].items()): print('\t%-40s %s%s' % (entry, - einfo[3] != '-' and '%-40s: ' % einfo[3] or '', + '%-40s: ' % einfo[3] if einfo[3] != '-' else '', einfo[2])) except ValueError as exc: print(exc.args[0] % exc.args[1:]) diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index 5610815bd..bb77aa22d 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -112,7 +112,7 @@ class GoogleDocstring: if not self._config: from sphinx.ext.napoleon import Config - self._config = self._app and self._app.config or Config() # type: ignore + self._config = self._app.config if self._app else Config() # type: ignore if not what: if inspect.isclass(obj): @@ -385,7 +385,7 @@ class GoogleDocstring: def _format_field(self, _name: str, _type: str, _desc: List[str]) -> List[str]: _desc = self._strip_empty(_desc) has_desc = any(_desc) - separator = has_desc and ' -- ' or '' + separator = ' -- ' if has_desc else '' if _name: if _type: if '`' in _type: diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py index f767bd7f7..1a356c021 100644 --- a/sphinx/jinja2glue.py +++ b/sphinx/jinja2glue.py @@ -188,7 +188,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader): self.loaders = [SphinxFileSystemLoader(x) for x in loaderchain] use_i18n = builder.app.translator is not None - extensions = use_i18n and ['jinja2.ext.i18n'] or [] + extensions = ['jinja2.ext.i18n'] if use_i18n else [] self.environment = SandboxedEnvironment(loader=self, extensions=extensions) self.environment.filters['tobool'] = _tobool diff --git a/sphinx/pycode/parser.py b/sphinx/pycode/parser.py index cbae86c9e..690f4297e 100644 --- a/sphinx/pycode/parser.py +++ b/sphinx/pycode/parser.py @@ -479,7 +479,7 @@ class Parser: def parse_comments(self) -> None: """Parse the code and pick up comments.""" - tree = ast.parse(self.code.encode()) + tree = ast.parse(self.code) picker = VariableCommentPicker(self.code.splitlines(True), self.encoding) picker.visit(tree) self.comments = picker.comments diff --git a/sphinx/transforms/__init__.py b/sphinx/transforms/__init__.py index 3d72b88df..b6119d8da 100644 --- a/sphinx/transforms/__init__.py +++ b/sphinx/transforms/__init__.py @@ -296,7 +296,7 @@ class FilterSystemMessages(SphinxTransform): default_priority = 999 def apply(self, **kwargs) -> None: - filterlevel = self.config.keep_warnings and 2 or 5 + filterlevel = 2 if self.config.keep_warnings else 5 for node in self.document.traverse(nodes.system_message): if node['level'] < filterlevel: logger.debug('%s [filtered system message]', node.astext()) diff --git a/sphinx/transforms/post_transforms/__init__.py b/sphinx/transforms/post_transforms/__init__.py index 090ff0084..9cb7add44 100644 --- a/sphinx/transforms/post_transforms/__init__.py +++ b/sphinx/transforms/post_transforms/__init__.py @@ -155,7 +155,7 @@ class ReferencesResolver(SphinxPostTransform): if self.config.nitpicky: warn = True if self.config.nitpick_ignore: - dtype = domain and '%s:%s' % (domain.name, typ) or typ + dtype = '%s:%s' % (domain.name, typ) if domain else typ if (dtype, target) in self.config.nitpick_ignore: warn = False # for "std" types also try without domain name diff --git a/sphinx/util/jsdump.py b/sphinx/util/jsdump.py index bfdba170b..2be48a34a 100644 --- a/sphinx/util/jsdump.py +++ b/sphinx/util/jsdump.py @@ -83,7 +83,7 @@ def dumps(obj: Any, key: bool = False) -> str: if obj is None: return 'null' elif obj is True or obj is False: - return obj and 'true' or 'false' + return 'true' if obj else 'false' elif isinstance(obj, (int, float)): return str(obj) elif isinstance(obj, dict): diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index eac446793..e5d00fd2c 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -89,7 +89,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 '¶' or '' + self.permalink_text = '¶' if self.permalink_text else '' self.permalink_text = self.encode(self.permalink_text) self.secnumber_suffix = self.config.html_secnumber_suffix self.param_separator = '' diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index 438f161f7..e6bf0c9b2 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -61,7 +61,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 '¶' or '' + self.permalink_text = '¶' if self.permalink_text else '' self.permalink_text = self.encode(self.permalink_text) self.secnumber_suffix = self.config.html_secnumber_suffix self.param_separator = '' diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index e5573c182..db326406d 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -631,7 +631,7 @@ class LaTeXTranslator(SphinxTranslator): latex_engine=self.config.latex_engine) self.context = [] # type: List[Any] self.descstack = [] # type: List[str] - self.table = None # type: Table + self.tables = [] # type: List[Table] self.next_table_colspec = None # type: str self.bodystack = [] # type: List[List[str]] self.footnote_restricted = None # type: nodes.Element @@ -665,7 +665,7 @@ class LaTeXTranslator(SphinxTranslator): def hypertarget(self, id: str, withdoc: bool = True, anchor: bool = True) -> str: if withdoc: id = self.curfilestack[-1] + ':' + id - return (anchor and '\\phantomsection' or '') + \ + return ('\\phantomsection' if anchor else '') + \ '\\label{%s}' % self.idescape(id) def hypertarget_to(self, node: Element, anchor: bool = False) -> str: @@ -749,6 +749,14 @@ class LaTeXTranslator(SphinxTranslator): return renderer.render(template_name, variables) + @property + def table(self) -> Table: + """Get current table.""" + if self.tables: + return self.tables[-1] + else: + return None + def visit_document(self, node: Element) -> None: self.curfilestack.append(node.get('docname', '')) if self.first_document == 1: @@ -1045,11 +1053,21 @@ class LaTeXTranslator(SphinxTranslator): raise nodes.SkipNode def visit_table(self, node: Element) -> None: - if self.table: + if len(self.tables) == 1: + if self.table.get_table_type() == 'longtable': + raise UnsupportedError( + '%s:%s: longtable does not support nesting a table.' % + (self.curfilestack[-1], node.line or '')) + else: + # change type of parent table to tabular + # see https://groups.google.com/d/msg/sphinx-users/7m3NeOBixeo/9LKP2B4WBQAJ + self.table.has_problematic = True + elif len(self.tables) > 2: raise UnsupportedError( - '%s:%s: nested tables are not yet implemented.' % + '%s:%s: deeply nested tables are not implemented.' % (self.curfilestack[-1], node.line or '')) - self.table = Table(node) + + self.tables.append(Table(node)) if self.next_table_colspec: self.table.colspec = '{%s}\n' % self.next_table_colspec if 'colwidths-given' in node.get('classes', []): @@ -1066,7 +1084,7 @@ class LaTeXTranslator(SphinxTranslator): self.body.append(table) self.body.append("\n") - self.table = None + self.tables.pop() def visit_colspec(self, node: Element) -> None: self.table.colcount += 1 @@ -1491,7 +1509,7 @@ class LaTeXTranslator(SphinxTranslator): elif isinstance(node[0], nodes.image) and 'width' in node[0]: length = self.latex_image_length(node[0]['width']) self.body.append('\\begin{wrapfigure}{%s}{%s}\n\\centering' % - (node['align'] == 'right' and 'r' or 'l', length or '0pt')) + ('r' if node['align'] == 'right' else 'l', length or '0pt')) self.context.append('\\end{wrapfigure}\n') elif self.in_minipage: self.body.append('\n\\begin{center}') diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index fd33c9fe4..2a631f176 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -240,7 +240,7 @@ class TexinfoTranslator(SphinxTranslator): title = self.settings.title # type: str if not title: title_node = self.document.next_node(nodes.title) - title = (title_node and title_node.astext()) or '<untitled>' + title = title_node.astext() if title_node else '<untitled>' elements['title'] = self.escape_id(title) or '<untitled>' # filename if not elements['filename']: @@ -290,7 +290,7 @@ class TexinfoTranslator(SphinxTranslator): # each section is also a node for section in self.document.traverse(nodes.section): title = cast(nodes.TextElement, section.next_node(nodes.Titular)) - name = (title and title.astext()) or '<untitled>' + name = title.astext() if title else '<untitled>' section['node_name'] = add_node_name(name) def collect_node_menus(self) -> None: @@ -304,7 +304,7 @@ class TexinfoTranslator(SphinxTranslator): node_menus[node['node_name']] = entries # try to find a suitable "Top" node title = self.document.next_node(nodes.title) - top = (title and title.parent) or self.document + top = title.parent if title else self.document if not isinstance(top, (nodes.document, nodes.section)): top = self.document if top is not self.document: |