Skip to content

Commit

Permalink
Merge branch '4.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
tk0miya committed May 5, 2021
2 parents 6b8ee1e + 5127435 commit 26f1e2d
Show file tree
Hide file tree
Showing 25 changed files with 205 additions and 50 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Expand Up @@ -23,9 +23,9 @@ jobs:
python: 3.9
docutils: du17
coverage: "--cov ./ --cov-append --cov-config setup.cfg"
# - name: py310-dev
# python: 3.10-dev
# docutils: du16
- name: py310-dev
python: 3.10-dev
docutils: du17
env:
PYTEST_ADDOPTS: ${{ matrix.coverage }}

Expand Down
5 changes: 5 additions & 0 deletions CHANGES
Expand Up @@ -25,6 +25,8 @@ Release 4.1.0 (in development)
Dependencies
------------

* Support jinja2-3.0

Incompatible changes
--------------------

Expand All @@ -42,10 +44,13 @@ Features added
* #8588: autodoc: :confval:`autodoc_type_aliases` now supports dotted name. It
allows you to define an alias for a class with module name like
``foo.bar.BazClass``
* #3257: autosummary: Support instance attributes for classes
* #9129: html search: Show search summaries when html_copy_source = False
* #9120: html theme: Eliminate prompt characters of code-block from copyable
text
* #9097: Optimize the paralell build
* #9131: Add :confval:`nitpick_ignore_regex` to ignore nitpicky warnings using
regular expressions


Bugs fixed
Expand Down
14 changes: 14 additions & 0 deletions doc/usage/configuration.rst
Expand Up @@ -419,6 +419,20 @@ General configuration

.. versionadded:: 1.1

.. confval:: nitpick_ignore_regex

An extended version of :confval:`nitpick_ignore`, which instead interprets
the ``type`` and ``target`` strings as regular expressions. Note, that the
regular expression must match the whole string (as if the ``^`` and ``$``
markers were inserted).

For example, ``(r'py:.*', r'foo.*bar\.B.*')`` will ignore nitpicky warnings
for all python entities that start with ``'foo'`` and have ``'bar.B'`` in
them, such as ``('py:const', 'foo_package.bar.BAZ_VALUE')`` or
``('py:class', 'food.bar.Barman')``.

.. versionadded:: 4.1

.. confval:: numfig

If true, figures, tables and code-blocks are automatically numbered if they
Expand Down
3 changes: 1 addition & 2 deletions setup.py
Expand Up @@ -21,8 +21,7 @@
'sphinxcontrib-htmlhelp',
'sphinxcontrib-serializinghtml',
'sphinxcontrib-qthelp',
'Jinja2>=2.3,<3.0',
'MarkupSafe<2.0',
'Jinja2>=2.3',
'Pygments>=2.0',
'docutils>=0.14,<0.18',
'snowballstemmer>=1.1',
Expand Down
3 changes: 2 additions & 1 deletion sphinx/config.py
Expand Up @@ -131,6 +131,7 @@ class Config:
'manpages_url': (None, 'env', []),
'nitpicky': (False, None, []),
'nitpick_ignore': ([], None, []),
'nitpick_ignore_regex': ([], None, []),
'numfig': (False, 'env', []),
'numfig_secnum_depth': (1, 'env', []),
'numfig_format': ({}, 'env', []), # will be initialized in init_numfig_format()
Expand Down Expand Up @@ -309,7 +310,7 @@ def __setstate__(self, state: Dict) -> None:
self.__dict__.update(state)


def eval_config_file(filename: str, tags: Tags) -> Dict[str, Any]:
def eval_config_file(filename: str, tags: Optional[Tags]) -> Dict[str, Any]:
"""Evaluate a config file."""
namespace: Dict[str, Any] = {}
namespace['__file__'] = filename
Expand Down
4 changes: 2 additions & 2 deletions sphinx/environment/adapters/toctree.py
Expand Up @@ -8,7 +8,7 @@
:license: BSD, see LICENSE for details.
"""

from typing import TYPE_CHECKING, Any, Iterable, List, cast
from typing import TYPE_CHECKING, Any, Iterable, List, Optional, cast

from docutils import nodes
from docutils.nodes import Element, Node
Expand Down Expand Up @@ -48,7 +48,7 @@ def note(self, docname: str, toctreenode: addnodes.toctree) -> None:

def resolve(self, docname: str, builder: "Builder", toctree: addnodes.toctree,
prune: bool = True, maxdepth: int = 0, titles_only: bool = False,
collapse: bool = False, includehidden: bool = False) -> Element:
collapse: bool = False, includehidden: bool = False) -> Optional[Element]:
"""Resolve a *toctree* node into individual bullet lists with titles
as items, returning None (if no containing titles are found) or
a new node.
Expand Down
6 changes: 4 additions & 2 deletions sphinx/ext/autosummary/__init__.py
Expand Up @@ -662,8 +662,10 @@ def import_ivar_by_name(name: str, prefixes: List[str] = [None]) -> Tuple[str, A
name, attr = name.rsplit(".", 1)
real_name, obj, parent, modname = import_by_name(name, prefixes)
qualname = real_name.replace(modname + ".", "")
analyzer = ModuleAnalyzer.for_module(modname)
if (qualname, attr) in analyzer.find_attr_docs():
analyzer = ModuleAnalyzer.for_module(getattr(obj, '__module__', modname))
analyzer.analyze()
# check for presence in `annotations` to include dataclass attributes
if (qualname, attr) in analyzer.attr_docs or (qualname, attr) in analyzer.annotations:
return real_name + "." + attr, INSTANCEATTR, obj, modname
except (ImportError, ValueError, PycodeError):
pass
Expand Down
28 changes: 23 additions & 5 deletions sphinx/ext/autosummary/generate.py
Expand Up @@ -239,15 +239,33 @@ def skip_member(obj: Any, name: str, objtype: str) -> bool:
name, exc, type='autosummary')
return False

