Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sphinx-doc/sphinx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames <50501825+Gobot1234@users.noreply.github.com>2021-08-02 02:32:14 +0300
committerGitHub <noreply@github.com>2021-08-02 02:32:14 +0300
commit596ad5523de2caa5b83a16bd61f99fca1a8d65b0 (patch)
tree64cdb8a61050af0f18f3c36d551f2ccc8533b3b2 /sphinx/util
parent423b10a84843a629b96b6893a08819a1e07927af (diff)
parentd788e78a5e2f339cc5e5c5fd5d8431e1991e568f (diff)
Merge branch '4.x' into 4.x
Diffstat (limited to 'sphinx/util')
-rw-r--r--sphinx/util/__init__.py4
-rw-r--r--sphinx/util/cfamily.py2
-rw-r--r--sphinx/util/console.py2
-rw-r--r--sphinx/util/docutils.py8
-rw-r--r--sphinx/util/inspect.py26
-rw-r--r--sphinx/util/inventory.py2
-rw-r--r--sphinx/util/logging.py16
-rw-r--r--sphinx/util/matching.py6
-rw-r--r--sphinx/util/nodes.py10
-rw-r--r--sphinx/util/typing.py27
10 files changed, 65 insertions, 38 deletions
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index 99ed8dca7..384925157 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -59,7 +59,7 @@ def docname_join(basedocname: str, docname: str) -> str:
def path_stabilize(filepath: str) -> str:
- "normalize path separater and unicode string"
+ "Normalize path separator and unicode string"
newpath = filepath.replace(os.path.sep, SEP)
return unicodedata.normalize('NFC', newpath)
@@ -435,7 +435,7 @@ def split_full_qualified_name(name: str) -> Tuple[Optional[str], str]:
A "full" qualified name means a string containing both module name and
qualified name.
- .. note:: This function imports module actually to check the exisitence.
+ .. note:: This function actually imports the module to check its existence.
Therefore you need to mock 3rd party modules if needed before
calling this function.
"""
diff --git a/sphinx/util/cfamily.py b/sphinx/util/cfamily.py
index 8d0896624..3aa22c625 100644
--- a/sphinx/util/cfamily.py
+++ b/sphinx/util/cfamily.py
@@ -216,7 +216,7 @@ class DefinitionError(Exception):
class BaseParser:
def __init__(self, definition: str, *,
- location: Union[nodes.Node, Tuple[str, int]],
+ location: Union[nodes.Node, Tuple[str, int], str],
config: "Config") -> None:
self.definition = definition.strip()
self.location = location # for warnings
diff --git a/sphinx/util/console.py b/sphinx/util/console.py
index 0c8008371..0fb6cc672 100644
--- a/sphinx/util/console.py
+++ b/sphinx/util/console.py
@@ -25,7 +25,7 @@ codes: Dict[str, str] = {}
def terminal_safe(s: str) -> str:
- """safely encode a string for printing to the terminal."""
+ """Safely encode a string for printing to the terminal."""
return s.encode('ascii', 'backslashreplace').decode('ascii')
diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py
index c2e12e152..5a2732027 100644
--- a/sphinx/util/docutils.py
+++ b/sphinx/util/docutils.py
@@ -339,6 +339,10 @@ class SphinxDirective(Directive):
"""Set source and line number to the node."""
node.source, node.line = self.get_source_info()
+ def get_location(self) -> str:
+ """Get current location info for logging."""
+ return ':'.join(str(s) for s in self.get_source_info())
+
class SphinxRole:
"""A base class for Sphinx roles.
@@ -401,6 +405,10 @@ class SphinxRole:
def set_source_info(self, node: Node, lineno: int = None) -> None:
node.source, node.line = self.get_source_info(lineno)
+ def get_location(self) -> str:
+ """Get current location info for logging."""
+ return ':'.join(str(s) for s in self.get_source_info())
+
class ReferenceRole(SphinxRole):
"""A base class for reference roles.
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index 23dd9e930..2bb900bd7 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -211,12 +211,15 @@ def getslots(obj: Any) -> Optional[Dict]:
def isNewType(obj: Any) -> bool:
"""Check the if object is a kind of NewType."""
- __module__ = safe_getattr(obj, '__module__', None)
- __qualname__ = safe_getattr(obj, '__qualname__', None)
- if __module__ == 'typing' and __qualname__ == 'NewType.<locals>.new_type':
- return True
+ if sys.version_info >= (3, 10):
+ return isinstance(obj, typing.NewType)
else:
- return False
+ __module__ = safe_getattr(obj, '__module__', None)
+ __qualname__ = safe_getattr(obj, '__qualname__', None)
+ if __module__ == 'typing' and __qualname__ == 'NewType.<locals>.new_type':
+ return True
+ else:
+ return False
def isenumclass(x: Any) -> bool:
@@ -245,12 +248,17 @@ def ispartial(obj: Any) -> bool:
return isinstance(obj, (partial, partialmethod))
-def isclassmethod(obj: Any) -> bool:
+def isclassmethod(obj: Any, cls: Any = None, name: str = None) -> bool:
"""Check if the object is classmethod."""
if isinstance(obj, classmethod):
return True
elif inspect.ismethod(obj) and obj.__self__ is not None and isclass(obj.__self__):
return True
+ elif cls and name:
+ for basecls in getmro(cls):
+ meth = basecls.__dict__.get(name)
+ if meth:
+ return isclassmethod(meth)
return False
@@ -837,6 +845,12 @@ def getdoc(obj: Any, attrgetter: Callable = safe_getattr,
* inherited docstring
* inherited decorated methods
"""
+ if cls and name and isclassmethod(obj, cls, name):
+ for basecls in getmro(cls):
+ meth = basecls.__dict__.get(name)
+ if meth:
+ return getdoc(meth.__func__)
+
doc = attrgetter(obj, '__doc__', None)
if ispartial(obj) and doc == obj.__class__.__doc__:
return getdoc(obj.func)
diff --git a/sphinx/util/inventory.py b/sphinx/util/inventory.py
index f21c27323..a7a68304f 100644
--- a/sphinx/util/inventory.py
+++ b/sphinx/util/inventory.py
@@ -24,7 +24,7 @@ if TYPE_CHECKING:
class InventoryFileReader:
- """A file reader for inventory file.
+ """A file reader for an inventory file.
This reader supports mixture of texts and compressed texts.
"""
diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py
index 494f45ebb..e18d82469 100644
--- a/sphinx/util/logging.py
+++ b/sphinx/util/logging.py
@@ -187,7 +187,7 @@ class MemoryHandler(logging.handlers.BufferingHandler):
@contextmanager
def pending_warnings() -> Generator[logging.Handler, None, None]:
- """Contextmanager to pend logging warnings temporary.
+ """Context manager to postpone logging warnings temporarily.
Similar to :func:`pending_logging`.
"""
@@ -215,7 +215,7 @@ def pending_warnings() -> Generator[logging.Handler, None, None]:
@contextmanager
def suppress_logging() -> Generator[MemoryHandler, None, None]:
- """Contextmanager to suppress logging all logs temporary.
+ """Context manager to suppress logging all logs temporarily.
For example::
@@ -244,7 +244,7 @@ def suppress_logging() -> Generator[MemoryHandler, None, None]:
@contextmanager
def pending_logging() -> Generator[MemoryHandler, None, None]:
- """Contextmanager to pend logging all logs temporary.
+ """Context manager to postpone logging all logs temporarily.
For example::
@@ -264,7 +264,7 @@ def pending_logging() -> Generator[MemoryHandler, None, None]:
@contextmanager
def skip_warningiserror(skip: bool = True) -> Generator[None, None, None]:
- """contextmanager to skip WarningIsErrorFilter for a while."""
+ """Context manager to skip WarningIsErrorFilter temporarily."""
logger = logging.getLogger(NAMESPACE)
if skip is False:
@@ -284,7 +284,7 @@ def skip_warningiserror(skip: bool = True) -> Generator[None, None, None]:
@contextmanager
def prefixed_warnings(prefix: str) -> Generator[None, None, None]:
- """Prepend prefix to all records for a while.
+ """Context manager to prepend prefix to all warning log records temporarily.
For example::
@@ -351,7 +351,7 @@ class InfoFilter(logging.Filter):
def is_suppressed_warning(type: str, subtype: str, suppress_warnings: List[str]) -> bool:
- """Check the warning is suppressed or not."""
+ """Check whether the warning is suppressed or not."""
if type is None:
return False
@@ -434,7 +434,7 @@ class DisableWarningIsErrorFilter(logging.Filter):
class MessagePrefixFilter(logging.Filter):
- """Prepend prefix to all records."""
+ """Prepend prefix to all log records."""
def __init__(self, prefix: str) -> None:
self.prefix = prefix
@@ -555,7 +555,7 @@ class SafeEncodingWriter:
class LastMessagesWriter:
- """Stream writer which memories last 10 messages to save trackback"""
+ """Stream writer storing last 10 messages in memory to save trackback"""
def __init__(self, app: "Sphinx", stream: IO) -> None:
self.app = app
diff --git a/sphinx/util/matching.py b/sphinx/util/matching.py
index f32d682f1..1e7f9883a 100644
--- a/sphinx/util/matching.py
+++ b/sphinx/util/matching.py
@@ -90,14 +90,16 @@ _pat_cache: Dict[str, Pattern] = {}
def patmatch(name: str, pat: str) -> Optional[Match[str]]:
- """Return if name matches pat. Adapted from fnmatch module."""
+ """Return if name matches the regular expression (pattern)
+ ``pat```. Adapted from fnmatch module."""
if pat not in _pat_cache:
_pat_cache[pat] = re.compile(_translate_pattern(pat))
return _pat_cache[pat].match(name)
def patfilter(names: Iterable[str], pat: str) -> List[str]:
- """Return the subset of the list NAMES that match PAT.
+ """Return the subset of the list ``names`` that match
+ the regular expression (pattern) ``pat``.
Adapted from fnmatch module.
"""
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index 36db149b9..7ce0933c6 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -40,8 +40,8 @@ caption_ref_re = explicit_title_re # b/w compat alias
class NodeMatcher:
"""A helper class for Node.traverse().
- It checks that given node is an instance of specified node-classes and it has
- specified node-attributes.
+ It checks that the given node is an instance of the specified node-classes and
+ has the specified node-attributes.
For example, following example searches ``reference`` node having ``refdomain``
and ``reftype`` attributes::
@@ -91,7 +91,7 @@ class NodeMatcher:
def get_full_module_name(node: Node) -> str:
"""
- return full module dotted path like: 'docutils.nodes.paragraph'
+ Return full module dotted path like: 'docutils.nodes.paragraph'
:param nodes.Node node: target node
:return: full module dotted path
@@ -588,7 +588,7 @@ NON_SMARTQUOTABLE_PARENT_NODES = (
def is_smartquotable(node: Node) -> bool:
- """Check the node is smart-quotable or not."""
+ """Check whether the node is smart-quotable or not."""
if isinstance(node.parent, NON_SMARTQUOTABLE_PARENT_NODES):
return False
elif node.parent.get('support_smartquotes', None) is False:
@@ -600,7 +600,7 @@ def is_smartquotable(node: Node) -> bool:
def process_only_nodes(document: Node, tags: "Tags") -> None:
- """Filter ``only`` nodes which does not match *tags*."""
+ """Filter ``only`` nodes which do not match *tags*."""
for node in document.traverse(addnodes.only):
try:
ret = tags.eval_condition(node['expr'])
diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py
index deba6b53d..78feb6492 100644
--- a/sphinx/util/typing.py
+++ b/sphinx/util/typing.py
@@ -33,10 +33,10 @@ else:
ref = _ForwardRef(self.arg)
return ref._eval_type(globalns, localns)
-if sys.version_info > (3, 10):
- from types import Union as types_Union
-else:
- types_Union = None
+try:
+ from types import UnionType # type: ignore # python 3.10 or above
+except ImportError:
+ UnionType = None
if False:
# For type annotation
@@ -86,6 +86,9 @@ def get_type_hints(obj: Any, globalns: Dict = None, localns: Dict = None) -> Dic
except NameError:
# Failed to evaluate ForwardRef (maybe TYPE_CHECKING)
return safe_getattr(obj, '__annotations__', {})
+ except AttributeError:
+ # Failed to evaluate ForwardRef (maybe not runtime checkable)
+ return safe_getattr(obj, '__annotations__', {})
except TypeError:
# Invalid object is given. But try to get __annotations__ as a fallback for
# the code using type union operator (PEP 604) in python 3.9 or below.
@@ -114,7 +117,7 @@ def restify(cls: Optional[Type]) -> str:
return ':class:`%s`' % INVALID_BUILTIN_CLASSES[cls]
elif inspect.isNewType(cls):
return ':class:`%s`' % cls.__name__
- elif types_Union and isinstance(cls, types_Union):
+ elif UnionType and isinstance(cls, UnionType):
if len(cls.__args__) > 1 and None in cls.__args__:
args = ' | '.join(restify(a) for a in cls.__args__ if a)
return 'Optional[%s]' % args
@@ -177,17 +180,17 @@ def _restify_py37(cls: Optional[Type]) -> str:
text += r"\ [%s]" % ", ".join(restify(a) for a in cls.__args__)
return text
- elif hasattr(cls, '__qualname__'):
- if cls.__module__ == 'typing':
- return ':class:`~%s.%s`' % (cls.__module__, cls.__qualname__)
- else:
- return ':class:`%s.%s`' % (cls.__module__, cls.__qualname__)
elif hasattr(cls, '_name'):
# SpecialForm
if cls.__module__ == 'typing':
return ':obj:`~%s.%s`' % (cls.__module__, cls._name)
else:
return ':obj:`%s.%s`' % (cls.__module__, cls._name)
+ elif hasattr(cls, '__qualname__'):
+ if cls.__module__ == 'typing':
+ return ':class:`~%s.%s`' % (cls.__module__, cls.__qualname__)
+ else:
+ return ':class:`%s.%s`' % (cls.__module__, cls.__qualname__)
elif isinstance(cls, ForwardRef):
return ':class:`%s`' % cls.__forward_arg__
else:
@@ -315,7 +318,7 @@ def stringify(annotation: Any) -> str:
elif annotation in INVALID_BUILTIN_CLASSES:
return INVALID_BUILTIN_CLASSES[annotation]
elif (getattr(annotation, '__module__', None) == 'builtins' and
- hasattr(annotation, '__qualname__')):
+ getattr(annotation, '__qualname__', None)):
if hasattr(annotation, '__args__'): # PEP 585 generic
return repr(annotation)
else:
@@ -346,7 +349,7 @@ def _stringify_py37(annotation: Any) -> str:
elif hasattr(annotation, '__origin__'):
# instantiated generic provided by a user
qualname = stringify(annotation.__origin__)
- elif types_Union and isinstance(annotation, types_Union): # types.Union (for py3.10+)
+ elif UnionType and isinstance(annotation, UnionType): # types.Union (for py3.10+)
qualname = 'types.Union'
else:
# we weren't able to extract the base type, appending arguments would