def get_members(obj: Any, types: Set[str], include_public: List[str] = [],
imported: bool = True) -> Tuple[List[str], List[str]]:
items: List[str] = []
public: List[str] = []
def get_class_members(obj: Any) -> Dict[str, Any]:
members = sphinx.ext.autodoc.get_class_members(obj, [qualname], safe_getattr)
return {name: member.object for name, member in members.items()}

def get_module_members(obj: Any) -> Dict[str, Any]:
members = {}
for name in dir(obj):
try:
value = safe_getattr(obj, name)
members[name] = safe_getattr(obj, name)
except AttributeError:
continue
return members

def get_all_members(obj: Any) -> Dict[str, Any]:
if doc.objtype == "module":
return get_module_members(obj)
elif doc.objtype == "class":
return get_class_members(obj)
return {}

def get_members(obj: Any, types: Set[str], include_public: List[str] = [],
imported: bool = True) -> Tuple[List[str], List[str]]:
items: List[str] = []
public: List[str] = []

all_members = get_all_members(obj)
for name, value in all_members.items():
documenter = get_documenter(app, value, obj)
if documenter.objtype in types:
# skip imported members if expected
Expand Down
13 changes: 9 additions & 4 deletions sphinx/jinja2glue.py
Expand Up @@ -12,7 +12,7 @@
from pprint import pformat
from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Tuple, Union

from jinja2 import BaseLoader, FileSystemLoader, TemplateNotFound, contextfunction
from jinja2 import BaseLoader, FileSystemLoader, TemplateNotFound
from jinja2.environment import Environment
from jinja2.sandbox import SandboxedEnvironment
from jinja2.utils import open_if_exists
Expand All @@ -22,6 +22,11 @@
from sphinx.util import logging
from sphinx.util.osutil import mtimes_of_files

try:
from jinja2.utils import pass_context # type: ignore # jinja2-3.0 or above
except ImportError:
from jinja2 import contextfunction as pass_context

if TYPE_CHECKING:
from sphinx.builders import Builder

Expand Down Expand Up @@ -101,7 +106,7 @@ def __next__(self) -> int:
next = __next__ # Python 2/Jinja compatibility


@contextfunction
@pass_context
def warning(context: Dict, message: str, *args: Any, **kwargs: Any) -> str:
if 'pagename' in context:
filename = context.get('pagename') + context.get('file_suffix', '')
Expand Down Expand Up @@ -180,9 +185,9 @@ def init(self, builder: "Builder", theme: Theme = None, dirs: List[str] = None)
self.environment.filters['toint'] = _toint
self.environment.filters['todim'] = _todim
self.environment.filters['slice_index'] = _slice_index
self.environment.globals['debug'] = contextfunction(pformat)
self.environment.globals['debug'] = pass_context(pformat)
self.environment.globals['warning'] = warning
self.environment.globals['accesskey'] = contextfunction(accesskey)
self.environment.globals['accesskey'] = pass_context(accesskey)
self.environment.globals['idgen'] = idgen
if use_i18n:
self.environment.install_gettext_translations(builder.app.translator)
Expand Down
4 changes: 2 additions & 2 deletions sphinx/project.py
Expand Up @@ -10,7 +10,7 @@

import os
from glob import glob
from typing import Dict, List, Set
from typing import Dict, List, Optional, Set

from sphinx.locale import __
from sphinx.util import get_matching_files, logging, path_stabilize
Expand Down Expand Up @@ -60,7 +60,7 @@ def discover(self, exclude_paths: List[str] = []) -> Set[str]:

return self.docnames

def path2doc(self, filename: str) -> str:
def path2doc(self, filename: str) -> Optional[str]:
"""Return the docname for the filename if the file is document.
*filename* should be absolute or relative to the source directory.
Expand Down
6 changes: 3 additions & 3 deletions sphinx/transforms/__init__.py
Expand Up @@ -10,7 +10,7 @@

import re
import warnings
from typing import TYPE_CHECKING, Any, Dict, Generator, List, Tuple
from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Tuple

from docutils import nodes
from docutils.nodes import Element, Node, Text
Expand Down Expand Up @@ -72,8 +72,8 @@ class SphinxTransformer(Transformer):
A transformer for Sphinx.
"""

document: nodes.document = None
env: "BuildEnvironment" = None
document: nodes.document
env: Optional["BuildEnvironment"] = None

def set_environment(self, env: "BuildEnvironment") -> None:
self.env = env
Expand Down
16 changes: 15 additions & 1 deletion sphinx/transforms/post_transforms/__init__.py
Expand Up @@ -8,6 +8,7 @@
:license: BSD, see LICENSE for details.
"""

import re
from typing import Any, Dict, List, Optional, Tuple, Type, cast

from docutils import nodes
Expand Down Expand Up @@ -171,14 +172,27 @@ def warn_missing_reference(self, refdoc: str, typ: str, target: str,
warn = node.get('refwarn')
if self.config.nitpicky:
warn = True
dtype = '%s:%s' % (domain.name, typ) if domain else typ
if self.config.nitpick_ignore:
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
if (not domain or domain.name == 'std') and \
(typ, target) in self.config.nitpick_ignore:
warn = False
if self.config.nitpick_ignore_regex:
def matches_ignore(entry_type: str, entry_target: str) -> bool:
for ignore_type, ignore_target in self.config.nitpick_ignore_regex:
if re.fullmatch(ignore_type, entry_type) and \
re.fullmatch(ignore_target, entry_target):
return True
return False
if matches_ignore(dtype, target):
warn = False
# for "std" types also try without domain name
if (not domain or domain.name == 'std') and \
matches_ignore(typ, target):
warn = False
if not warn:
return

Expand Down
2 changes: 1 addition & 1 deletion sphinx/util/docfields.py
Expand Up @@ -209,7 +209,7 @@ class DocFieldTransformer:
Transforms field lists in "doc field" syntax into better-looking
equivalents, using the field type definitions given on a domain.
"""
typemap: Dict[str, Tuple[Field, bool]] = None
typemap: Dict[str, Tuple[Field, bool]]

def __init__(self, directive: "ObjectDescription") -> None:
self.directive = directive
Expand Down
8 changes: 4 additions & 4 deletions sphinx/util/docutils.py
Expand Up @@ -176,8 +176,8 @@ class sphinx_domains:
"""
def __init__(self, env: "BuildEnvironment") -> None:
self.env = env
self.directive_func: Callable = None
self.roles_func: Callable = None
self.directive_func: Callable = lambda *args: (None, [])
self.roles_func: Callable = lambda *args: (None, [])

def __enter__(self) -> None:
self.enable()
Expand Down Expand Up @@ -372,7 +372,7 @@ def __call__(self, name: str, rawtext: str, text: str, lineno: int,
if name:
self.name = name.lower()
else:
self.name = self.env.temp_data.get('default_role')
self.name = self.env.temp_data.get('default_role', '')
if not self.name:
self.name = self.env.config.default_role
if not self.name:
Expand Down Expand Up @@ -491,7 +491,7 @@ def dispatch_departure(self, node: Node) -> None:

# cache a vanilla instance of nodes.document
# Used in new_document() function
__document_cache__: nodes.document = None
__document_cache__: Optional[nodes.document] = None


def new_document(source_path: str, settings: Any = None) -> nodes.document:
Expand Down
4 changes: 2 additions & 2 deletions sphinx/util/logging.py
Expand Up @@ -320,8 +320,8 @@ def prefixed_warnings(prefix: str) -> Generator[None, None, None]:
prefix_filter.prefix = previous
else:
# not prefixed yet
prefix_filter = MessagePrefixFilter(prefix)
try:
prefix_filter = MessagePrefixFilter(prefix)
warning_handler.addFilter(prefix_filter)
yield
finally:
Expand Down Expand Up @@ -472,7 +472,7 @@ class SphinxLogRecordTranslator(logging.Filter):
* Make a instance of SphinxLogRecord
* docname to path if location given
"""
LogRecordClass: Type[logging.LogRecord] = None
LogRecordClass: Type[logging.LogRecord]

def __init__(self, app: "Sphinx") -> None:
self.app = app
Expand Down

0 comments on commit 26f1e2d

Please sign in to comment.